Redis学习笔记-如何解决缓存和数据库的数据不一致

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis学习笔记-如何解决缓存和数据库的数据不一致

只要在业务中使用缓存,就必然会面对缓存和数据库之间的一致性保证问题了,这也是 Redis 缓存应用中的必答题,如果某些业务场景数据不一致,就会导致严重的错误,比如某个商品库存信息在 Redis 中和数据库中不一致,这就会导致用户下单操作出现严重错误,这个是在业务上无法接受的,这篇文章来学习一下 Redis 缓存和数据库不一致。

1.笔记图

2.数据一致性是啥意思?


不符合下面这两种情况就属于缓存和数据库的数据不一致:

  • 缓存中有数据,缓存的数据值需要和数据库中的值相同
  • 缓存中没有数据,数据库中的值必须是最新值

3.写回策略

  • 同步直写:写请求发给缓存的同时,也会发给后端数据库进行处理,等到缓存和数据库都写完数据,才给客户端返回,同步直写策略优先保证数据可靠性,增加了缓存的响应延迟
  • 异步写回:优先提供快速响应,所有写请求都先在缓存中处理,等到这些增改的数据要被从缓存中淘汰出来时,缓存将它们写回后端数据库,使用这种策略时,如果数据还没有写回数据库,就发生了故障,数据库就没有最新的数据了

4.Redis缓存类型

  • 只读缓存:所有的数据写请求,会直接发往后端的数据库,如果 Redis 已经缓存了相应的数据,应用需要把这些缓存的数据删除,当应用再次读取这些数据时,会发生缓存缺失,应用会把这些数据从数据库中读出来,并写到缓存中
  • 读写缓存
  • 读写缓存除了读请求会发送到缓存,写请求也会发送到缓存
  • 在使用读写缓存时,最新的数据在 Redis 中,一旦出现掉电或宕机,内存中的数据可能就会丢失

5.数据不一致情况

  • 如果有数据需要删改时,假设先删除缓存数据成功了,再删改数据库数据失败了,再次访问数据时,缓存中没有数据,就会读到数据库中的旧数据
  • 假设先删改数据库数据成功了,再删除缓存数据失败了,数据库中的值是新值,缓存中的值是旧值,其他并发请求会访问到缓存中的旧值

  • 更新数据库和删除缓存值的过程中,无论这两个操作的执行顺序谁先谁后,只要有一个操作失败了,就会导致客户端读取到旧值

  • 即使删改数据库和删除缓存这两个操作执行时都没有失败,当有大量并发请求时,应用还是有可能读到不一致的数据

6.缓存和数据库数据操作原子性

  • 要想保证缓存和数据库中的数据一致,就要采用同步直写策略,需要同时更新缓存和数据库
  • 如果发生删改操作,应用既要更新数据库,也要在缓存中删除数据。两个操作如果无法保证原子性(要么都完成,要么都没完成),就会出现数据不一致问题了
  • 同步直写策略要在业务应用中使用事务机制,来保证缓存和数据库的更新具有原子性
  • 缓存和数据者要么一起更新,要么都不更新,返回错误信息,进行重试

7.解决数据不一致问题

  • 重试机制

  • 可以把要删除的缓存值或者是要更新的数据库值暂存到消息队列中(如Kafka),当没有成功删除缓存值或者是更新数据库值时,从消息队列中重新读取这些值,再次进行删除或更新
  • 如重试超过一定次数没有成功,就需要向业务层发送报错信息
  • 情况一:先删除缓存,再更新数据库
  • 问题描述

  • 假设线程 A 删除缓存值后,还没有来得及更新数据库(比如说有网络延迟),
    线程 B 就开始读取数据了,线程 B 会发现缓存缺失,就只能去数据库读取

  • 线程 B 读取到了旧值

  • 线程 B 是在缓存缺失的情况下读取的数据库,它还会把旧值写入缓存,这可能会导致其他线程从缓存中读到旧值
  • 解决办法延迟双删
  • 在线程 A 更新完数据库值以后,可以让它 sleep 一小段时间,再进行一次缓存删除操作
  • 加上 sleep 的这段时间,就是为了让线程 B 能够先从数据库读取数据,再把缺失的数据写入缓存,线程 A 再进行删除
  • 线程 A sleep 的时间,就需要大于线程 B 读取数据再写入缓存的时间,这个 sleep 时间需要根据业务统计下线程读数据和写缓存的操作时间,以此为基础来进行估算
  • 伪代码:
