在现在的业务场景下,高可用性要求越来越高,外围业务跨可用区未然成为标配。腾讯云数据库高级工程师刘家文联合腾讯云数据库的内核实战经验,给大家分享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高可用,内核开发有着丰盛的教训。