高性能缓存实践-缓存击穿

目标

缓存击穿

缓存击穿: 某一个热点数据(key),在某一瞬间失效,导致大量的请求访问这一个热点数据,击穿缓存,直接查询数据库。

高性能缓存实践-缓存击穿

解决方法:

热点key永不过期

对于一个非常热点的数据(key),直接设置缓存永久不过期。

引用其他博客的:“我们对主打商品都是早早的做好了准备,让缓存永不过期。即便某些商品自己发酵成了爆款,也是直接设为永不过期就好了。”

优点:方式简单粗暴。

缺点:仅适用于基本不变化的数据。

定时更新或者检查更新

参考 应对缓存击穿的解决方法

定时更新:

后台定义一个job(定时任务)专门主动更新缓存数据.比如,一个缓存中的数据过期时间是30分钟,那么job每隔29分钟定时刷新数据(将从数据库中查到的数据更新到缓存中)。

不足:增加系统复杂度。比较适合那些 key 相对固定,cache 粒度较大的业务,key 比较分散的则不太适合,实现起来也比较复杂。

检查更新:

将缓存key的过期时间(绝对时间)一起保存到缓存中(可以拼接,可以添加新字段,可以采用单独的key保存…不管用什么方式,只要两者建立好关联关系就行).在每次执行get操作后,都将get出来的缓存过期时间与当前系统时间做一个对比,如果缓存过期时间-当前系统时间<=1分钟(自定义的一个值),则主动更新缓存.这样就能保证缓存中的数据始终是最新的(和方案一一样,让数据不过期.)

不足:假如在最后临近的一分钟没有请求来获取缓存数据,有可能导致缓存过期,并没有重新加载。导致接下来的时间,大量请求到来,依然会出现缓存击穿。

互斥锁

使用互斥锁就已经默认会出现,大量请求在同一时间,访问一个失效的热点数据的情况。通过互斥锁,只允许第一个线程获得锁,访问数据库获得数据再设置到缓存中,其他线程等待,从更新的缓存中获得热点数据。

单体应用可以使用(ReentrantLock)来实现互斥锁。分布式系统可以使用分布式锁(Redis setnx)(ZooKeeper) 等。

综上

在阅读一些博客中,也提到了使用 hystrix 来实现资源隔离,还没有研究,等研究了再实践。

大道至简,对于解决方法的选择,不一定越复杂的越好,黑猫白猫逮到高性能缓存实践-缓存击穿就是高性能缓存实践-缓存击穿

高性能缓存实践-缓存击穿