首页 > 数据库 >redis 如何保证数据一致性

redis 如何保证数据一致性

时间:2023-08-02 10:22:28浏览次数:54  
标签:缓存 删除 数据 数据库 redis 更新 线程 一致性 保证数据

引言

日常开发中常会使用redis作为项目中的缓存,只要我们使用 Redis 缓存,就必然会面对缓存和数据库间的一致性保证问题。而且如果数据不一致,那么应用从缓存中读取的数据就不是最新数据,可能会导致严重的业务问题。

为什么会数据不一致

数据一致性:指的是redis缓存跟数据库的数据的一致。假如缓存中没有数据,那么数据库的值必须是最新的。如果缓存中有数据,那么缓存中的值需要跟数据库的值相同。

理解完上述数据一致性的前提,我们看下什么情况下会导致缓存跟数据库的数据不一致。

  • 并发更新问题:当多个客户端同时对同一个数据进行更新时,假设有两个客户端同时读取了数据库中的数据,然后对其进行了修改,并分别将修改后的数据存入缓存。因为两个客户端并不知道对方的修改,所以会导致缓存中存储的数据和数据库中的数据不一致。
  • 异常情况:在更新缓存的过程中,如果发生了错误或者异常,可能导致缓存更新失败,从而导致缓存和数据库数据不一致,大致分为如下两种场景。
场景 问题
先删除缓存,再更新数据库 先删除缓存值, 数据库更新失败,导致请求再次访问缓存时,发现缓存缺失,再读数据库时,从数据库中读到旧值
先更新数据库,再删除缓存 缓存删除失败,导致请求再次访问缓存时,发现缓存命中,并从缓存中读取到旧值

如何解决数据不一致的问题

重试机制

无论是先操作缓存,还是先操作数据库,假如后者执行失败,我们可以发起重试,尽可能地去做「补偿」。我们可以把要更新/删除的值暂存到消息队列中,当应用没有能够成功地更新/删除数据库值时,可以从消息队列中重新读取这些值,然后再次进行删除或者更新。

这种做法引入消息队列,可能会增加更多的维护成本。如果重试超过的一定次数还是失败,需要向业务层发送报错信息。

注意:即使这两个操作执行时都没有失败,但是当有大量并发请求时,应用还是可能会读到不一致的数据。还是分以下两种情况讨论!

先更新数据库,再删除缓存

假设线程 A 删除了数据库中的值,但还没来得及删除缓存,线程 B 就开始读取数据了,那么此时,线程 B 查询缓存时,就会直接从缓存中读取到旧值。不过这种情况下,如果其他线程并发读缓存的请求不多,那么就不会有很多请求读取到旧值。并且线程 A 一般也会很快删除缓存值,这样其他线程再次读取时,就会发生缓存缺失,然后去数据库中获取最新的值,因此这种情况对业务的影响较小。

先删除缓存,再更新数据库(延迟双删)

我们先删除缓存,然后更新数据库的值,更新完数据库值以后,我们可以让线程先 sleep 一小段时间,再进行一次缓存删除操作

这就是延迟双删,伪代码如下

redis.delKey(K)
db.update(K)
Thread.sleep(T)
redis.delKey(K)

有了sleep 的这段时间,即使有其他缓存从数据库读取到旧的值并重新放到缓存中,我们也能再次删除,保证缓存中会是新的值。至于sleep的这个时间如何确定?以实际业务执行时间为准。

总结

  1. 删除缓存或更新数据库失败导致的数据不一致,我们可以使用重试机制确保操作成功。
  2. 在删除缓存、更新数据库的这两步操作中,有其他线程的并发读导致其他线程读取到旧值,我们可以使用延迟双删方案解决。

标签:缓存,删除,数据,数据库,redis,更新,线程,一致性,保证数据
From: https://www.cnblogs.com/GentleJim/p/17599853.html

相关文章

  • wix 安装vcredist
    <DirectoryId="TARGETDIR"Name="SourceDir"><!--<DirectoryId="ProgramFilesFolder">--><DirectoryId="ProgramFiles64Folder"><DirectoryId="CompanyFolder&quo......
  • SpringBoot + Redis 执行lua脚本
    1、背景有时候,我们需要一次性操作多个Redis命令,但是这样的多个操作不具备原子性,而且Redis的事务也不够强大,不支持事务的回滚,还无法实现命令之间的逻辑关系计算。所以,一般在开发中,我们会利用lua脚本来实现Redis的事务。2、lua脚本Redis中使用lua脚本,我们需要注意......
  • 白话解析:一致性哈希算法 consistent hashing
    在了解一致性哈希算法之前,最好先了解一下缓存中的一个应用场景,了解了这个应用场景之后,再来理解一致性哈希算法,就容易多了,也更能体现出一致性哈希算法的优点,那么,我们先来描述一下这个经典的分布式缓存的应用场景。场景描述假设,我们有三台缓存服务器,用于缓存图片,我们为这三台......
  • Redis基础
    1.Redis入门1.1Redis简介Redis是一个基于内存的key-value结构数据库。Redis是互联网技术领域使用最为广泛的存储中间件。官网:https://redis.io中文网:https://www.redis.net.cn/key-value结构存储:主要特点:基于内存存储,读写性能高适合存储热点数据(热点商品、资讯、新闻......
  • Redis中使用Lua脚本
    一、简介Redis中为什么引入Lua脚本?Redis是高性能的key-value内存数据库,在部分场景下,是对关系数据库的良好补充。Redis提供了非常丰富的指令集,官网上提供了200多个命令。但是某些特定领域,需要扩充若干指令原子性执行时,仅使用原生命令便无法完成。Redis为这样的用户场景提供了lu......
  • 负载均衡算法: 简单轮询算法, 平滑加权轮询, 一致性hash算法, 随机轮询, 加权随机轮询
    直接上干活/***@version1.0.0*@@menu<p>*@date2020/11/1716:28*/publicclassLoadBlance{staticMap<String,Integer>serverWeightMap=newHashMap<>();static{serverWeig......
  • 随机高并发查询结果一致性设计实践
    一、前言物流合约中心是京东物流合同管理的唯一入口。为商家提供合同的创建,盖章等能力,为不同业务条线提供合同的定制,归档,查询等功能。由于各个业务条线众多,为各个业务条线提供高可用查询能力是物流合约中心重中之重。同时计费系统在每个物流单结算时,都需要查询合......
  • 深度长文整理-Redis进阶
    目录一、基础二、为什么Redis是单线程的?三、为什么单线程这么快?四、select、poll、epoll五、Redis的事务六、Redis的监控七、Redis的配置文件八、Redis的持久化8.1、fork()系统调用8.2、RDB8.3、AOF8.4、RDB和AOF的选择九、发布订阅十、主从复制十一、集群搭建及小实验11.1、架构一......
  • ChaosBlade 项目指南:我是如何为社区贡献 Redis 故障场景
    作者:中国移动磐基CMChaos混沌工程团队,晁元宁(@Yuaninga),ReviewerofChaosBlade01Redis新特性介绍1.1背景Redis实际使用过程中会存在一些故障演练需求。例如:模拟触发所有key过期的极端故障场景、模拟主动触发Redis内存淘汰策略释放内存场景等等。所以,根据以上故障演练......
  • 原生php 接入redis 详细步骤
    前言环境:win10php5.4IIS10 一.安装php-redis扩展下载地址:https://windows.php.net/downloads/pecl/releases/redis/注意选择好对应的版本,图中2.2.7指的是redis的版本,后边的5.4指php版本,还有vc9和x86,这些可以在phpinfo当中查到。 下载好之后解压,复制包里的php_redis.d......