Redis 集群原理及搭建笔记
原理:
Redis 集群是一个分布式(distributed)、容错(fault-tolerant)的 Redis 实现,集群可以使用的功能是普通单机 Redis 所能使用的功能的一个子集(subset)。
Redis 集群中不存在中心(central)节点或者代理(proxy)节点,集群的其中一个主要设计目标是达到线性可扩展性(linear scalability)。
Redis 集群为了保证一致性(consistency)而牺牲了一部分容错性:系统会在保证对网络断线(net split)和节点失效(node failure)具有有限(limited)抵抗力的前提下,尽可能地保持数据的一致性。
集群介绍:
Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。
Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.
Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令.
Redis 集群的优势:
自动分割数据到不同的节点上。
整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
Redis 集群的数据分片
Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:
节点 A 包含 0 到 5500号哈希槽.
节点 B 包含5501 到 11000 号哈希槽.
节点 C 包含11001 到 16384号哈希槽.
这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中的部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.
Redis 集群的主从复制模型
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.
在我们例子中具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用.
然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了
不过当B和B1 都失败后,集群是不可用的.
Redis 一致性保证
Redis 并不能保证数据的强一致性. 这意味这在实际中集群在特定的条件下可能会丢失写操作.
第一个原因是因为集群是用了异步复制. 写操作过程:
客户端向主节点B写入一条命令.
主节点B向客户端回复命令状态.
主节点将写操作复制给他得从节点 B1, B2 和 B3.
主节点对命令的复制工作发生在返回命令回复之后, 因为如果每次处理命令请求都需要等待复制操作完成的话, 那么主节点处理命令请求的速度将极大地降低 —— 我们必须在性能和一致性之间做出权衡。 注意:Redis 集群可能会在将来提供同步写的方法。 Redis 集群另外一种可能会丢失命令的情况是集群出现了网络分区, 并且一个客户端与至少包括一个主节点在内的少数实例被孤立。
举个例子 假设集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六个节点, 其中 A 、B 、C 为主节点, A1 、B1 、C1 为A,B,C的从节点, 还有一个客户端 Z1 假设集群中发生网络分区,那么集群可能会分为两方,大部分的一方包含节点 A 、C 、A1 、B1 和 C1 ,小部分的一方则包含节点 B 和客户端 Z1 .
Z1仍然能够向主节点B中写入, 如果网络分区发生时间较短,那么集群将会继续正常运作,如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了.
注意, 在网络分裂出现期间, 客户端 Z1 可以向主节点 B 发送写命令的最大时间是有限制的, 这一时间限制称为节点超时时间(node timeout), 是 Redis 集群的一个重要的配置选项。
目前redis支持的cluster特性
1):节点自动发现
2):slave->master 选举,集群容错
3):Hot resharding:在线分片
4):进群管理:cluster xxx
5):基于配置(nodes-port.conf)的集群管理
6):ASK 转向/MOVED 转向机制.
redis-cluster架构图
架构细节:
(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value2) redis-cluster选举:容错
(1)领着选举过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster- node-timeout),认为当前master节点挂掉.
(2):什么时候整个集群不可用(cluster_state:fail),当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误
a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成进群的slot映射[0-16383]不完成时进入fail状态.
b:如果进群超过半数以上master挂掉,无论是否有slave集群进入fail状态.
实验开始:
目的:以下三组为一个集群
192.168.11.121 master 6389 slave 6390
192.168.11.122 master 6389 slave 6390
192.168.11.123 master 6389 slave 6390
(master和slave不能本机一一对应,否者当1主节点及其从节点同时挂掉,会使集群不可用)
安装:
可用gitee的资源进行部署(适合三台主机,每台有两个节点,一主一备)
redis-cluster-install-5.0.12.zip
https://gitee.com/chen-ahai/redis-cluster-install.git
分别把该安装包拷贝到三台服务器上,并调整config.ini,执行install.sh进行安装
提示running便说明两个节点已完成部署
接下来有两种方法完成集群规划并分配:
方法一:(自由分配主从)
随便找个节点,执行:
./redis-cli -a XXXXXXX --cluster create 192.168.11.121:6389 192.168.11.122:6389 192.168.11.123:6389 192.168.11.121:6390 192.168.11.122:6390 192.168.11.123:6390 --cluster-replicas 1
可以看到:
192.168.11.121:6389对应192.168.11.122:6390
192.168.11.122:6389对应192.168.11.123:6390
192.168.11.123:6389对应192.168.11.121:6390
方法二:(手动分配主,分配从)
先随便找个节点,执行命令,分配master节点
./redis-cli --cluster create 192.168.11.121:6389 192.168.11.122:6389 192.168.11.123:6389 -h 127.0.0.1 -p 6389 -a XXXXXXX
再分配从
分配192.168.11.121的6390为本机的slave
(第一个ip+端口是要加入的从节点,第二个ip+端口为作为从节点的主节点,master-id是主节点的id)
./redis-cli -a XXXXXX --cluster add-node --cluster-slave --cluster-master-id 07d965171022c0d1c439dfe9db7d39878433b8e7 192.168.11.121:6390 192.168.11.121:6389
Ps:理论上这样分配是不可取的,主从都在一台上,当主机发生宕机,slave也无法容灾,导致集群不可用
因此我们可以通过指令,修改从节点对应的主节点
(进入要修改的节点,执行cluster replicate+要修改的新的master节点)
./redis-cli -h 127.0.0.1 -p 6390 -a xxxxxxxx
cluster replicate e0a934e9f9f475f2a07a1ca36ccc7deb598400e1
192.168.11.121:6390(slave)对应192.168.11.122:6389(master)
验证:
以目前的主从关系
192.168.11.121主---> 192.168.11.123 从
192.168.11.122主---> 192.168.11.121 从
192.168.11.123主---> 192.168.11.122 从
1.随意进入一个master节点,并随机插入数据,并查看数据
2.进入192.168.11.123节点查看该节点的数据
该节点存着zhiyang和chenjignfu的键值
3.模拟192.168.11.123该主机宕机。(模拟单主机故障)按照如下主从关系。
192.168.11.121:6389主---> 192.168.11.123:6390 从
192.168.11.122:6389主---> 192.168.11.121:6390 从
192.168.11.123:6389主---> 192.168.11.122:6390 从
当主机宕机,192.168.11.122将会接管192.168.11.123节点,从slave切换成master,并确保数据存在.
将192.168.11.123服务器强制关机,看192.168.11.122从节点日志:
可以看到192.168.11.122:6390节点从slave节点切换成master节点,且该节点的数据与之前192.168.11.123:6389节点的数据一致:
恢复192.168.11.123后,主从关系如下,故障点恢复后,并不会发生抢占,
192.168.11.121:6389主---> 192.168.11.123:6390 从
192.168.11.122:6389主---> 192.168.11.121:6390 从
192.168.11.122:6390主---> 192.168.11.123:6389 从
参考:
https://blog.51cto.com/zyxjohn/1932714
https://www.cnblogs.com/alca0126/articles/13889803.html
总结:如果客户只提供三台服务器作为中间件服务器,可考虑部署redis-cluster模式,该高可用架构可提高整体redis可使用的内存,读写的能力,容灾能力。