Redis设计与实现--多机数据库的实现

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消息。

 

posted @ 2018-04-21 18:00  清水捞蟹  阅读(540)  评论(0编辑  收藏  举报