当前位置: 首页 > news >正文

【Redis】Redis缓存与数据库DB数据如何保持同步?

需要让数据库与redis高度保持一致,因为要求时效性比较高。采用的读写锁保证的强一致性。使用Redisson实现读写锁。在读的时候添加共享锁,可以保证读读不互斥、读写互斥。当我们更新数据的时候,添加排他锁。它是读写、读读都互斥,这样就能保证在写数据的同时,是不会让其他线程读数据的,避免了脏数据。这里面需要注意的是,读方法和写方法上需要使用同一把锁才行。

场景:图书馆的公共记事本

假设有一个公共图书馆,规则如下:

  • MySQL数据库 = 图书馆中央书库里唯一的一本master 记事本(唯一正本)。所有重要的记录都记在这里,它绝对正确,但放在库里,查阅起来很慢
  • Redis缓存 = 图书馆大厅公告板。管理员会把master记事本上的热门内容抄录一份贴在这里,大家查阅起来非常快
  • 用户 = 来图书馆的读者。

现在问题来了:如何保证公告板(Redis) 上的内容,永远和中央书库里的master记事本(MySQL) 内容一致?


如果没有锁( naive 双写):混乱的局面

  1. 读者A想要一条数据。他走到公告板前,开始阅读。
  2. 同时,读者B想要更新这条数据。他做了两件事:
    • 他跑去中央书库,修改了master记事本。
    • 然后他走到公告板前,准备把公告板上的旧内容擦掉,改成新的。
  3. 问题发生:就在读者B擦掉了旧内容,但还没写完新内容的那个瞬间!
  4. 读者A正好读完了公告板上旧内容的前半句,抬头一看,发现内容被擦掉了一半(读到了脏数据),或者读到了正在写的一半新一半旧的内容,完全看不懂了。

这就是脏读。在没有保护的情况下,读写同时进行就会导致这种问题。


解决方案:Redisson读写锁 (ReadWriteLock)

图书管理员引入了两把特殊的锁和一套规则:

  1. 共享锁 (Read Lock - 读锁):一把绿色的锁,有很多把一模一样的副本。
  2. 排他锁 (Write Lock - 写锁):一把红色的锁,全世界只有一把。
规则一:读操作(上共享锁)

当有读者(比如读者A)想去公告板读数据时,他必须遵循:

  1. 他先去锁架子上拿一把绿色的共享锁,挂在公告板上。
  2. 如果公告板上已经挂了一把绿色锁:说明还有其他人在读。没关系! 绿色锁允许多人一起读(共享)。读者A可以直接和其他人一起阅读。
  3. 他读完后,会把自己拿的那把绿色锁从公告板上取下放回原处。
规则二:写操作(上排他锁)

当有读者(比如读者B)想更新数据时,他必须遵循:

  1. 他需要做两件事:a. 去中央书库改master记事本。 b. 更新公告板。
  2. 在开始做任何事之前,他必须先去锁架子上拿那把唯一的红色排他锁,挂在公告板上。
  3. 红色锁的霸道规则
    • 如果公告板上已经有绿色锁(有人在读):对不起,读者B必须等着!直到所有读者读完,把他们的绿色锁都拿走为止。红色锁不允许任何其他锁存在。
    • 如果公告板上是空的:读者B成功挂上红色锁。
    • 如果公告板上已经有红色锁:说明其他人在写,读者B也必须等着
  4. 读者B挂上红色锁后,就意味着:“现在我要开始写了,所有人都给我闪开!
    • 这时,任何想来读数据的人(想拿绿色锁)都会被拦住,他们必须等读者B写完。
  5. 读者B完成所有操作(更新书库master本 + 更新公告板)后,把红色锁取下放回原处。

这个过程如何保证强一致性?

我们回到最初的混乱场景,现在看看会怎样:

  1. 读者A想读数据,他成功在公告板上挂了一把绿色共享锁,开始阅读。
  2. 这时,读者B想写数据。他试图去拿红色排他锁
  3. 管理员拦住了他:“对不起,公告板上现在有绿色锁,你不能写,请排队等待。”
  4. 读者A慢悠悠地读完了,然后取下了自己的绿色锁。
  5. 此时公告板空了,管理员告诉读者B:“好了,现在你可以去挂红色锁了。”
  6. 读者B挂上红色锁,这意味着:所有后续的读者(读请求)都被挡住了公告板外
  7. 读者B安全地先更新中央书库,再更新公告板。因为期间绝对没有其他人能来读公告板,所以不会有人读到“擦到一半”的脏数据。
  8. 读者B写完,取下红色锁。
  9. 等待的读者们一拥而上,他们读到的是读者B刚刚写好的最新、最完整、一致的数据

总结一下你那段话的含义:

  • 读写锁:就是那把绿色共享锁红色排他锁
  • 读读不互斥:多个人可以同时拿绿色锁一起读(共享),效率高。
  • 读写、写写互斥:只要有人拿了红色锁,其他所有人(无论是想读的还是想写的)都必须等待。这保证了写的原子性。
  • 同一把锁:读和写必须操作同一个公告板(同一个key) 的锁才有效。你不能给“用户名”的缓存加锁,却去改“用户余额”的数据。
  • 强一致性:通过“写操作阻塞所有读操作”这种稍微牺牲一点性能的方式,换来了数据的绝对准确。

这种方案非常适合对数据准确性要求极高的场景(如商品库存、账户余额),虽然性能不是最高的,但数据是最可靠的。

http://www.dtcms.com/a/393208.html

相关文章:

  • 考研408---C语言复习
  • 批量抓取图片
  • WinDivert学习文档之五-————编程API(十一)
  • 【打印菱形】
  • XC7Z100-2FFG900I Xilinx AMD Zynq-7000 FPGA SoC
  • 成本价的SEO优化服务供应链
  • dock生命周期体验-生到死的命令
  • 软件测试方案-模板一
  • 防火墙WEB方式登录配置【HCL模拟】-学习篇(1)
  • Ceph用户管理与cephFS分布式存储实战
  • AgenticSeek:重新定义AI助手的边界 - 100%本地化智能代理系统深度解析
  • 701. 二叉搜索树中的插入操作
  • Spring AI(六)Tool Calling本地回调方法
  • 《2511系统分析师第二遍阅读总结3》
  • 【Linux】系统部分——线程同步与生产者消费者模型
  • No008:共建产业知识生态——DeepSeek如何助力中小企业数字化转型
  • 3.8 开发环境 - IntelliJ IDEA
  • Paimon系列:IDEA环境读写Paimon表
  • Java进阶教程,全面剖析Java多线程编程,插入线程,笔记10
  • 成品油加油站综合服务智慧监管平台! “智控油站,计量秒核查” + “数治加油,科技防猫腻”
  • C++编程学习(第34天)
  • 【数据结构与算法Trip第5站】动态规划
  • 防抖那些事儿
  • 【办公类-115-01】20250920信息员每周通讯上传之文字稿整理
  • 深入解析HotSpot解释器方法调用机制:从invokevirtual到方法入口
  • 用AI修复失语者的声音:大模型如何帮助渐冻人重新“说话”?
  • 【ICCV 2023】通过学习采样来学习上采样
  • 有效解决舍入误差的方法
  • count down 90 days
  • GEO完全指南 AI时代的内容优化新范式