系列文章:
《缓存与数据库双写不一致》
《redis主从不一致问题》

在聊数据库与缓存一致性问题之前,先聊聊数据库主库与从库的一致性问题。

1. 概述

一致性问题是分布式常见问题,还可以再分为最终一致性和强一致性。

  • 强一致性:在任何时刻所有的用户或者进程查询到的都是最近一次成功更新的数据。强一致性是程度最高一致性要求,也是最难实现的。关系型数据库更新操作就是这个案例。

  • 最终一致性:和强一致性相对,在某一时刻用户或者进程查询到的数据可能都不同,但是最终成功更新的数据都会被所有用户或者进程查询到。当前主流的nosql数据库都是采用这种一致性策略。

redis存在的一致性问题:双写不一致和主从不一致,本篇文章主要讲主从不一致。

1. 常见的数据库集群架构如何?

答:一主多从,主从同步,读写分离。
在这里插入图片描述

如上图:

(1)一个主库提供写服务
(2)多个从库提供读服务,可以增加从库提升读性能
(3)主从之间同步数据

画外音:任何方案不要忘了本心,加从库的本心,是提升读性能。

2. 为什么主从会出现不一致?

2.1 延迟

答:主从同步有时延,这个时延期间读从库,可能读到不一致的数据。

在这里插入图片描述
如上图:

(1)服务发起了一个写请求
(2)服务又发起了一个读请求,此时同步未完成,读到一个不一致的脏数据
(3)数据库主从同步最后才完成
画外音:任何数据冗余,必将引发一致性问题。

2.2 宕机

我们知道Redis Setnx(SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定的值。特点是先加锁成功后,后续的加锁命令会失败,一般用来做分布式锁,但是在系统宕机时,会存在问题。

以Redission分布式锁为例,就是如果你对某个redis master实例,写入了myLock这种锁key的value,此时会异步复制给对应的master slave实例。

假设客户端1对master写了一条锁数据,正往slave实例同步,尚未完成,但是这个过程中一旦发生redis master宕机,主备切换,redis slave变为了redis master。

接着就会导致,客户端2来尝试加锁的时候,在新的redis master上完成了加锁,而客户端1也以为自己成功加了锁。此时就会导致多个客户端对一个分布式锁完成了加锁。这时系统在业务上一定会出现问题,导致脏数据的产生。所以这个就是redis cluster,或者是redis master-slave架构的主从异步复制导致的redis分布式锁的最大缺陷:在redis master实例宕机的时候,可能导致多个客户端同时完成加锁。

更详细的内容,可参见 《Redission分布式锁原理(看门狗原理)》

3. 如何避免这种主从延时导致的不一致?

方案一:忽略

任何脱离业务的架构设计都是耍流氓,绝大部分业务,例如:百度搜索,淘宝订单,QQ消息,58帖子都允许短时间不一致。

画外音:如果业务能接受,最推崇此法。

如果业务能够接受,别把系统架构搞得太复杂。

方案二:redlock

redlock也不是完美,也存在一些问题,总体来说用的比较少。

详情可参见《redis分布式锁的安全性探讨(二):分布式锁Redlock


Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