Redis集群:集群容灾

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Redis 版,经济版 1GB 1个月
简介: Redis集群:集群容灾

集群原理简述

Redis3.0版本之前没有提供集群功能,一般用一致性Hash和Hash环在客户端做key的分片。3.0版本开始Redis使用Hash槽实现分片,Redis共准备了16384个槽(slot),这些slot分布在集群节点上。

   为什么是16384?

   Redis需要维护节点和槽之间的映射关系,每个节点需要知道自己有哪些槽,并且需要在结点之间传递这个消息。
   为了节省存储空间,每个节点用一个Bitmap来存放其对应的槽:
   2k = 2*1024*8 = 16384,也就是说,每个结点用2k的内存空间,总共16384个比特位,就可以存储该结点对应了哪些槽。然后这2k的信息,通过Gossip协议,在结点之间传递。

客户端使用公式(HASH_SLOT = CRC16(key) mod 16384)计算出Key对应的slot位置,根据从服务端获取slot和节点映射信息,找到slot对应的节点。

   如果服务端slot对应的节点发生了变更,客户端向旧节点发送操作时会收到MOVED指令:(error) MOVED 866 127.0.0.1:7000,意思是866这个slot已经迁移到127.0.0.1:7000节点,客户端向新节点发送操作并更新本地缓存的slot和节点映射信息。

集群容灾

当Redis部分slot所在的节点不可用时,整个集群都变的不可用,所以集群容灾最重要的就是要避免这种情况出现。

方案一:为每个master节点配置一个slave节点

优点:当master宕机时,slave自动提升为master节点恢复服务。

缺点:如果slave节点也宕机,由于没有其他从节点可以提升为主节点(因为master节点仍未恢复正常),集群没法继续进行正常操作。如果为每个master节点都配置多个slave节点,则会造成浪费。

方案二:不对称集群——备份迁移

不对称性集群是让集群布局时不时地自动变化。

例如,假设集群有三个主节点 A,B,C。节点 A 和 B 都各有一个从节点,A1 和 B1。节点 C 有两个从节点:C1 和 C2。

       主节点 A 失效。A1 被提升为主节点。

       节点 C2 迁移成为节点 A1 的从节点,要不然 A1 就没有任何从节点。

       三个小时后节点 A1 也失效了。

       节点 C2 被提升为取代 A1 的新主节点。

       集群仍然能继续正常工作。

备份迁移算法

迁移算法不用任何形式的协议,因为 Redis 集群中的从节点布局不是集群配置信息(配置信息要求前后一致并且/或者用 config epochs 来标记版本号)的一部分。 它使用的是一个避免在主节点没有备份时从节点大批迁移的算法。这个算法保证,一旦集群配置信息稳定下来,最终每个主节点都至少会有一个从节点作为备份。

接下来讲这个算法是如何工作的。在开始之前我们需要定义清楚在这个上下文中什么才算是一个好的从节点:一个好的从节点是指从给定节点的角度看,该从节点不处于 FAIL 状态。

每个从节点若检测出存在至少一个没有好的从节点的单一主节点,那么就会触发这个算法的执行。然而在所有检测出这种情况的从节点中,只有一部分从节点会采取行动。 通常这“一部分从节点”都只有一个,除非有不同的从节点在给定时间间隔里对其他节点的失效状态有稍微不同的视角。

采取行动的从节点是属于那些拥有最多从节点的主节点,并且不处于 FAIL 状态及拥有最小的节点 ID。

例如,如果有 10 个主节点,它们各有 1 个从节点,另外还有 2 个主节点,它们各有 5 个从节点。会尝试迁移的从节点是在那 2 个拥有 5 个从节点的主节点中的所有从节点里,节点 ID 最小的那个。已知不需要用到任何协议,在集群配置信息不稳定的情况下,有可能发生一种竞争情况:多个从节点都认为自己是不处于 FAIL 状态并且拥有较小节点 ID(实际上这是一种比较难出现的状况)。如果这种情况发生的话,结果是多个从节点都会迁移到同个主节点下,不过这种结局是无害的。这种竞争发生的话,有时候会使得割让出从节点的主节点变成没有任何备份节点,当集群再次达到稳定状态的时候,本算法会再次执行,然后把从节点迁移回它原来的主节点。

最终每个主节点都会至少有一个从节点作为备份节点。通常表现出来的行为是,一个从节点从一个拥有多个从节点的主节点迁移到一个孤立的主节点。

这个算法能通过一个用户可配置的参数 cluster-migration-barrier 进行控制。这个参数表示的是,一个主节点在拥有多少个好的从节点的时候就要割让一个从节点出来。例如这个参数若被设为 2,那么只有当一个主节点拥有 2 个可工作的从节点时,它的一个从节点会尝试迁移。

备份迁移测试

用于测试的集群:主节点7000/7001分别有从节点7005/7003,主节点7002有从节点7004和7006。

