- 缓存是什么?(what)
- 缓存,是一种存储数据的组件,它的作用是让对数据的请求更快地返回。我们经常会把缓存放在内存中来存储, 所以有人就把内存和缓存画上了等号,这完全是外行人的见解,实际上,凡是位于速度相差较大的两种硬件之间,用于协调两者数据传输速度差异的结构,均可称之为缓存。
- 缓存就是为了弥补存储系统在这些复杂业务场景下的不足,其基本原理是将可能重复使用的数据放到内存中,一次生成、多次使用,避免每次使用都去访问存储系统。
- 缓存作为一种常见的空间换时间的性能优化手段,在很多地方都有应用,
- 为什么使用缓存?(why)
- 缓存经常读取的数据在内存中,能够提升性能,大大加快访问速度,例如微博、微信等系统
- 需要经过复杂运算的数据,可以提前计算好加载到缓存中,例如在线用户数
- 在哪里使用缓存 ?(where)
- 这里说一下缓存的分类,分为静态缓存、热点本地缓存、分布式缓存
- 图片,js、css文件,和一些静态httml可以做静态缓存
- 极端热点数据或者缓存内容比较少是可以使用单机缓存,例如
ehcache
组件、HashMap,Guava Cache ,不需要跨网络,速度极快,缺点单机容量有限 - 分布式环境一般使用外部缓存,
redis
或memcahced
- 缓存的不足
- 缓存比较适合读多写少的场景,并且数据最好带有一定的热点属性,
- 缓存会给系统带来一定的复杂性,并会有数据不一致的风险,要根据实际情况使用
- 缓存通常使用内存作为存储介质,但是内存并不是无限的
- 缓存会给运维也带来一定的成本
- 缓存的几个问题
- 缓存穿透
- 一般有两种情况,一个是存在数据不存在,
- 如果数据确实不存在,一般业务不会大量读取这一类数据
- 如果被黑客攻击,可以简单设置个null或者默认值,第二次就会直接走缓存了,可以是一个固定+随机过期时间
- 二是缓存生成需要你耗费大量时间或者资源
- 如果业务系统访问时正好失效了,就会花费大量时间,拖累数据库,
- 例如商品分页数据,一般比较大,用户一般范文前几页,我们一般设置1天过期时间,第10页缓存过期概率比较大,如果有爬虫访问,就会导致重新生成缓存,导致拖慢数据库,一般没有太好的办法,可以监控后禁止,识别爬虫然后禁止访问
- 缓存雪崩
- 一般是当业务系统缓存失效过期后需要重新生成缓存的过程中需要耗时几百ms,这时候有大量的请求穿透缓存来到db,每个线程看不到其他线程缓存,会重新生成缓存,对db造成巨大的压力,
- 解决方案
- 更新锁:对缓存的更新进行加锁操作,确保只有一个线程能够更新缓存,为获取到锁的线程等待或者直接返回默认值,
- 后台更新机制:
- 由后台系统定时,更新缓存,不是业务系统,缓存本身有效期甚至为永久
- 解决当内存不够,会剔除一些数据,可以使用消息队列发送一条消息通知后台系统更新缓存,更新前判断缓存是否存在,
- 后台更新还可以进行缓存预热
- 缓存热点
- 对于一份缓存,如果是热点数据,经常访问,可能单机承受不来太高的qps,可以利用副本和片机制,,把同一份数据变成多个副本,放在不同的机器上,利用key+编号区分,访问时随机访问一个,要注意key不能设置统一个过期时间,否则缓存同时失效会引发上文雪崩问题
- 至于怎么保证缓存中有500M数据都是热点数据,可以利用lru机制实现,具体方案:二、如何使redis中存放的都是热点数据?