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

  • 相关阅读:
    github添加版本号
    centOS 7联网
    运用session来控制用户的异地登录被挤下线情况
    寻找节点d=n的节点算法
    基于Seajs的可控台球碰撞游戏
    RequireJs 源码解读及思考
    BackBone 源码解读及思考
    关于「远程兼职」
    cocos2d-html5 中的性能优化
    细说移动前端Android联调
  • 原文地址:https://www.cnblogs.com/cheungchein/p/8902562.html
Copyright © 2020-2023  润新知