缓存是高并发高性能的利器
在使用缓存时,特别是更新缓存和更新数据库之间的先后顺序,很多人有不同的争议。
策略
先更新数据库,再更新缓存;
先删除缓存,再更新数据库;
先更新数据库,再删除缓存;
第一种方案
存在线程安全问题,同时如果数据更新频繁,读行为还没到,缓存更新频繁存在性能浪费。 同时如果写高并发场景,压力则直接压到了DB上。
第二种方案
该方案仍然存在不一致问题。一个请求进行更新操作,另一个请求进行查询,第一个请求写缓存还没完成,读请求先读db后把缓存更新了,造成旧数据放到缓存了,如果最后没能正确更新,数据有可能永远是脏的。
第三种方案
源自于FB的方案,cache-aside pattern,策略是:
失效:应用从缓存取值,没有得到从数据库获取,成功后放入缓存。
命中:应用从缓存中取数据,得到后返回。
更新:数据落库,成功后,让缓存失效。
简单点说,FB的策略就是先更新DB,再删除缓存。
当然这种方案同样存在并发问题,两个请求,缓存刚失效,一个写一个读,同样读请求会将旧值放入缓存。
但是这种几率极低 ,只有在读操作时间大于写操作时会存在,而数据库特点是读请求速度快于写请求(停下来脑补1分钟)。
当然针对于可能存在的并发问题还是需要处理的,可以采用异步延迟删除策略,保证读取之后进行缓存删除。
如果删除缓存失败了怎么办?
可以采用重试(引入MQ兜底),存在引入MQ的成本。
订阅Binlog,达到双通道保证。
当然如果对于一致性要求较高可以直接开启线程重试,自己开脑洞吧。
我们在解决高并发场景下会引入自研的内存队列,这个队列的缓存是需要维护的,对于单机内存的数据一致性处理远比分布式缓存更复杂,就不展开谈了。
领取专属 10元无门槛券
私享最新 技术干货