之间提到的哨兵+主从模式的方案,主要存在以下两个缺点:
- 只能保证高可用,但主从切换的过程中会丢失数据,因为只有一个master
- 只能单点写,没有解决水平扩容的问题
一、集群简介
redis集群是redis提供的分布式数据库方案,集群通过分片(Sharding)来进行数据共享,并提供复制和故障转移功能;
一个redis集群由多个节点(node)组成,各个节点之间的连接工作可以使用cluster meet来完成。而redis服务器在启动时会根据cluster-enabled配置选项的yes/no来决定是否开启服务器的集群模式。
集群的作用:
- 分散单台服务器的访问压力,实现负载均衡
- 分散单台服务器端的存储压力,实现可扩展性
- 降低单台服务器宕机带来的业务灾难
二、集群详细介绍
2.1 集群的数据结构
- clusterNode结构保存一个节点当前的状态,比如节点的创建时间,节点的名字,节点当前配置纪元,节点的IP地址和端口号等;
2.2 数据存储设计:
- 通过算法设计,计算出key应该保存的位置
说明:节点使用以下算法来计算给定键key属于哪个槽:
def slot_number(key):
return CRC16(key) & 16383
其中CRC16(key)语句用于计算键key的CRC-16校验和,而&16383语句则用于计算出一个介于0至16383之间的整数作为key的槽号;
使用CLUSTER KEYSLOT <key>可以查看一个指定key属于哪个槽
- 将所有的存储空间切分成16384份,每台主机存一部分,每份代表的是一个存储空间,而不是一个key的保存空间
- 按key计算出来的结果放到对应的存储空间
2.3 重新分片
所谓增加节点和减少节点,就是改变槽对应的存储位置。加机器的时候相当于把自己的槽分给新的机器;去机器就把自己的返回给其他机器;
redis重新分片工作是由redis-trib负责执行的,重新分片的关键是将某个槽的所有键值对从一个节点转移到另外一个节点。
内部的通讯设计:各个数据库相互通信,保存各个库槽的编号数据;当key过来的时候,一次命中,直接返回;一次未命中,告知具体的位置,最多两次就可以找到key
2.4 复制与故障转移
redis集群中的节点分为主节点master和从节点slave,主节点用来处理槽,从节点用于复制某个主节点,并在被复制的主节点下线时,代替下线的主节点继续处理命令请求。
2.4.1 设置从节点
向一个节点发送指令:cluster replicate <node_id> 可以让接收命令的节点成为node_id所指定节点的从节点,并开始对主节点进行复制
2.4.2 故障检测
集群中的每个节点都会定期地向其他节点发送PING消息,以此来检测对方是否下线,如果接收PING的节点没有在规定的时间内向发送PING的节点返回PONG消息,这个时候发送PING的节点将对方标记为疑似下线(PFAIL)。
如果一个集群里面,半数以上负责处理槽的主节点都将某个主节点A报告为疑似下线,那么这个主节点将被标记为已下线(FAIL),将这个主节点A标记为已下线的节点会向集群广播一条消息,收到的消息的加二点都会立即将主节点A标记为已下线。
2.4.3 故障转移
当一个从节点发现自己正在复制的主节点进入已下线状态时,从节点将开始对下线主节点进行故障转移,以下是故障转移的执行步骤:
- 复制下线主节点的所有从节点里面,会有一个节点被选中
- 被选中的从节点执行SLAVEOF no one命令,成为新的主节点
- 新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己
- 新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本下线主节点负责的槽;
- 新的主节点开始接收和自己负责槽相关的命令请求,故障转移完成;
2.4.4 选举新的主节点
新的主节点通过选举产生,选举的方法类似哨兵的选举,都是基于Raft算法的领头选举;简要描述如下:
- 集群的配置纪元是一个自增计数器,初始值是0;但集群中的某个节点开始一次故障转移操作时,这个值增一
- 对于每个配置纪元,集群里每个负责处理槽的主节点都有一次投票的机会,而第一个向主节点要求投票的从节点将获得主节点的投票
- 当从节点发现自己正在复制的主节点进入已下线状态时,从节点会向集群广播一条CLUSTER_TYPE_FAILOVER_AUTH_REQUEST消息,要求所有收到这条消息并且有投票权的主节点向这个从节点投票
- 如果一个主节点具有投票权,并且这个主节点尚未投票给其他从节点,那么主节点将向要求投票的从节点返回一条CLUSTER_TYPE_FAILOVER_AUTH_ACK消息,表示这个主节点支持这个从节点成为新的主节点
- 每个参与选举的从节点都会接收这个消息,并根据自己收到了多少条这种消息来统计自己获得了多少主节点的支持
- 如果集群中有N个具有投票权的主节点,当一个从节点获得大于等于N/2+1票时,这个从节点当选为主节点
- 因为在每一个配置的纪元里面,每个具有投票权的主节点只能投一次票,所以确保获得N/2+1票的节点只能有一个,也就是选举出来的主节点只有一个
- 如果这个纪元没有选择出来,集群进入下一个新的配置纪元,并再次进行选举,直到选举出来新的主节点为止。
三、Cluster集群的搭建
3.1 cluster配置
功能 | 指令 |
设置加入cluster,成为其中的节点 | cluster-enabled yes/no |
cluster配置文件名(该文件自动生成的) | cluster-config-file <filename> |
节点服务访问超时时间,用来判断该节点是否下线并切换从节点 | cluster-node-timeout <millseconds> |
master连接的最小slave数量 | cluster-migration-barrier <count> |
3.2 cluster节点操作
功能 | 指令 |
查看集群节点信息 | cluster nodes |
进入一个从节点redis,切换其主节点 | cluster replicate <master-id> |
发现一个新节点,增加主节点 | cluster meet ip:port |
忽略一个没有solt的节点 | cluster forget <id> |
手动故障转移 | cluster failover |
这一篇就到这里。下一篇来聊一下缓存预热的相关话题。