美文网首页
缓存一致性问题的思考

缓存一致性问题的思考

作者: Vayne_God | 来源:发表于2022-03-28 10:55 被阅读0次

1、分布式锁

写请求开始前先加分布式锁,并发读请求进来判断当前读取的数据有没有分布式锁, 如果有分布式锁, 说明有并发写请求, 缓存里的数据 ,可能是无效的, 所以直接去查数据库。 之后的事情就交给mysql的锁机制来解决了, 判断有锁存在的读请求, 是不会更新缓存的,查到数据直接返回。 更新缓存的操作, 交给写请求去完成。写请求更新完数据库后,更新缓存数据,同时释放分布式锁。
这里要注意分布式锁要设置一个过期时间,防止加锁的进程宕机,无法正常释放分布式锁。还有,如果写操作比较耗时,也要考虑过期时间到了,写操作还没完成的情况,推荐用锁续期的方式。我们可以先给锁设置一个超时时间,然后启动一个守护线程,让守护线程在一段时间之后重新去设置这个锁的超时时间,续命锁的实现过程就是写一个守护线程,然后去判断对象锁的情况,快失效的时候,再次进行重新加锁,但是一定要判断锁的对象是同一个,不能乱续。主线程业务执行完了,守护线程也需要销毁,避免资源浪费,使用续命锁的方案相对比较而言更复杂,所以如果业务比较简单,可以根据经验类比,合理的设置锁的超时时间就行。

2、先失效缓存,再更新数据库

有两个并发请求,A为读请求,B为写请求,B先失效掉缓存,A进来后缓存未命中,查询数据库的当前值返回,并更新缓存。B请求更新完数据库后,更新缓存值。
该方案会存在数据一致性问题,因为如果B先更新缓存,A后更新,有可能使得数据库和缓存不一致(A更新的是数据库的旧值)。这种可能性比较小,因为读请求比写请求要快。如果一定要解决这个问题,可以采用以下方法:
延时双删 —— 写请求B更新完数据库之后,sleep一段时间(保证该时间内,读请求A读数据库+更新缓存完成),然后再次删除缓存。当然为了提高并发,可以异步线程去完成该过程。

3、先更新数据库,再失效缓存(极度不建议采用,明显的不一致性)

有两个并发请求,A为读请求,B为写请求,B先更新数据库,未来得及删除缓存,A进来后缓存命中,查询到旧的缓存值,非常明显的数据不一致。
当然,如果并发量不高,或者对数据一致性要求不高的情况下,可以引入消息队列来达到最终一致性。方案有以下几种:
(1)消息队列监听mysql的binlog,生产过期缓存的消息,客户端程序消费消息,执行过期缓存操作。
(2)还是利用binlog,不过不实用消息队列。canal的工作原理:canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议;MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal );canal 解析 binary log 对象(原始为 byte 流)
(3)更新数据库成功后,往消息队列发送消息,消费到消息后再删除缓存,借助消息队列的重试机制来达到最终一致性。

4、Read/Write through

以缓存为操作为主,数据存先存在于缓存,缓存的数据是不会过期的。
Read Through:先查询缓存中数据是否存在,如果存在则直接返回;如果不存在,则由缓存组件负责从数据库中同步加载数据。
Write Through:先查询要写入的数据在缓存中是否已经存在,如果已经存在,则更新缓存中的数据,并且由缓存组件同步更新到数据库中,如果缓存中数据不存在,我们把这种情况叫做Write Miss(写失效)。
Write Miss解决方式:一个是“Write Allocate(按写分配)”,做法是写入缓存相应位置,再由缓存组件同步更新到数据库中。另一个是“No- write allocate(不按写分配)”,做法是不写入缓存中,而是直接更新到数据库中。

适用场景

用于读操作较多,相较于Cache aside而言更适合缓存一致的场景。
使用简单屏蔽了底层数据库的操作,只是操作缓存。
这种方式其实可以以Redis为存储,对数据的持久性要求较低的。

5、Write Back(Write behind)

Write back是相较于Write Through而言的一种异步回写策略。在数据更新时只写入缓存Cache。只在数据被替换出缓存时,被修改的缓存数据才会被写到后端存储。此模式的优点是数据写入速度快,因为不需要写存储;缺点是一旦更新后的数据未被写入存储时出现系统掉电的情况,数据将无法找回。


image.png

问题

实现比较复杂,可能会丢失数据.

适用场景

用于读少写多的场景,Linux系统的页缓存和MySQL InnoDB 引擎的Cache Pool其实就是使用的WriteBack策略.
相较于Write through 而言拥有更高的写入性能.

相关文章

  • java并发编程(一)缓存一致性协议

    多线程环境下存在的问题 缓存一致性问题,指令重拍问题,可见性,有序性, 缓存一致性问题 在多处理器系统中,每个处理...

  • 缓存一致性问题的思考

    1、分布式锁 写请求开始前先加分布式锁,并发读请求进来判断当前读取的数据有没有分布式锁, 如果有分布式锁, 说明有...

  • JMM 内存模型简析

    高速缓存 cpu(CPU寄存器)<---> CPU高速缓存 <---> 主内存RAM 缓存一致性问题:多个处理器的...

  • Java多线程(5)

    Java多线程(5) CPU缓存一致性问题 因为缓存的出现,极大提高了CPU的吞吐能力,但同时也引入了缓存不一致的...

  • 缓存

    通过本文档,你将会了解到 为什么要使用缓存 本地缓存它不香么?为什么要使用redis缓存, 缓存一致性问题,缓存穿...

  • java多线程-3-volatile

    缓存一致性问题 起因:高速缓存 方案总线LOCK#锁,释放锁前该块内存无法被别的cpu或线程访问缓存一致性协议(I...

  • 多线程安全问题:可见性、原子性、有序性

    引言 CPU缓存与内存产生的一致性问题 CPU时间片切换产生的原子性问题 CPU指令编译优化产生的有序性问题 并发...

  • 高并发场景下的缓存有哪些常见的问题?

    一、缓存一致性问题 当数据时效性要求很高时,需要保证缓存中的数据与数据库中的保持一致,而且需要保证缓存节点和副本中...

  • 缓存在高并发场景下的常见问题

    一、缓存一致性问题 当数据时效性要求很高时,需要保证缓存中的数据与数据库中的保持一致,而且需要保证缓存节点和副本中...

  • 高并发场景下的缓存有哪些常见的问题?

    一、缓存一致性问题 当数据时效性要求很高时,需要保证缓存中的数据与数据库中的保持一致,而且需要保证缓存节点和副本中...

网友评论

      本文标题:缓存一致性问题的思考

      本文链接:https://www.haomeiwen.com/subject/ajqbbltx.html