一、缓存穿透
在项目中使用缓存通常都是APP先检查缓存中是否命中,如果命中直接返回缓存内容;如果不命中就直接查询数据库然后回写缓存并返回结果。此时如果查询某个数据在缓存中一直不存在,就会造成每一次请求都查询DB,这样缓存就失去了意义,在流量大时,DB可能就会挂掉。如果碰到这样的问题可以在封装的缓存SET和GET部分增加个步骤,如果查询一个KEY不存在,就以这个KEY为前缀设定一个标识KEY;以后再查询该KEY的时候,先查询标识KEY,如果标识KEY存在,就返回一个协定好的非FALSH或者NULL值,然后APP做相应的处理,这样缓存层就不会被穿透。当然这个验证KEY的失效时间不能太长。
二、缓存并发
有时候如果网站并发访问高,一个缓存如果失效,可能出现多个进程同时查询DB,同时回写缓存的情况;如果并发确实很大,可能造成DB压力过大,还有缓存频繁更新的问题。我现在的想法是再APP中对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询。
三、缓存失效
引起这个问题的主要原因还是高并发的时候,平时我们设定一个缓存的过期时间时,可能有一些会设置5分钟,10分钟等;并发很高时可能会出在某一个时间同时生成了很多的缓存,并且过期时间都一样,这个时候就可能引发一当过期时间到后,这些缓存同时失效,请求全部转发到DB,DB可能会压力过重。一个简单方案就是将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。