高并发下如何保证缓存和数据库的数据一致性?
缓存由于其高性能 , 支持高并发的特性 , 在高并发的项目中不可或缺 。 被大家广泛使用的有Redis , Memcached等 。 本文主要探讨几种常见的缓存的读写模式 , 以及如何来保证缓存和数据库的数据一致性 。
Cache-Aside
Cache-Aside可能是项目中最常见的一种模式 。 它是一种控制逻辑都实现在应用程序中的模式 。 缓存不和数据库直接进行交互 , 而是由应用程序来同时和缓存以及数据库打交道 。 Cache-Aside的名字正体现了这个模式 , Cache在应用的一旁(aside) 。
读数据时
- 程序需要判断缓存中是否已经存在数据 。
- 当缓存中已经存在数据(也就是缓存命中 , cache hit) , 则直接从缓存中返回数据
- 当缓存中不存在数据(也就是缓存未命中 , cache miss) , 则先从数据库里读取数据 , 并且存入缓存 , 然后返回数据
本文插图
写数据时 , 我们可以有以下两种策略:
第一种策略:
- 更新数据库
- 更新缓存
- A写数据库
- B后于A写数据库
- B写缓存
- A写缓存
- 缓存和数据库中的数据不一致 , 缓存中的是脏数据
第二种策略:
- 更新数据库
- 删除缓存中对应的数据
本文插图
那么这种写策略会有线程安全的问题吗?有 , 试想一下有两个线程 , 线程A读 , 线程B写
- A读数据 , 由于未命中那么从数据库中取数据
- B写数据库
- B删除缓存
- A由于网络延迟比较慢 , 将脏数据写入缓存
应用场景
应用于缓存不支持Read-Through/Write-Through的系统 。
优点
- 缓存仅仅保存被请求的数据 , 属于懒加载模式(Lazy Loading) , 和下文的Write-Through模式相比 , 避免了任何数据都被写入缓存造成缓存频繁的更新 。
- 当发生缓存未命中的情况时 , 则会比较慢 , 因为要经过三个步骤:查询缓存 , 从数据库读取 , 写入缓存 。
- 复杂的逻辑都在应用程序中 , 如果实现微服务 , 多个微服务中会有重复的逻辑代码
这种模式中 , 应用程序将缓存作为主要的数据源 , 而数据库对于应用程序是透明的 , 更新数据库和从数据库的读取的任务都交给缓存来代理了 , 所以对于应用程序来说 , 简单很多 。
Read-Through
由缓存配置一个读模块 , 它知道如何将数据库中的数据写入缓存 。 在数据被请求的时候 , 如果未命中 , 则将数据从数据库载入缓存 。
本文插图
Write-Through
缓存配置一个写模块 , 它知道如何将数据写入数据库 。 当应用要写入数据时 , 缓存会先存储数据 , 并调用写模块将数据写入数据库 。
推荐阅读
- 海峡生活汇印度对中国虎视眈眈,我国将如何迎接挑战,英国仍想着事后清算
- JEECG前端Chrome调试小技巧汇总
- 嘴强玩家马小跳如何才能绝地翻盘?萨满:简单,炉石传说:对手场上7个死亡之翼
- 购房置业▲社保未缴满15年如何补救,这4种方式都可以,劝你不要选第4个
- #青春有你第二季#青你2学员问杨天真“火了如何调整心态”,杨天真怒怼:等你火了再说吧
- 程程搞笑该如何废物利用,网友回答笑了,在家找到过期的洗面奶
- 崔元新不输当前5G新机的4款旧旗舰,你如何选择呢?,新一轮降价潮
- 炒米视角对国家没用”,此人如何评价?,王福重博士谈农民:“一身蛮力
- 讲故事的女人是如何对待她们的?说出来你绝对不敢相信,萨达姆俘虏美国女兵后
- 我家的猫叫皮蛋台积电急了,纯国产芯片来了,华为设计,中芯生产你如何评价?,ASML断供失效