欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Redis异地多活原理简介

程序员文章站 2022-03-26 21:37:00
一、异地多活需要了解的知识什么是异地多活简单来说,就是在不同地域建立数据中心,每个数据中心在日常使用中都需要正常接入业务流量,做业务支撑。异地多活的优势主要体现在以下几个方面。单机房系统架构,一旦机房故障,线上业务中断将会带来不可估量的影响。但是对于异地多活架构的系统来说,如下图:其中地域 1 机房故障,甚至地域 2 机房也故障,只要地域 3 的机房是可用的,流量都可以切到地域 3 机房,线上的业务也不会中断。性能的提升举个简单的例子:从北京到上海共 1468 公里,即使是...

一、异地多活需要了解的知识

  1. 什么是异地多活
    简单来说,就是在不同地域建立数据中心,每个数据中心在日常使用中都需要正常接入业务流量,做业务支撑。
  2. 异地多活的优势
    主要体现在以下几个方面。
  • 单机房系统架构,一旦机房故障,线上业务中断将会带来不可估量的影响。但是对于异地多活架构的系统来说,如下图:
    Redis异地多活原理简介
    其中地域 1 机房故障,甚至地域 2 机房也故障,只要地域 3 的机房是可用的,流量都可以切到地域 3 机房,线上的业务也不会中断。

  • 性能的提升

举个简单的例子:从北京到上海共 1468 公里,即使是光速传输,一个来回也需要接近 10ms;实际测试中,延迟大概在 30ms 左右。但是如果有多个数据中心,可供客户端就近访问,那么性能可能提升几个量级

异地多活,也属于分布式架构的系统。也绕不开CAP

C: 一致性(Consistency ),在分布式系统中的所有数据备份,在同一时刻是否同样的值。
A: 可用性( Availability ),在集群中一部分节点故障后, 集群整体是否还能响应客户端的读写请求。
P: 分区容错性( Partition tolerance ),以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在 C 和 A 之间做出选择。

二、原生 Redis 做异地多活所面临的的问题

  • 断点续传能力差

redis 增量重传过程,如下图所示:
Redis异地多活原理简介

从节点链接主节点后,会向主节点发送psync 命令,主节点收到命令后,查找对应的 replid的复制积压缓冲区(backlog),如果所需同步的 offset 大于 server 记录的 offset,增开始增量同步;否则,开始全量同步

4.0 版本: replid 与 offset 持久化在 rdb 中,重启/主备切换后可以续传,但是这些仅仅是减小了全量重传的概率,不能解决全量重传的问题。
由上可知,是否全量重传,需要靠 backlog 来保证,但是 backlog的大小受限且不宜过大。

  • 双活时无法进行全量同步
    众所周知,Redis 是一个单线程的程序,在原生版本全量同步过程中,所有的请求都会阻塞。在可用性要求比价高的系统中,这是无法被容忍的。所以使用原生 redis 在多活系统中,一个数据中心的 redis 集群在全量同步过程中,会造成所以请求阻塞并中断,导致业务调用失败。

  • 无法去环
    一个多活集群,就像一个小型的环形网络,如下图所示。
    Redis异地多活原理简介
    当同步程序从地域 1 集群向地域 2 集群同步set key val命令,地域 2 集群写入同步程序发送过来的命令,接着地域 2 的同步程序又向地域 3 的集群发送当前变更命令;同理,地域 3 的同步程序又向地域 1 的集群同步,以此类推,这个数据变更同步会在多个集群间无限循环下去。

  • 可扩展性差,实现多活架构复杂
    原生 redis,还是可以借助三方组件,通过修改客户端的方式,来实现异地多活。

例子: 快手自研的客户端修改方案 (额。。内部WIKI 就不贴地址了)

实现的基本原理,是在客户端将命令变更发送到 kafka,再由同步程序将变更从 kafka 消费然后写入目标集群,从而实现数据同步。所以,理论上需要对所有的 redis 的客户端做一次封装,维护成本过大,不利于其他未封装客户端的接入;且该架构严重依赖 kafka 消息中间件。

同步方案设计

