这里分享一下缓存和数据库数据一致性刷新的一些方案和实践。
主要从一下4个方面进行介绍和分享。
数据一致性介绍
- 随着业务发展,数据需要添加副本以提高可行性;
- 为减少db访问压力,需要进行读写分离;
- 为提高接口响应时间,一般会将访问数据进行缓存;
- 当然还有其他形式的数据,如存储与es搜索引擎以满足特定业务场景(此处主要讨论缓存数据一致性);
一些方案
- 使用缓存的一些场景:
- 面向用户的接口请求量大,使用缓存提升性能;
- 数据强一致性场景(如 库存),直接操作数据库,展示类接口使用缓存;
- 方案一:
- 查询接口时无缓存数据进行缓存数据的写入;
- 缓存失效时间使缓存自动失效;
- 数据变动,根据对db从库的监听对缓存进行失效;
- 方案二:
- 查询接口时无缓存则获取缓存;
- 缓存自动失效;
- 数据变动触发缓存数据更新;
遇到的问题和解决
- 问题:从数据库变动发出消息失效缓存,写入缓存时读取其他从库,导致写入脏数据;
- 解决:所有的从库数据变动都去发送触发缓存失效的消息;
- 解决:所有的从库数据变动都去发送触发缓存失效的消息;
- 问题:过期缓存删除存在隐患,无法预知当前是否有线程已持有过期数据正要插入(缓存的读取不是原子操作);如下图:
- 解决:采用如下图的方案:相关说明如下
- 先删除缓存后删除db数据,防止当前网站线程crash引起数据不一致;
- 原子操作前判断缓存是否命中,命中则直接返回,防止热点数据引起的缓存击穿;
- 减小缓存数据的颗粒,减小此处锁的颗粒,降低锁开销,锁持有的时间就是一次数据库访问的时间;
- 解决:采用如下图的方案:相关说明如下
一些思考和总结
- 任何技术方案都需要根据具体的业务场来考虑,比如缓存方案中,数据变动是去时缓存失效还是刷新缓存,就是可以考虑多个方面;
- 缓存多大范围的数据?
- 数据的热点程度?