缓存的一般操作方式
针对热点访问的数据,如果每次都从数据库取数,并发量上来了会增加DB的压力,从而影响其他业务的数据访问。所以缓存应运而生,将这些热点的数据放在内存中,并设置失效时间,在有效的时间内直接返回内存中的数据不再从DB中取数,从而减轻DB的压力。
缓存引入业务的一般逻辑如下:外部传入的key是否存在缓存中,存在则直接返回,不存在则从DB中取数并放入缓存中,再返回。以上逻辑在特殊情况下存在问题。
缓存穿透
针对检测传入的key是否存在缓存中的逻辑,如果外部传入的key一定不存在(即查询一个不存在的数据)会出现缓存穿透问题。攻击者可以拿着这个key不停的访问,进而不停访问DB,DB消耗大量的资源处理无意义的请求,进而影响整个系统。
解决方案:1.对于key做非法的校验,例如,业务中key一定是大于0的或者以xxx开头;2.对于非法的key,既使从DB取的数据为空,也将这个空的结果放入到缓存中。
缓存击穿
针对同一个key,过了失效时间,如果此时系统有千万级的并发同时访问这个key会出现缓存击穿问题。千万级的访问会同时访问DB,瞬间增大DB压力甚至导致DB崩溃,进而影响其他业务。
解决方案:1.同步锁,从DB中取数增加同步锁,这样只有一个请求是访问的DB,其他访问仍然从缓存中取数,但需要设置等待,所以此方式存在性能问题。2.永不过期,业务上判断这个热点数据是否真的永不变更,如果是则不设置失效的事件,如果会变更将变更操作异步处理(即发现缓存即将过期,异步线程访问DB取数(这边还是要设置同步)重新设置缓存)。
缓存雪崩
如果缓存数据的失效时间设置一样,过了失效时间,如果此时系统针对不同key的大量访问会出现缓存雪崩问题。不同key的请求会转到DB,同击穿一样,会在瞬时增加DB的压力。
解决方案:对于不同的key,失效时间设置合理的随机值,降低key失效时间的重复率,进而减少key集体失效的事件发生。