考虑到 redis 大部分作为纯缓存的应用场景,在设计异地多活时,为了保证缓存的高可用性,防止因校验数据一致带来的性能损耗甚至集群不可用导致缓存击穿,所以我们将 redis 异地版本,设计为优先遵循 AP 原则,既一个地域集群实例故障再恢复时,同一时段内会适当容忍部分数据不一致的情况,但保持最终数据一致性。

  1. 内核层面解决断点续传、双活全量同步、回环

(1) AOF 的特性与优势
特性:
Redis 所有变更操作写入 AOF 文件
AOF 文件都是追加循序写
修改redis协议
追加顺序写,很容易优化写入性能(MMAP,PageCache 等)
RESP 协议短小精悍,便于改造优化
基于 AOF,可以通过增加协议字段的方式,实现众多功能

(2) 解决数据回环问题
在RESPv2 协议前增加 3 个标志位:

server-id : 对应 redis 实例全局唯一的 id
opid : redis 变更操作编号
Src-id : 源 redis 实例 id,用于区分哪些数据是接收同步过来的,哪些是自己的
协议整体设计格为 opinfo_cmd + real_cmd,仅在写 AOF 文件时,插入对应的 opinfo_cmd;

例如:
serverA 写入了一条编号为 101 的变更操作,随后收到同步程序发送的 serverB 的相关变更数据;
收到 serverB 发送的数据后,经过一系列校验,写入 AOF 文件,将 src_opid 置为对应的 src_opid;
同步程序发送增量数据时,直接略过 server_id 不为 A 且 src_opid 不等于-1 的数据即可,这样就从源头上,解决了数据回环问题。

(3) 增强断点续传能力
为了增强异地多活版本的断点续传能力,协议中又增加了一个 timpstamp 字段,使得可以多维度断点续传

(4)解决双活无法全量同步
针对这个问题,我们特意优化了同步程序,现有同步程序流程如下:

0131b9d7-e2ef-4877-a6b4-2956487cac10

同步程序收到 rdb 文件后,直接解析 RDB 文件,通过 redis Restore 命令进行恢复;恢复成功后,通过我们新增的 opget 命令,拉取增量数据,进行同步。这样,就不会使对端 redis 中断。

解决多活一致性问题 - CRDT
CRDT(Conflict-Free Replicated Data Type)是各种基础数据结构最终一致算法的理论总结,能根据一定的规则自动合并,解决冲突,达到强最终一致的效果。CRDT 详细介绍

(1)符合 CRDT 操作的 3 个基本原理
结合律:(X U Y) U Z = X U (Y U Z)
交换律:X U Y = Y U X
幂等律:X U X = X
(2)Redis - CRDT 命令原理概览
Counter 类 - Redis 对应的命令操作(incr,decr,incrby,decrby)
INCRY,天然符合结合律与交换律,但是不符合幂等律,所以在写入时必须保证不丢不重,才能保证最终结果的一致。
Register 类 - Redis 对应的命令操作(set)
set 不满足交换类,所以改造时需要增加一些附加的元信息,来保证更新的单调性。这里采用 LWW Register,既 Last-Write-Win,通过附加时间戳信息,来保证所有异地集群,都是最后写入的最新数据。
Redis异地多活原理简介
Set 类 - Redis 对应命令操作(集合类命令、Hash 命令)
多点并发进行 Add 与 Remove 操作时,因为无法满足交换律,所以会有冲突,如下图所示,最后经过同步,两边集群数据不一致,且最终结果与预期均不符

解决此类问题,从学术原理角度,有 LWW-element-Set、Observed-Remove Set 等方案;但是从工程角度,LWW-element-Set 更加易于实现与维护,其原理是在 Set 中增加时间戳,具体原理实现流程如图:

参考:

  • CRDT: https://hal.inria.fr/inria-00609399/document
  • 阿里云CRDT介绍 https://developer.aliyun.com/article/635632
  • 快手Stack: https://kstack.corp.kuaishou.com/tech/web/article/info/812

本文地址:https://blog.csdn.net/qq_33797928/article/details/107350683

相关标签: Redis