redis.delKey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)

  • 情况二:先删除缓存,再更新数据库

  • 问题描述:如线程 A 删除数据库中的值,没来得及删除缓存值,线程 B 就开始读取数据了,线程 B 查询缓存时,发现缓存命中,会读取旧值
  • 解决办法
  • 删除缓存值或更新数据库失败而导致数据不一致,你可以使用重试机制确保删除或更新操作成功
  • 在删除缓存值、更新数据库的这两步操作中,有其他线程的并发读操作,导致其他线程读取到旧值,应对方案是延迟双删

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
19天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
164 85
|
2月前
|
存储 监控 数据处理
flink 向doris 数据库写入数据时出现背压如何排查?
本文介绍了如何确定和解决Flink任务向Doris数据库写入数据时遇到的背压问题。首先通过Flink Web UI和性能指标监控识别背压,然后从Doris数据库性能、网络连接稳定性、Flink任务数据处理逻辑及资源配置等方面排查原因,并通过分析相关日志进一步定位问题。
203 61
|
8天前
|
SQL 存储 运维
从建模到运维:联犀如何完美融入时序数据库 TDengine 实现物联网数据流畅管理
本篇文章是“2024,我想和 TDengine 谈谈”征文活动的三等奖作品。文章从一个具体的业务场景出发,分析了企业在面对海量时序数据时的挑战,并提出了利用 TDengine 高效处理和存储数据的方法,帮助企业解决在数据采集、存储、分析等方面的痛点。通过这篇文章,作者不仅展示了自己对数据处理技术的理解,还进一步阐释了时序数据库在行业中的潜力与应用价值,为读者提供了很多实际的操作思路和技术选型的参考。
21 1
|
12天前
|
存储 Java easyexcel
招行面试:100万级别数据的Excel,如何秒级导入到数据库?
本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。
|
15天前
|
前端开发 JavaScript 数据库
获取数据库中字段的数据作为下拉框选项
获取数据库中字段的数据作为下拉框选项
46 5
|
16天前
|
缓存 NoSQL Redis
Redis经典问题:数据并发竞争
数据并发竞争是大流量系统(如火车票系统、微博平台)中常见的问题,可能导致用户体验下降甚至系统崩溃。本文介绍了两种解决方案:1) 加写回操作加互斥锁,查询失败快速返回默认值;2) 保持多个缓存备份,减少并发竞争概率。通过实践案例展示,成功提高了系统的稳定性和性能。
|
16天前
|
缓存 监控 NoSQL
Redis经典问题:数据不一致
在使用Redis时,缓存与数据库数据不一致会导致应用异常。主要原因包括缓存更新失败、Rehash异常等。解决方案有:重试机制、缩短缓存时间、优化写入策略、建立监控报警、定期验证一致性、采用缓存分层及数据回滚恢复机制。这些措施可确保数据最终一致性,提升应用稳定性和性能。
|
16天前
|
缓存 监控 NoSQL
Redis经典问题:缓存穿透
本文详细探讨了分布式系统和缓存应用中的经典问题——缓存穿透。缓存穿透是指用户请求的数据在缓存和数据库中都不存在,导致大量请求直接落到数据库上,可能引发数据库崩溃或性能下降。文章介绍了几种有效的解决方案,包括接口层增加校验、缓存空值、使用布隆过滤器、优化数据库查询以及加强监控报警机制。通过这些方法,可以有效缓解缓存穿透对系统的影响,提升系统的稳定性和性能。
|
2月前
|
关系型数据库 MySQL 数据库
GBase 数据库如何像MYSQL一样存放多行数据
GBase 数据库如何像MYSQL一样存放多行数据
|
2月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
46 5