1 复制功能
1.1 旧版复制功能
同步,命令传播。
存在问题:断线后重复制的低效问题。
1.2 新版复制实现
将旧版实现中的同步换成PSYNC;
PSYNC分为完整重同步,部分重同步。
1.3 部分重同步的实现
复制偏移量
复制积压缓冲区(一个FIFO队列,默认大小1M)
2 Sentinel
2.1 Sentinel启动与初始化
1) 初始化服务器
2) 使用Sentinel专用代码
3) 初始化Sentinel状态
4) 初始化Sentinel状态的masters属性
5) 创建连向主服务器的网络连接
2.2 获取主服务器信息
Sentinel默认每10s通过命令连接向被监视的主服务器发送INFO命令。
2.3 获取从服务器信息
Sentinel发现主服务器有新的从服务器出现,除了会为这个新的从服务器创建相应的实例结构外,还会创建连接到从服务器的命令连接和订阅连接。
创建命令连接后,Sentinel默认每10s通过命令连接向从服务器发送INFO命令。
2.4 向主服务器和从服务器发送信息
Sentinel默认每2s通过命令连接向所有被监视的主服务器和从服务器的_sentinel_:hello频道发送消息。
2.5 接收来自主服务器和从服务器的频道消息
Sentinel与一个主服务器或者从服务器建立起订阅连接后,Sentinel就会通过订阅连接,向服务器发送:SUBSCRIBE _sentinel_:hello
当sentinel接收到一条消息时,sentinel会提取出Sentinel IP,Sentinel端口号,Sentinel运行ID:
1)若消息中的运行ID与自身一样,则忽略;
2)若不一样,接受消息的Sentinel将根据消息,更新相应的主服务器的实例结构。
首先更新Sentinel字典,然后创建连向其他Sentinel的命令连接。
2.6 检测主观下线状态
Sentinel每秒向与之创建了命令连接的实例发送PING命令,并通过回复来判断实例是否在线。
如果一个实例在down-after-milliseconds毫秒内,连续向Sentinel返回无效回复,那么Sentinel会修改这个实例结构,表示该实例已主观下线。
2.7 检测客观下线状态
Sentinel使用命令:SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid> 询问其他Sentinel是否同意主服务器下线;
目标Sentinel会分析并取出命令请求中包含的各个参数,检查主服务器是否已下线,然后向源Sentinel返回一个包含三个参数的Multi Bulk回复;
根据其他Sentinel发回的命令回复,Sentinel将统计其他Sentinel同意主服务器已下线的数量,当该数量达到配置指定的参数时,Sentinel会将主服务器实例结构的flags属性SRI_O_DOWN打开,表示主服务器已经下线。
2.8 选举领头Sentinel
2.9 故障转移
1)选出新的主服务器(依次排除下线或断线的->最近5s内没有回复领头Sentinel的INFO命令的->与已下线主服务器连接断开超过down-after-milliseconds*10的->优先级->复制偏移量->运行ID);
2)修改从服务器的复制目标;
3)将旧的主服务器变为从服务器。
3 集群
3.1 集群数据结构
clusterNode记录自己的状态,并为集群中的其他节点(包括主节点和从节点)都创建了一个相应的clusterNode结构,以此来记录其他节点的状态.
clusterNode的link属性是一个clusterLink结构,该结构保存了连接节点所需的信息,比如套接字描述符,输入缓冲区,输出缓冲区.
最后,每一个节点都保存这一个clusterState结构,这个结构记录了在当前节点的视角下集群目前的状态:
命令: CLUSTER MEET
3.2 槽指派
clusterNode中的slots属性和numsolts属性记录了节点负责处理哪些槽,
CLUSTER ADDSLOTS命令接受一个或多个槽作为参数,并将输入的槽指派给接受该命令的节点负责.
3.3 集群中执行命令
首先,计算键属于哪一个槽命令:CLUSTER KEYSLOT <key>;如果当前节点非所在槽的节点,客户端则会转向正确的节点执行命令。
节点和单机数据库在数据库方面有一个区别:节点只能使用0号数据库,而单机数据库则没有这一限制.
clusterState中的slots_to_keys跳跃表来保存槽与键之间的关系:
3.4 重新分片
重新分片由Redis集群管理软件redis-trib负责执行。
过程如图:
ASK错误:如果key所属的槽正在进行迁移,节点会向客户端发出一个ASK错误。
clusterState结构中的importing_slots_from数组记录了当前节点正在从其他节点导入的槽;migrating_slots_to数组记录了当前节点正在迁移至其他节点的槽。
接收到ASK错误的客户端会根据错误提供的IP和端口号,然后首先向目标节点发送一个ASKING命令,之后再重新发送要执行的命令。
ASKING命令负责打开客户端的REDIS_ASKING标识,
MOVED错误:代表槽的负责权已经从一个节点转移到了另一个节点。
3.5 复制与故障转移
3.5.1 设置从节点
设置从节点:CLUSTER REPLICATE <node_id>
从节点相关设置:
主节点相关设置:
3.5.2 故障检测
集群中的每个节点都会定期向其他节点发送PING消息,如果未在规定时间接收到PONG消息,那么就将该节点标记为疑似下线(PFAIL);
半数以上复杂处理槽的主节点都将某节点标识为疑似下线,则该节点将被标记为FAIL节点.
3.5.3 故障转移
3.5.4 选举新的节点
主节点才有投票权,这个过程与选领头Sentinel的方法非常相似。两者都是基于Raft算法的领头选举方法实现的。
3.6 消息
MEET消息:请求接收者加入集群。
PING消息:检测节点是否在线。
PONG消息:接收者收到发送者的MEET消息或者PING消息时,返回PONG消息以向发送者确认收到了该消息。
FAIL消息:当主节点A判断另一主节点B已进入FALL状态,节点A会向集群广播一条关于B的FALL消息,其他节点收到后立即将B标记为已下线。
PUBLISH消息:接收者立即执行这个命令,并向集群广播一条PUBULISH消息。