我们都知道,在开发过程中,很多时候都会用到我们的缓存,而缓存的种类也是五花八门的,我们今天来了解的就是关于缓存中的一种,那就是 redis 。
Redisredis是一个key-value存储系统 。
和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型) 。
这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的 。
在此基础上,redis支持各种不同方式的排序 。与memcached一样,为了保证效率,数据都是缓存在内存中 。
区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步 。
今天我们不说这个 Redis 的主从同步,我们来说说我们最常使用 Redis 的时候,会导致的一些问题 。
Redis和 MySQL 如何保持一致说到这个一致性,了不起就得和大家说道说道了,为什么会出现这种情况呢?实际上就是和 Redis 的使用有很大的关系 。
都知道,Redis 是一个 NoSQL 的数据库,而且他还很快,所以很多数据都会从 Mysql 中把数据取出来,然后放到我们的缓存中,然后下次读取数据的时候,从 Redis 中直接去读取,这个时候,我们就会出现问题了 。
什么问题呢?
在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节 。所以,就需要使用redis做一个缓冲操作,让请求先访问到Redis,而不是直接访问MySQL等数据库 。
这个业务场景,主要是解决读数据从Redis缓存,一般都是按照下图的流程来进行业务操作 。
文章插图
读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存Redis和数据库MySQL间的数据一致性问题 。
不管是先写 MySQL数据库,再删除Redis缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况 。
举一个例子:
1.如果删除了缓存 Redis,还没有来得及写库 MySQL,另一个线程就来读取,发现缓存为空,则到数据库中读取数据,写入缓存,此时缓存中为脏数据 。
2.如果先写了库,在删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会出现数据不一致情况 。
因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题 。
其实解决方案也有不是少,今天了不起来给大家分析一下 Redis 和 Mysql 保证数据一致性的实现方案 。
缓存和数据库一致性解决方案延时双删策略延时双删策略步骤如下:
- 1.先删除缓存
- 2.再写数据库
- 3.休眠N毫秒
- 4.再次删除缓存
【Redis 和 Mysql 如何保证数据一致性?】其中,线程1先删除缓存;
线程2读取缓存为null,同步db数据到缓存中;
线程1更新db中的数据;
线程3查询缓存中数据是旧数据;
这样的话,就会出现 Mysql 和 Redis 中的数据不一致,这时候采用延迟双删策略,去保证数据的一致性,
这时候就有人问了,为什么要休眠一段时间,然后再执行呢?
假象一下,如果没有第三步操作时,有很大概率,在两次删除Redis操作执行完毕之后,数据库的数据还没有更新,此时若有请求访问数据,便会出现我们一开始提到的数据不一致的问题 。
为什么还要再次删除缓存呢?
如果我们没有第二次删除操作,此时有请求访问数据,有可能是访问的之前未做修改的 Redis 数据,删除操作执行后,Redis为空,有请求进来时,便会去访问数据库,此时数据库中的数据已是更新后的数据,保证了数据的一致性 。
因为感觉这种延迟双删除可靠性并没有那么高,因为我们并不能保证删除 Redis 成功,也不能保证数据库更新也是成功的,也就是我们所说的原子性,两个组合起来只是在理想情况下 。
比如双删失败我们应该怎么处理呢?
1、设置缓存过期时间从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案 。所有的写操作以数据库为准,只要到达缓存过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存 。
推荐阅读
- MySQL索引,快速记忆法
- Redis有哪些持久化方式?一文带你了解技术存储的魅力!
- 浅析 Redis 中 String 数据类型及其底层编码
- 带你读 MySQL 源码:Where 条件怎么过滤记录?
- |战国 和田玉白玉籽料 龙凤纹 楚式 玉珮
- 宋修|宋修内司玉勒 和田玉白玉籽料 双勾诗文 勒子
- 什么是王者荣耀中的羊群效应?零和博弈到底是什么?
- 跑步教练如何进行饮食和营养摄取?
- 艺术品|?为什么要买非常贵的和田玉艺术品?
- 岫岩玉|和田玉“平替”!盘点那些最像和田玉的天然玉石!