zoukankan      html  css  js  c++  java
  • 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消息。

  • 相关阅读:
    一个好的时间函数
    Codeforces 785E. Anton and Permutation
    Codeforces 785 D. Anton and School
    Codeforces 510 E. Fox And Dinner
    Codeforces 242 E. XOR on Segment
    Codeforces 629 E. Famil Door and Roads
    Codeforces 600E. Lomsat gelral(Dsu on tree学习)
    Codeforces 438D The Child and Sequence
    Codeforces 729E Subordinates
    【ATcoder】D
  • 原文地址:https://www.cnblogs.com/cheungchein/p/8902562.html
Copyright © 2011-2022 走看看