127.0.0.1:7000> cluster nodes
9b022d79cf860c87dc2190cdffc55b282dd60e42 127.0.0.1:7002@17002 master - 0 1542960331000 3 connected 10923-16383
3bcdfbed858bbdd92dd760632b9cb4c649947fed 127.0.0.1:7000@17000 myself,master - 0 1542960330000 1 connected 0-5460
ea4e0dcf8dbf6d4611659b5abbd6563926224f0f 127.0.0.1:7004@17004 slave 9b022d79cf860c87dc2190cdffc55b282dd60e42 0 1542960329000 5 connected
6e41c9b986e863943c1fd41de3411241e0fcb65b 127.0.0.1:7006@17006 slave 9b022d79cf860c87dc2190cdffc55b282dd60e42 0 1542960331690 3 connected
e852e07181f20dd960407e5b08f7122870f67c89 127.0.0.1:7003@17003 slave 2a8f29e22ec38f56e062f588e5941da24a2bafa0 0 1542960331000 2 connected
2a8f29e22ec38f56e062f588e5941da24a2bafa0 127.0.0.1:7001@17001 master - 0 1542960328000 2 connected 5461-10922
583a6b71dcde83ab2685fcfd4ea94ecf9e353a1e 127.0.0.1:7005@17005 slave 3bcdfbed858bbdd92dd760632b9cb4c649947fed 0 1542960329000 7 connected

停掉7000后,7005升级为master。

127.0.0.1:7001> cluster nodes
ea4e0dcf8dbf6d4611659b5abbd6563926224f0f 127.0.0.1:7004@17004 slave 9b022d79cf860c87dc2190cdffc55b282dd60e42 0 1542961385025 3 connected
2a8f29e22ec38f56e062f588e5941da24a2bafa0 127.0.0.1:7001@17001 myself,master - 0 1542961380000 2 connected 5461-10922
e852e07181f20dd960407e5b08f7122870f67c89 127.0.0.1:7003@17003 slave 2a8f29e22ec38f56e062f588e5941da24a2bafa0 0 1542961383000 6 connected
583a6b71dcde83ab2685fcfd4ea94ecf9e353a1e 127.0.0.1:7005@17005 master - 0 1542961383995 8 connected 0-5460
9b022d79cf860c87dc2190cdffc55b282dd60e42 127.0.0.1:7002@17002 master - 0 1542961382000 3 connected 10923-16383
6e41c9b986e863943c1fd41de3411241e0fcb65b 127.0.0.1:7006@17006 slave 9b022d79cf860c87dc2190cdffc55b282dd60e42 0 1542961381936 3 connected
3bcdfbed858bbdd92dd760632b9cb4c649947fed 127.0.0.1:7000@17000 master,fail - 1542961362723 1542961362313 1 disconnected

停掉7005后,原属于7002的从节点7006被提升为master。

127.0.0.1:7001> cluster nodes
ea4e0dcf8dbf6d4611659b5abbd6563926224f0f 127.0.0.1:7004@17004 slave 9b022d79cf860c87dc2190cdffc55b282dd60e42 0 1542961749007 3 connected
2a8f29e22ec38f56e062f588e5941da24a2bafa0 127.0.0.1:7001@17001 myself,master - 0 1542961747000 2 connected 5461-10922
e852e07181f20dd960407e5b08f7122870f67c89 127.0.0.1:7003@17003 slave 2a8f29e22ec38f56e062f588e5941da24a2bafa0 0 1542961750033 6 connected
583a6b71dcde83ab2685fcfd4ea94ecf9e353a1e 127.0.0.1:7005@17005 master,fail - 1542961727108 1542961726285 8 disconnected
9b022d79cf860c87dc2190cdffc55b282dd60e42 127.0.0.1:7002@17002 master - 0 1542961746000 3 connected 10923-16383
6e41c9b986e863943c1fd41de3411241e0fcb65b 127.0.0.1:7006@17006 master - 0 1542961749000 9 connected 0-5460
3bcdfbed858bbdd92dd760632b9cb4c649947fed 127.0.0.1:7000@17000 master,fail - 1542961362723 1542961362313 1 disconnected

停掉7006后,没有其他从节点被提升,集群瘫痪。将7002的cluster-migration-barrier设置为0,7002的从节点也没有被提升。可能Redis要求从节点少于2个不给提升?

127.0.0.1:7001> cluster nodes
ea4e0dcf8dbf6d4611659b5abbd6563926224f0f 127.0.0.1:7004@17004 slave 9b022d79cf860c87dc2190cdffc55b282dd60e42 0 1542963389063 3 connected
2a8f29e22ec38f56e062f588e5941da24a2bafa0 127.0.0.1:7001@17001 myself,master - 0 1542963389000 2 connected 5461-10922
e852e07181f20dd960407e5b08f7122870f67c89 127.0.0.1:7003@17003 slave 2a8f29e22ec38f56e062f588e5941da24a2bafa0 0 1542963387000 6 connected
583a6b71dcde83ab2685fcfd4ea94ecf9e353a1e 127.0.0.1:7005@17005 master,fail - 1542961727108 1542961726285 8 disconnected
9b022d79cf860c87dc2190cdffc55b282dd60e42 127.0.0.1:7002@17002 master - 0 1542963388024 3 connected 10923-16383
6e41c9b986e863943c1fd41de3411241e0fcb65b 127.0.0.1:7006@17006 master,fail - 1542963208985 1542963206916 9 disconnected 0-5460
3bcdfbed858bbdd92dd760632b9cb4c649947fed 127.0.0.1:7000@17000 master,fail - 1542961362723 1542961362313 1 disconnected

