在现在的业务场景下,高可用性要求越来越高,外围业务跨可用区未然成为标配。腾讯云数据库高级工程师刘家文联合腾讯云数据库的内核实战经验,给大家分享 Redis 是如何实现多可用区,内容蕴含Redis 主从版、集群版原生架构,腾讯云 Redis 集群模式主从版、多 AZ 架构实现以及多 AZ 关键技术点,具体可分为以下四个局部:
第一局部:介绍 Redis 的原生架构,蕴含主从版及集群版;
第二局部:介绍腾讯云 Redis 架构,为了解决主从架构存在的问题,腾讯云应用了集群模式的主从版。其次为了更好的适应云上的 Redis 架构,引入了 Proxy;
第三局部:剖析原生 Redis 为何不能实现多 AZ 架构的高可用以及腾讯云是如何实现多可用区;
第四局部:分享实现多可用区的几个关键技术点,蕴含节点部署、就近接入及节点的选主机制。
点击观看视频
Redis 原生架构
Redis 的原生架构蕴含主从版及集群版。主从版是由一个 master,多个 slave 组成。主从的高可用个别采纳哨兵模式 。哨兵模式在节点故障后,能主动把相应的节点进行下线解决, 然而哨兵模式无奈补节点 。为了配合补从,须要管控组件进行帮助,因而个别会将 监控组件和管控组件 配合实现主从版的一个高可用。无论是哪种形式,主从版的可用性依赖内部的仲裁组件,存在复原工夫长及组件自身的高可用问题。其次主从版还会导致 双写 的问题及 提主有损 的性能缺点。
Redis 的集群版中的每一个节点互相独立,节点之间通过 Gossip 协定来进行通信,每一个节点都保留了集群中所有节点的一个信息。集群版的数据 基于 slot进行分片治理,slot 总共有 16384 个,节点的 slot 并不是固定的,能够通过搬迁 key 的计划来实现 slot 的迁徙,有了 slot 的搬迁性能,集群版能够 实现数据平衡及分片的动静调整。
Redis 集群版外部集成了 Gossip 协定,通过 Gossip 协定能实现 节点的主动发现和主动成灾 的性能。主动发现是指一个节点要退出到集群中,只须要退出集群中的任何一个节点,退出后,新节点的信息会通过 Gossip 推广到集群中的所有的节点。同理,当一个节点故障后,所有节点都会把故障信息发送给集群其它节点,通过肯定的判死逻辑,它会让这个节点进行主动下线,这个也就是 Redis 集群版的 主动容灾性能。
为了阐明单可用区是如何部署的,咱们须要进一步理解 Redis 集群版的主动容灾。主动容灾总共分为两个步骤,第一个就是咱们的 判死逻辑 ,当超过一半的主节点认为该节点故障,集群就会认为这个节点曾经故障。此时从节点会 发动投票,超过一半的主节点受权该节点为主节点时,它会将角色变为主节点,同时播送角色信息。
依据下面这两点剖析,不难发现 Redis 集群版有两个部署要求,一个是 主从不能同机 ,当主从同机的机器故障后,整个分片就相当于曾经故障了,集群也就变为一个不可用的状态。其次是咱们的 节点数不能超过分片数的一半,这里要留神的是节点数,而不是只限度主节点数。
上图的左边局部是谬误部署形式,在集群节点状态没有变动的状况下,是可能满足高可用的,但集群的主从产生切换后,一个机器上的主节点曾经超过大多数,而这个大多数机器故障后,集群无奈主动复原。因而三分三从的集群版,要满足高可用总共须要六台机器。
腾讯云 Redis 架构
为了解决双主的问题及反对无损提主的操作,腾讯云上应用了集群模式的主从版。实现集群模式的主从版,先要解决三个问题:
第一个是集群模式须要 至多 3 个投票(仲裁)节点 的问题,因为主从版本只有一个 Master,为了达到 3 个仲裁节点,咱们引入了两个 Arbiter 节点,Arbiter 只有投票权,不存储数据,通过这个革新后,就可能满足了集群版的高可用。
第二个是 多 DB 问题,因为腾讯云上引入了 Proxy,缩小了对多 DB 治理的简单,因而能够放开单 DB 限度。
最初一个是须要 启用跨 slot 拜访,在主从版中,所有的 slot 都在一个节点下面,不存在跨节点问题,因而能够勾销跨 slot 限度。
解决完这几个次要问题后,集群模式能够达到齐全兼容主从版,同时领有集群版的主动容灾、无损提主及能够在业务反对的状况下,无缝降级为集群版。
因为 Client 版本比拟多,为了兼容不同的 Client,腾讯云引入了Proxy。Proxy 除了屏蔽 Client 的差别外,也屏蔽的后端 Redis 的版本差别,业务能够应用主从版的 Client 去应用后端的集群版。Proxy 也补齐了 Redis 短少的流量隔离及反对更丰盛的指标监控,还能将多个连贯的申请转换为 pipeline 申请转发到后端,晋升 Redis 的性能。
Redis 的多 AZ 架构
部署高可用的多可用区架构,须要至多满足两个条件:
主从不能部署到同一个可用区;
一个可用区的节点数不能超过分片数的一半。
如果咱们部署一个三分片的实例,那应该须要个 6 个可用区能力真正保障它的高可用。即便可用区短缺,它也会有性能的抖动,拜访本可用区,性能和单可用区雷同,但如果跨可用区拜访,至多呈现 2ms 提早,因而原生的 Redis 是不适宜多可用区的部署,为了实现高可用的部署,咱们须要更深刻的剖析它的问题所在。这种场景的高可用不满足次要是因为 主节点漂移,而投票权和主节点又是绑定关系。当投票权在不同可用区间切换后,导致超过大多数投票节点在该可用区,此时该可用区故障后就会呈现集群无奈复原的状况。
从下面剖析能够看出,高可用的问题是因为投票权产生漂移导致的。假如能把投票权固定在某些节点下面,这样投票权就能够不再漂移。当然这里无奈将投票权固定在从或者主节点上,对于多可用区,最好的形式就是引入了一个 ZoneArbiter 节点,它只做节点的判死及选主,不存储任何数据。这样投票权就从存储节点中分离出来。在投票权拆散后,即便数据节点的 Master 能够位于一个可用区,从位于不同的可用区也能满足高可用。业务在主可用区中拜访和单可用区拜访性能是雷同的。
多 AZ 的关键技术
保障高可用后,接下来介绍多可用区的三个要害的点:高可用如何部署、性能如何达到最优、可用区故障后保障集群主动复原。
节点部署同样须要满足两个点:第一是 主从不能同可用区 ,这个比拟容易满足,只有有 2 个可用区即可,第二点是 至多三个 ZoneArbiter 节点位于不同的可用区,第二个条件须要三个可用区,如果没有三个可用区的地区也能够将 ZoneArbiter 部署于就近的地区,因为数据节点和仲裁节点是拆散的,位于其它可用区的节点只会呈现判死及提主有毫秒级提早,对性能和高可用不会有任何影响。
剖析完部署后,再来看下 数据的存储链路,存储链路分为读和写链路,写链路是从 client 到 LB,再到 Proxy,最初将数据写入到相应的 Master。在读的时候,开启就近读的个性后,链路从 client 到 LB,再到 Proxy,最初抉择一个就近的节点读取数据。就近门路抉择蕴含 LB 的就近抉择及 Proxy 的就近抉择,LB 要依据 Client 的地址抉择绝对应的 Proxy。如果是读,Proxy 要跟据本身所在可用区信息抉择同可用区的节点进行读拜访。如果是写,Proxy 须要拜访主可用区的 Master 节点。能实现就近拜访,最要害的一个点就是要 LB 及 Proxy 要存储相干后端的可用区信息,有这些信息后,就能实现就近的路由抉择。
单可用区和多可用区故障的最大区别是:首先多可用区的某一节点故障后,主节点有可能切到其它可用区会 导致性能稳定 。其次对于多可用区的实例, 整个可用区故障后,须要投票的节点比单可用区的节点多。在多节点故障的场景测试中,128 分片,63 节点同时故障,99% 以上都无奈失常复原集群。而无奈复原的要害就是 Redis 的选主机制导致。因而咱们须要更深刻的了解 Redis 的选主机制。
首先看下选主机制的 受权机制,当主节点收到一个 failover 信息后,核查本身节点为 Master,而后查看投票的这个节点集群的 epoch 是不是最新的,并且在这个 epoch,并没有投票任何的节点,为了避免一个节点的多个从节点反复发动投票,这里在 30s 内不容许反复发动。最初再核查这个 slot 的归属权是否属于发动 failover 的这个节点,如果都没有问题,那么就会投票给该节点。
综上,容许该主节点投票的条件是:
- 发动投票的节点的集群信息是最新的;
- 一个 epoch 只能受权一个节点;
- 30s 内同一分片只能受权一次;
- slot 的归属权正确。
看完主节点的受权机制后,再看下从 节点发动投票的机制。发动投票的流程是先核查 1 分钟内没有发动过投票,再核查该节点数据是否无效(不能和主断开 160s)。从节点是无效的,就开始计算发动投票的工夫,当投票工夫到后,将集群的 epoch+1,而后再发动 failover,如果主节点的受权超过分片数的一半,则本身提为主节点,并播送节点信息。这里从节点投票有两个要害的点,一分钟只能重试一次投票,最大重试 160s,从节点最多能够投票 3 次。当超过一半的 master 受权提主,提主胜利,否则超时。
在某一主节点故障后,集群的选主尽量在 同可用区 中抉择。一个分片不同从节点之间的选主工夫由节点的 offset 排名及的 500ms 的随机工夫决定。在写少读多状况下,offset 排名大多工夫是雷同的。在单可用区场景下,随机抉择一个节点自身无任何影响,但多可用区就会呈现性能的抖动。因而这个就须要在排名中引入同可用区的排名。而同可用区的排名就须要要每个节点都晓得所有节点的可用区信息。在 Gossip 中刚好有一个预留字段,咱们将可用区信息存储在这个预留字段中,而后将这个节点的可用区信息会播送到所有节点中,这样每个节点都有所有节点的可用区信息。在投票的时候咱们依照 offset 和可用区信息排名综合思考来保障同可用区优先提主。
一个节点的选主剖析完后,咱们来剖析下 多节点故障的投票机会。多个节点发动投票时,会随机抉择 500 毫秒内的一个工夫点,而后发动投票。如果集群有 100 个主节点,500 毫秒发动完投票,每个节点投票工夫是 5 毫秒,5 毫秒必定是不够一个投票周期。在之前的多节点故障投票成功率测试后果也就证实了这种状况简直不能胜利。
投票不能胜利的关机是 集群不同节点投票是随机发动 导致的,既然随机存在抵触,最间接的解决办法就是 按程序来投票 。按程序投票能够简略分为两种,一种是 依赖内部的管制 ,引入内部依赖就须要保障它的高可用,个别状况下,存储链路的高可用最好不要依赖内部组件,否则会导致整体的可用性受内部组件加存储节点的高可用的影响。那再思考下 集群外部实现程序投票,集群外部实现程序投票也有两种形式,一个是仲裁节点按程序来受权。然而这种形式很容易突破一个 epoch 投一个从节点的准则,突破后可能会导致投票后果不合乎预期。还有一种解决办法是由从节点来程序发动投票。
从节点要保障程序发动投票,那就须要每个节点的排名是保障雷同的,而节点 ID 在生命周期中是惟一的,且每个节点都有其它节点的 ID 信息,因而这里 抉择节点 ID 的排名 是比拟好的一种计划,每个从节点 ID 发动投票前,首先核查本人的节点 ID 是不是第一名,如果是就发动投票,如果不是就期待 500ms。这个 500ms 是为了避免队头投票失败的场景。按这种形式优化后,投票都能够胜利。因为自身是分布式的,这里还是存在着小概率失败,在失败后就须要内部监控,强行提主,保障集群的尽快恢复。
专家答疑
1. 通过 sentinel 连贯 redis 也会呈现双写么?
答:双写是对存量的连贯来说的,如果存量的连贯没有断开,它会写入到之前的 master 节点,而新的连贯会写入到新的 master 节点,此时就是双写。而集群模式呈现双写最多 15s(判死工夫),因为 15s 后发现本身曾经脱离大多数,会将节点切换为集群 Fail,此时写入及读取出错,而躲避了双写的问题。
2. 固定节点投票,这几个节点会不会成为单点
答:单点是不可躲避的,比方 1 主 1 从,主挂了,那么从提主后,这个节点就是单点,呈现单点是须要咱们进行补从操作。而这里仲裁节点呈现故障,补充一个节点即可,只有保障大多数仲裁节点失常工作即可,因为仲裁和数据拜访是拆散的,故障及补节点对数据拜访无任何影响。
3. 整个可用区故障和可用区内节点故障 failover 的解决策略是什么?
答:不论是整个可用区故障还是单机故障导致的多节点故障,都应该采纳程序投票来实现,缩小抵触,而如果同可用区有从节点,该节点应该优先提主。
4. 想问下写申请,要同步等从复制完吗?
答:Redis 不是强同步,Redis 强同步须要应用 wait 命令来实现。
5. 最大反对多少 redis 分片呢,节点多了应用 gossip 有会不会有性能问题?
答:最好不要超过 500 个,超过 500 个节点会呈现 ping 导致的性能抖动,此时只能通过调大 cluster_node_timeout 来升高性能抖动
6. 多区主节点,写同步如何实现?
答:可能想问的是寰球多活实例,多活实例个别须要数据先落盘,而后再同步给其它节点,同步的时候要保障从节点先收到数据后,能力发送给多活的其它节点。还须要解决数据同步环路,数据抵触等问题。
7. 以后选主逻辑和 raft 选主有大的区别吗?
答:雷同的点都须要满足大多数受权,都有一个随机抉择工夫,不同的点 Redis 是主节点有投票权(针对多分片状况),而 raft 可认为是所有节点(针对单分片状况)。Raft 数据写入要超一半节点胜利才返回成。Redis 应用弱同步机制(能够应用 wait 强势主从同步完返回),写完主节点立刻返回,在主故障后,须要数据越新的节点优先提主(数据偏移值由 Gossip 告诉给其它节点),但不保障它肯定胜利。
对于作者
刘家文,腾讯云数据库高级工程师,先后负责 Linux 内核及 redis 相干研发工作,目前次要负责腾讯云数据库 Redis 的开发和架构设计,对 Redis 高可用,内核开发有着丰盛的教训。