保证缓存和数据库的一致性

如何保证缓存和数据库的一致性


在日常开发中为了提高数据的响应速度,可能会讲一些热点数据保存在缓存中,这样不用每次去数数据中查询了,可用有效提高服务端的响应速度 最常用的缓存就是redis
数据对实时性和精确性要求很高 则直接操作数据库

选中合适的数据存入到redis之后,每当读取数据的时候,就先去redis看有没有,如果有则直接返回 如果没有则取数据库中读取,并且将从数据库中读取到的数据缓存到redis中,

如何做到一致性


Cache-Aside 旁路缓存模式 尽可能地解决缓存与数据库不一致堵塞问题

读缓存


流程是这样的
1 读取数据
2 检查缓存中是否有需要的数据,如果命中(Cache Hit),则直接返回数据
3 如果没有命中缓存,即Cache Miss,那么就去访问数据库
4 将从数据库中读到的数据设置到缓存中
5 返回数据


写缓存 


1 写入
2 更新数据库
3 删除旧缓存


为什么是删除旧缓存而不是更新旧缓存


  删除缓存消耗太大了
 1 更新缓存 缓存的内容(更新缓存不是简单的更新一个Bean,缓存的都是一些复杂匀速那和计算结果),加缓存的必然性(如果不加缓存,不但无法提高并发量,同时也会给MySQL数据库带来巨大的负担),
 结论(对于这样的缓存,更新起来并不容易,删除缓存效果更好)
 2 对于一些写频繁的应用,如果按照(更新缓存-更新数据库)的模式来,比较浪费性能,例如,如果每次都要写缓存,可能写了十次,只读了一次,那么读到的数据只是第十次的,前面的九次都是无效数据,没必要更新
 3 对于更新缓存的方式,在并发环境下,可能会造成数据错误的情况,更新数据库的内容的先后顺序和更新缓存的先后顺序有关,顺序一致则数据一致,因为网络问题,顺序不一致,则数据不一致
 
 

为什么不先删除旧的缓存,然后再更新数据库?


可能出现的场景,有两个线程
A 线程首先删除缓存。
B 线程读取缓存,发现缓存中没有数据。
B 线程读取数据库。
B 线程将从数据库中读取到的数据写入缓存。
A 线程更新数据库。

一套操作下来,我们发现数据库和缓存中的数据不一致了!所以,在 Cache-Aside 中是先更新数据库,再删除缓存。


 延迟双删


 延迟双删是这样:先执行缓存清除操作,再执行数据库更新操作,延迟 N 秒之后再执行一次缓存清除操作,这样就不用担心缓存中的数据和数据库中的数据不一致了。
 如何确保原子性
 保证数据库更新完毕之后,也成功删除了缓存
 一种常见的解决方案就是使用消息中间件来实现删除的重试。大家知道,MQ 一般都自带消费失败重试的机制,当我们要删除缓存的时候,就往 MQ 中扔一条消息,缓存服务读取该消息并尝试删除缓存,删除失败了就会自动重试。


 Read-Through/Write-Through


 Read-Through 


 是一种类似于 Cache-Aside 的缓存方法,区别在于,在 Cache-Aside 中,由应用程序决定去读取缓存还是读取数据库,这样就会导致应用程序中出现了很多业务无关的代码;而在 Read-Through 中,相当于多出来了一个中间层 Cache Middleware,由它去读取缓存或者数据库,应用层的代码得到了简化,


 Write-Through


 在 Write-Through 策略中,所有的写操作都经过 Cache Middleware,每次写入时,Cache Middleware 会将数据存储在 DB 和 Cache 中,这两个操作发生在一个事务中,因此,只有两个都写入成功,一切才会成功。
这种写数据的优势在于,应用程序只与 Cache Middleware 对话,所以它的代码更加干净和简单。


Write Behind


Write-Behind 缓存策略类似于 Write-Through 缓存,应用程序仅与 Cache Middleware 通信,Cache Middleware 会预留一个与应用程序通信的接口。
Write-Behind 与 Write-Through 最大的区别在于,前者是数据首先写入缓存,一段时间后(或通过其他触发器)再将数据写入 Database,并且这里涉及到的写入是一个异步操作。这种方式下,Cache 和 DB 数据的一致性不强,对一致性要求高的系统要谨慎使用,如果有人在数据尚未写入数据源的情况下直接从数据源获取数据,则可能导致获取过期数据,不过对于频繁写入的场景,这个其实非常适用。
将数据写入 DB 可以通过多种方式完成:

一种是收集所有写入操作,然后在某个时间点(例如,当 DB 负载较低时)对数据源进行批量写入。
另一种方法是将写入合并成更小的批次,例如每次收集五个写入操作,然后对数据源进行批量写入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值