灾备恢复

假如我们某个主节点宕机后,由于某种原力死活启动不起来或者无法接入集群,需要我们在新的机器上恢复该节点和数据。

情况一:宕机服务器能访问,只是Redis无法使用

假设7006主节点挂了,复制7006整个目录到新机器,编辑根目录下的nodes-7006.conf,将里面7006的IP改为新机器的IP,直接启动即可恢复集群和数据。

如果是在同一台机器测试,将nodes-7006.conf改成nodes-7007.conf,修改redis.conf中的7006为7007。

注意:用7007代替7006后,重新启动7006时,需要在7006执行flushall和cluster reset,清除之前的集群信息,然后重新手动将7006加入集群,否则集群会报错。

情况二:宕机服务器无法访问,文件也复制不出来

这种情况数据肯定是没了,除非之前有做过备份。我们先想办法保证恢复集群可用性。

将当前集群中任意一台可用服务的nodes-port.conf文件复制到新机器的Redis目录下,这里假设用7008来恢复7007,修改文件名为nodes-7008.conf,修改redis.conf中相关端口为7008。

打开nodes-7008.conf文件

       删除原节点所在行的"myself,",

       在7007所在行的"master"前添加"myself,",

       删除master后面的"fail",如果"fail"后面有其他异常标志,一并删除。

       修改当前行的ip:port为新节点的ip:port

       启动7008。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
14天前
|
存储 运维 NoSQL
Redis Cluster集群模式部署
Redis Cluster集群模式部署
41 4
|
17天前
|
监控 NoSQL 算法
手把手教你如何搭建redis集群(二)
手把手教你如何搭建redis集群(二)
29 1
|
17天前
|
存储 NoSQL 容灾
手把手教你如何搭建redis集群(一)
手把手教你如何搭建redis集群(一)
35 1
|
2月前
|
负载均衡 监控 NoSQL
Redis的几种主要集群方案
【5月更文挑战第15天】Redis集群方案包括主从复制(基础,读写分离,手动故障恢复)、哨兵模式(自动高可用,自动故障转移)和Redis Cluster(官方分布式解决方案,自动分片、容错和扩展)。此外,还有Codis、Redisson和Twemproxy等工具用于代理分片和负载均衡。选择方案需考虑应用场景、数据量和并发需求,权衡可用性、性能和扩展性。
224 2
|
2月前
|
存储 监控 负载均衡
保证Redis的高可用性是一个涉及多个层面的任务,主要包括数据持久化、复制与故障转移、集群化部署等方面
【5月更文挑战第15天】保证Redis高可用性涉及数据持久化、复制与故障转移、集群化及优化策略。RDB和AOF是数据持久化方法,哨兵模式确保故障自动恢复。Redis Cluster实现分布式部署,提高负载均衡和容错性。其他措施包括身份认证、多线程、数据压缩和监控报警,以增强安全性和稳定性。通过综合配置与监控,可确保Redis服务的高效、可靠运行。
205 2
|
2月前
|
存储 监控 负载均衡
redis 集群 (主从复制 哨兵模式 cluster)
redis 集群 (主从复制 哨兵模式 cluster)
|
3天前
|
缓存 负载均衡 NoSQL
Redis系列学习文章分享---第十四篇(Redis多级缓存--封装Http请求+向tomcat发送http请求+根据商品id对tomcat集群负载均衡)
Redis系列学习文章分享---第十四篇(Redis多级缓存--封装Http请求+向tomcat发送http请求+根据商品id对tomcat集群负载均衡)
8 1
|
10天前
|
NoSQL Redis
redis集群教程
redis集群教程
|
3天前
|
存储 监控 NoSQL
Redis系列学习文章分享---第十二篇(搭建哨兵集群+RedisTemplate连接哨兵+搭建分片集群+-散列插槽+集群伸缩 +故障转移+RedisTemplate访问分片集群)
Redis系列学习文章分享---第十二篇(搭建哨兵集群+RedisTemplate连接哨兵+搭建分片集群+-散列插槽+集群伸缩 +故障转移+RedisTemplate访问分片集群)
9 0
|
3天前
|
NoSQL Redis
Redis系列学习文章分享---第五篇(Redis实战篇--优惠券秒杀,全局唯一id 添加优惠券 实现秒杀下单 库存超卖问题分析 乐观锁解决超卖 实现一人一单功能 集群下的线程并发安全问题)
Redis系列学习文章分享---第五篇(Redis实战篇--优惠券秒杀,全局唯一id 添加优惠券 实现秒杀下单 库存超卖问题分析 乐观锁解决超卖 实现一人一单功能 集群下的线程并发安全问题)
6 0