常见的缓存方面的问题有:缓存雪崩、缓存穿透、缓存击穿。
即大量的key在某个时刻,一起失效了(很可能这些key是同时导入的,并且加了相差无几的失效时间),这时大量访问直接奔数据库去了,导致数据库挂掉。
击穿一般形容尖利的东西,从某一点穿过。缓存击穿也是一样,指某个key迎来了大量请求,然而这个key失效了,导致所有访问直接奔数据库去了,导致数据库挂掉。
穿透可以理解为面粉穿过筛子,非常多的点。缓存穿透就是指,大量key迎来了大量请求,并且这些key都不存在,导致所有访问直接奔数据库去了,导致数据库挂掉。
雪崩和穿透的区别在于:虽然都是海量key,但雪崩的key是失效了,而穿透的key根本不存在。
击穿和穿透的区别在于:击穿的key只有一个或很少,穿透的key有海量。
处理的办法也比较简单:
加入key的时候,失效时间加上一个随机数,随机数分布越大,雪崩概率越低。使用集群,可以将数据分布到不同的物理机器上。如果这种大量导入的key具有一定规律,比如每天早上2点导入,那么失效时间大于24小时即可。双备份,两个缓存互相备份。击穿的处理方式就是:
保证热点key不失效,或者失效时间巨长。热点多备几个只读节点适当过滤一些不正常的访问限制访问的频率和线程数处理方式:
不存在的key,也保存起来,值就设置一个null,30秒失效,缺点当然就是浪费空间时间。以redis为例子,防止某类id的穿透攻击,就是做个bitmap,直接过滤掉不存在的id。高端的就是布隆过滤器(我也没用过),但是原理也是一样的,先把不存在的key过滤掉。数据库有变化,对缓存的处理一般是删除,而不是更新。
而更新手段比较靠谱的是更新前删除。
考虑到高并发,很可能更新后,还是会存在更新前的缓存,就需要再清一次。
考虑到高高高并发,甚至再更新数据库后,需要稍等几秒,再清一次缓存。