有人说,开源 Redis 的最终一致性曾经能满足大部分利用场景,也有人说,多正本的强统一代价太大,没有必要实现。要笔者说,其实弱一致性曾经不满足很多利用场景的诉求。怎么,不信?请听笔者娓娓道来。
1、不统一带来的困扰
1.1 秒杀变秒崩
分享一个电商秒杀流动中限流器的例子,在电商的秒杀流动中,为了扛住前端对数据库的超大流量冲击,个别应用两种计划来爱护零碎,一个是缓存,另一个则是限流。缓存这个容易实现,只须要在数据库前加一层缓存服务器,而对于限流来说,最简略的能够应用 Redis 的计数器来实现限流性能。
具体来说,假如咱们须要对某个接口限定流量为 5000QPS,即每秒钟拜访的次数不能超过 5000。那么咱们能够这么做:在一开始的时候设置一个计数器 counter 为 5000,并且过期工夫为 1s,即 1s 后计数器生效。每当一个申请过去的时候,counter 的值减 1,判断以后 counter 的值是否等于 0,如果等于,则阐明申请次数过多,间接拒绝请求。如果 counter 计数器不存在,则重置计数器为 5000,开始新一秒的接口限流,留神并发状况下计数器须要加锁。
失常状况下,这种计划不会呈现问题,然而针对这种秒杀流动,不怕一万,就怕万一,万一 Redis 忽然宕机怎么办,那岂不是限流器形同虚设,所有流量全副涌向后端的数据库,霎时零碎解体。此时聪慧的你必定会想到,给 Redis 搞一个备用服务器不就解决了,主服务器如果宕机,备用服务器顶上。没错,这种计划是对的,然而只正确了一半。为什么呢,如下图所示。
当给 Redis 配置从服务器之后,如果主服务器呈现宕机,能够立即切换到从服务器,然而因为开源 Redis 主从服务器之间的数据是异步复制的,如果网络不畅,常常产生主从数据不统一,如果此时主服务器产生宕机,切换到从服务器之后,因为限流器的判断出错,流量压力很容易超出阈值,一下子涌向数据库服务器,同样会造成零碎解体。
认真探索这个问题产生,根因是在于开源 Redis 的一致性机制为弱一致性,在某些工夫内,主从正本数据不统一。而要彻底解决这个问题,只有真正的强统一能力解决。
1.2 难以保护的 MySQL 组件
其实不止 Redis,就连赫赫有名的 MySQL 也逃不过弱统一的坑。MySQL 的部署中,为了保障高可用性,主从热备份是 MySQL 罕用的部署形式。然而如果产生故障时,仅仅靠 MySQL 本身的同步机制,是无奈保障主库和从库之间的数据统一的,于是呈现了重要的辅助组件 MHA(Master High Availability),它的部署形式如下:
MHA 由治理服务和 Node 服务组成,Node 服务部署在每个 MySQL 节点上,MHA 组件负责让 MySQL 的从库尽可能的追平主库,提供主从统一的状态。产生故障进行主从切换时,Manager 首先为从库补充落后的数据,而后再将用户拜访切换到从库,这个过程可能长达数十秒。
MHA 的部署和保护都相当简单,如未能顺利执行故障切换或产生数据失落,运维面临的局面都将很辣手。其实运维同学何尝不心愿手中的零碎稳固运行呢?要是数据库本身能提供强统一保障,何苦再依赖简单的辅助组件!
2、什么是强统一
上一节中笔者介绍了弱统一带来各种问题,接下来这一节具体介绍下什么是强统一。在“分布式系统”和“数据库”这两个畛域中,一致性都是重要概念,但它表白的内容却并不相同。对于分布式系统而言,一致性是在探讨当零碎内的一份逻辑数据存在多个物理的数据正本时,对其执行读写操作会产生什么样的后果,这也合乎 CAP 实践对一致性的表述。而在数据库畛域,“一致性”与事务密切相关,又进一步细化到 ACID 四个方面。因而,当咱们议论分布式数据库的一致性时,本质上是在议论事务一致性和数据一致性两个方面。
2.1 事务一致性
事务的一致性次要是指的事务的 ACID,别离是原子性、一致性、隔离性和持久性,如下图所示:
- 原子性: 事务中的所有变更要么全副产生,要么一个也不产生,通过日志技术实现;
- 一致性 :事务要保持数据的完整性,它是应用程序的属性,依赖原子性和隔离属性来实现;
- 隔离性 :多事务并行执行所失去的后果,与串行执行(一个接一个)完全相同,通过并发控制技术来实现;
- 持久性 :一旦事务提交,它对数据的扭转将被永恒保留,不应受到任何系统故障的影响,通过日志技术实现。
2.2 数据一致性
在分布式系统中,为了防止网络不牢靠带来的问题,通常会存储多个数据正本,逻辑上的一份数据存储在多个物理正本上,天然带来了数据一致性问题。
(1)状态视角
从状态的视角来看,任何变更操作后,数据只有两种状态,所有正本统一或者不统一。在某些条件下,不统一的状态是临时,还会转换到统一的状态,而那些永远不统一的状况简直不会去探讨,所以习惯上大家会把不统一称为“弱统一”。绝对的,统一就叫做“强统一”了。以一个一主两备的 MySQL 集群为例,“强统一”的交互过程如下:
在该模式下,主库与备库同步 binlog 时,主库只有在收到两个备库的胜利响应后,才可能向客户端反馈提交胜利。显然,用户取得响应时,主库和备库的数据正本曾经达成统一,所以后续的读操作必定是没有问题的,这就是状态视角的“强统一”的模型。
然而状态视角的这种强统一副作用很大:第一个是性能很差,主库必须要等备库 1 和备库 2 胜利返回后能力返回;第二个是可用性问题,如果主备节点很多,呈现故障的概率十分高。因而,状态视角的强统一代价十分大,所以很少应用。
(2)操作视角
状态视角的强统一升高了零碎的可用性,因而很多零碎抉择状态视角的弱一致性模型,通过额定的算法(如 Raft、Paxos)在不保障所有节点状态的统一的状况下,来保障操作视角的一致性,同时进步了零碎的可用性。通过退出一些限定条件,衍生出了若干种一致性模型:
- 线性一致性:操作视角实现真正的强统一
- 程序一致性:一致性强度弱于线性一致性
- 因果一致性:一致性强度弱于程序一致性
- 写后读一致性:一致性强度相当,弱于因果一致性
这些一致性模型的介绍参考《高斯 Redis 与强统一》这篇文章。
3、强统一的刚需场景
上一节咱们介绍了什么是强统一,这一节咱们介绍下强统一的典型利用场景。
在常见的互联网利用中,如果数据库服务器只部署在单个节点上,那么应用程序所有的读和写都只会拜访单个节点,一份逻辑数据在物理上也只有一份,这种场景下就谈不上强统一的问题。然而随着零碎中业务访问量的减少,如果是单机部署数据库,就会导致 I / O 拜访频率过高,数据库就会成为零碎的瓶颈。此时,为了升高单机磁盘的 I / O 拜访频率,进步单个机器的 I / O 性能,通常会减少多个数据存储节点,造成一主一从或者一主多重的架构,此时,咱们能够将负载散布在多个从节点上,一方面能够实现读写拆散,写申请拜访主库,读申请拜访备库。另一方面,还能够在主库如果呈现宕机的状况下进行主备切换,加强零碎的稳定性。在以上两个场景中,因为一份逻辑数据在物理上有多个正本,那么如何保障多个正本之间的数据统一呢,这就是强统一须要解决的问题。3.1 读写拆散场景
以关系型数据库 MySQL 为例,典型的部署计划为一主两从三节点计划,主节点负责解决写操作,两个从节解决读操作,分担主库的压力,如下图所示:
此时,如果零碎没有实现强统一,就有可能会遇到执行完写操作后,立即去读,而后发现读不到或者读到旧状态的难堪场景,比方操作程序为以下操作:
- 客户端首先通过代理向主节点 Master 进行了写入操作,此时因为没有实现强统一,写操作写完后立刻返回;
- 紧接着第二步去从节点 Slave A 执行读操作,此时 Master 和 Slave A 之间的同步还未实现,零碎处于非强统一的状态,所以第二步的读操作读取到了旧状态。
能够看出,在一主多备读写拆散的场景下,如果想要保障写入和读取操作的准确无误,零碎实现强统一是十分重要的。
3.2 主备切换场景
主备切换的场景也须要强统一来保障,以目前业内应用最宽泛的内存数据库 Redis 为例,Redis 的主从同步如下图所示:
从上图能够看出,当 Redis 客户端向 Master 服务器发送一条命令时,Master 服务器立刻回复客户端命令的执行后果,并不期待命令同步到从服务器再回复,也就是说 Redis 的主从同步其实是异步的。
因为 Master 节点存在宕机的可能,在这种状况下,如果在 Master 收到命令然而还没同步到 Slave 服务器时产生了宕机,Redis 就会产生主备切换,然而此时 Master 服务器和 Slave 服务器的数据还没有同步,就导致了数据失落的状况。可见,开源 Redis 弱一致性自身的缺点和有余,而要解决这个问题,必须实现强一致性能力解决。
4、高斯 Redis 强统一
因为开源的 Redis 不具备强统一的个性,导致开源 Redis 的利用也受到了诸多限度,为了解决开源 Redis 弱统一的问题,GaussDB(for Redis) 应运而生。GaussDB(for Redis) 是华为云数据库团队自主研发的兼容 Redis 协定的云原生数据库,彻底解决了开源 Redis 一致性问题带来的痛点。
4.1 高斯 Redis 架构
高斯 Redis 的整体架构如下:
相比开源 Redis,高斯 Redis 采纳存算拆散的设计思维,计算层负责计算和协定的解决,聚焦服务。而存储层负责正本治理、扩缩容等解决,聚焦数据自身。高斯 Redis 的劣势如下:
- 数据强统一:存储层应用分布式存储 DFV,轻松实现了 3 正本强统一;
- 超可用:N 个节点的集群最多能够挂掉 N – 1 个节点;
- 低成本:数据采纳磁盘存储并且进行压缩,每 GB 的老本不到开源 Redis 的十分之一;
- 秒扩容:计算层仅需批改路由映射,无需数据搬迁,实现秒级扩容;
- 主动备份:高斯 Redis 能够实现 MVCC 快照备份和定期主动备份。
4.2 高斯 Redis 强统一的实现
开源 Redis 和高斯 Redis 的架构如下图所示:
开源 Redis 或者传统的主从构造如左图所示,如果在读写拆散的场景或者主节点呈现宕机产生主从切换的时候,都会导致数据不统一的状况。
高斯 Redis 采纳存算拆散的架构,如右图所示,在存储层 DFV 的正本治理中采纳分布式共识算法实现了 3 正本的强统一。计算层调用存储层的接口时,如果返回 OK,那么即示意存储层曾经实现正本强统一的复制。
5、结语
咱们在做架构设计的时候,其实很多场景都暗藏着强统一的诉求。如朋友圈这类利用,如果没有实现强统一,朋友圈的评论很容易乱序。再比方限流器的场景,如果没有强统一的保障,也极容易造成数据库的解体。因而,必须在零碎设计之初就意识到强统一的重要性,能力设计出更加稳固和牢靠的零碎。而高斯 Redis 基于存算拆散的架构设计,实现了数据的强统一,为业务的稳固牢靠提供了超强保障。
【重磅举荐】华为云数据库特惠流动
本文由华为云公布