首页 > 数据库 >redis数据一致性问题还稀里糊涂?看这篇就够了

redis数据一致性问题还稀里糊涂?看这篇就够了

时间:2022-11-12 11:34:08浏览次数:47  
标签:缓存 删除 redis 数据库 稀里糊涂 线程 一致 一致性 数据

前言

当我们使用Redis做缓存时,数据不一致问题是绕不过的问题。如果我们没有很好的处理数据一致性问题,就有可能影响用户体验,最严重的会造成业务损失。数据一致性的场景和解决方式都有哪些呢?让我们一探究竟。

缓存和数据库的数据不一致发生原因

数据一致性总结就是2种情况:

  • 缓存中有数据,这时缓存的数据和数据库的相同;
  • 缓存中没有数据,这时数据库的值是最新值。

因此,不符合这2种情况的就是数据不一致了。而缓存又包括读写缓存和只读缓存。 发生数据不一致的情况有各自的区别。

读写缓存

对数据增删改操作时,需要在缓存中进行。同时呢还得根据写回策略,看是否要同步写回到数据库。

  • 同步直写策略:写缓存时,并同步写数据库。缓存和数据库的数据一致。
  • 异步写回策略:写缓存时不同步写数据库,而是等数据淘汰触发时,再将数据写回数据库。此情况下,若未触发数据淘汰就出现故障,数据库就没有最新数据,造成数据不一致的问题。

总结一下,采用读写缓存时,要保证数据一致性问题,就要采用同步直写策略。若数据一致性要求不是很高,可采用异步写回策略。

只读缓存

当要新增数据,就直接写到数据库;当数据删除或修改时,修改数据库的值,并将缓存的数据清除。

redis数据一致性问题还稀里糊涂?看这篇就够了_缓存

分析一下数据一致性的问题:

  • 新增数据:数据直接写到数据库,不对缓存操作。此时不存在一致性的问题。
  • 删除和修改数据:这种情况下,既要更新数据库,也要删除缓存。若两个操作保证不了原子性,就会出现数据不一致问题。
只读缓存删改数据的不一致问题
  • 先删除缓存,再更新数据库:若缓存删除成功,数据库更新失败。后面访问就会缓存缺失,然后访问数据库就会查到旧值。(数据库更新失败,这种情况此操作不就失败了吗?不能叫旧值吧?)
  • 先更新数据库,再删除缓存:若更新数据库成功,删除缓存失败。后续访问的就是缓存中的旧值。

redis数据一致性问题还稀里糊涂?看这篇就够了_缓存_02

看上图很好理解这个数据不一致的产生过程:

  1. a旧值=1,客户端要更新a的值为2;
  2. 先更新数据库成功,此时数据库a = 2;
  3. 再删除缓存,但失败了。缓存还在。此时缓存中a = 1, 数据库中a = 2;
  4. 再去查询a的值。因缓存命中,返回a = 1,和数据库不一致。

数据不一致的解决方案

处理方式一:先删除缓存,再更新数据库。(不推荐)

发生数据不一致的场景:

  1. 线程1删除缓存中的a数据后,还没来得及更新数据库。
  2. 此时线程2读取数据a,会发现缓存缺失,然后会去读数据库。

线程2去数据库读取这个动作会带来2个问题:

  • 线程2读取的a是旧值(因为线程1已经改了a的值,只是还没更新到数据库)
  • 线程2在缓存缺失时读了数据库的旧值,这也就算了,它还会将这个旧值回写到缓存中。后续读取a可能都会读到旧值。

这种处理方式很容易造成数据不一致的问题,而且可能会影响后续多个查询操作。很多教程有提供延迟双删的解决方案(线程1更新完数据库后,先sleep一段时间,再进行一次缓存删除操作),这种sleep的方式无法准确预估其他多个线程开始和结束的时间。还是可能会产生数据不一致问题。个人建议别使用这种处理方式。

处理方式二:先更新数据库,再删除缓存。(推荐)

发生数据不一致的场景:

  • 若线程1删除了数据库的值a,但还没来得及删除缓存。
  • 此时线程2读取a数据,就会命中缓存中a的值,这就是读到了旧值。

但此情况若并发读a的线程不多,影响就不大。因为线程1马上就会将缓存中的a删除。后续读取a时就会出现缓存缺失,然后去数据库读a的最新值。对业务的影响较小。

总结

在Redis的缓存和数据库的数据不一致问题上,可分为读写缓存只读缓存来分析。

读写缓存有同步写回策略异步写回策略。采用同步写回能保证数据一致性,若数据一致性要求不是很高,可采用异步写回策略。

只读缓存有2种处理方式:

  • 先删除缓存,再更新数据库(不推荐):并发请求多的时候,容易产生缓存和数据库值不一致的情况。
  • 先更新数据库,再删除缓存(推荐):并发请求多的时候,会存在短暂的数据不一致问题。

标签:缓存,删除,redis,数据库,稀里糊涂,线程,一致,一致性,数据
From: https://blog.51cto.com/u_15773567/5846576

相关文章

  • redis集群搭建
    Redis集群搭建安逸llllll已于2022-09-1312:20:58修改2721收藏9文章标签:redis数据库nosql版权目录Redis集群实现(redis版本6.2.4)1Redis集群1.1为什么要搭建集......
  • Redis的淘汰策略
    默认淘汰策略:满了就出错,不让写了Redis缓存的数据分为两种:设置了过期时间的、全量(也包含没设置过期时间的),这也是淘汰策略针对的两种数据范围lru:最近使用的保留,针对的两种......
  • Redis笔记02-数据类型
    String类型数据127.0.0.1:6379>setnamezhangsan#设置单key-valueOK127.0.0.1:6379>getname"zhangsan"127.0.0.1:6379>msetname1xiaowangname2lisiname3......
  • Redis各个客户端的对比
    【SpringRedisTemplate的底层一开始使用Jedis、但是自从SpringBoot2开始,底层开始使用了Lettuce,故不算在内】         【题外话:如果要使用Spring来集......
  • 腾讯云服务器部署redis
    一、下载安装redis1、使用wgethttp://download.redis.io/releases/redis-5.0.5.tar.gz下载redis2、tar-zxvfredis-5.0.5.tar.gz解压安装包3、进入解压后的文件目录......
  • Redis 简介 1
    虽然Redis已经很火了,相信还是有很多同学对Redis只是有所听闻或者了解并不全面,下面是一个比较系统的Redis介绍,对Redis的特性及各种数据类型及操作进行了介绍。是一个很不错......
  • 8、Redis整合SpringBoot
    1、依赖导入<!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-......
  • 6、Redis_Jedis_测试
    1、Jedis所需要的jar包<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.2.0</version></dependency>2、连接Rdis注意......
  • 5、Redis6三大新数据类型
    1、Bitmaps1、简介现代计算机用二进制(位)作为信息的基础单位,1个字节等于8位,例如“abc”字符串是由3个字节组成,但实际在计算机存储时将其用二进制表示,“abc”分别对应的......
  • Redis事务三大特性
    单独的隔离操作事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断没有隔离级别的概念队列中的命令没有提交之前......