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

数据库和缓存一致性问题

1、假设操作都能成功:
写:先更新数据库,后删除缓存
读:先读缓存,如果不存在读数据库,再写缓存

只要操作都成功,大部分时间可以做到缓存一致

除一种情况,2 个线程并发读写数据:

1、缓存中 X 不存在(数据库 X = 1)
2、线程 A 读取数据库,得到旧值(X = 1)
3、线程 B 更新数据库(X = 2)
4、线程 B删除缓存
5、线程 A 将旧值写入缓存(X = 1)
最终 X 的值在缓存中是 1(旧值),在数据库中是 2(新值),发生不一致。

其实概率「很低」,这是因为它必须满足 3 个条件:
1、缓存刚好已失效
2、读请求 + 写请求并发
3、更新数据库 + 删除缓存的时间(步骤 3-4),要比读数据库 + 写缓存时间短(步骤 2 和 5)
仔细想一下,条件 3 发生的概率其实是非常低的。因为写数据库一般会先「加锁」,所以写数据库,通常是要比读数据库的时间更长的。

2、假设有操作失败
程序在执行过程中发生异常,最简单的解决办法:异步重试。
其实就是把重试请求写到「消息队列」中,然后由专门的消费者来重试,直到成功。
或者订阅数据库变更日志,再操作缓存。

在「先更新数据库,再删除缓存」方案下,「读写分离 + 主从库延迟」也会导致缓存和数据库不一致,缓解此问题的方案是「延迟双删」,发送「延迟消息」到队列中,延迟删除缓存,同时也要控制主从库延迟,尽可能降低不一致发生的概率。
但是,这个时间在分布式和高并发场景下,其实是很难评估的。
很多时候,我们都是凭借经验大致估算这个延迟时间,例如延迟 1-5s,只能尽可能地降低不一致的概率。


http://www.kler.cn/a/14196.html

相关文章:

  • 盘点C# 9.0中好用的特性
  • Win7系统USB串口安装驱动出现“系统找不到指定的文件“解决方案
  • 计算机组成原理 指令系统(1)
  • itop-3568开发板驱动学习笔记(22)设备树(一)设备树基础
  • L1-094 剪切粘贴
  • 测试月入30K,Soeasy?测试这一行涨薪机制被我摸透了...
  • 【Android FrameWork(四)】- binder service_manager ServiceManager
  • 【Linux命令行与Shell脚本编程】第五章 理解 Shell 父子关系 后台进程 协程
  • 计算机类大学生竞赛经验分享
  • JavaSE 09 File 类 IO 流 - Part 01
  • 搜索引擎找外贸客户
  • 【产品经理】系统上线自查清单
  • TCP协议的相关特性(续)
  • GDB调试gdb
  • 光照的个人推导过程与GL实现
  • WTI纽约原油CFD是什么?交易技巧有哪些?
  • webpack5搭建react框架-配置优化
  • 入阵曲(C++)(前缀和)
  • 【C++】模板(二)
  • python算法中的字符串算法(详解)