Redis 多机数据库

复制

复制功能的实现
  • 同步
    在这里插入图片描述

  • 命令传播

  • 断线重连
    在这里插入图片描述

部分重同步的实现
  • 复制偏移量
  • 复制积压缓冲区
    • 固定长度先进先出队列,默认大小为1MB
  • 服务器运行 ID
PSYNC 命令的实现

在这里插入图片描述

身份验证

在这里插入图片描述

心跳检测
  • 向主服务器发送 info replication 命令,lag 表示从服务器最后一次向主服务器发送 replconf ack 命令距离现在过了多少秒。如果超过 1s,说明主从服务器之间的连接出现了故障。
  • 辅助实现 min-slaves 配置选项
    • min-slaves-to-write 3
    • min-slaves-max-lag 10
    • 在从服务器的数量少于3个,或者三个从服务器的延迟都大于或等于10秒时,主服务器将拒绝执行写命令
  • 检测命令丢失

Sentinel

在这里插入图片描述

启动 Sentinel 的命令
## 第一种
redis-sentinel /path/to/your/sentinel.conf

## 第二种
redis-server /path/to/your/sentinel.conf --sentinel
Sentinel 服务器启动过程
  • 初始化服务器

    • 本质上是运行在特殊模式下的 Redis 服务器
  • 使用 Sentinel 专用代码

  • 初始化 Sentinel 状态

    struct sentinelState {
        dict *masters;
        
        ...
    }
    
  • 初始化 Sentinel 状态的 masters 属性

    • typedef struct sentinelRedisInstance {
          int flags;
          sentinelAddr *addr;
          
          ...
      } sentinelRedisInstance;
      
      typedef struct sentinelAddr {
          char *ip;
          int port;
          
      } sentinelAddr;
      
  • 创建连向主服务器的网络连接,对于每个主服务器,Sentinel 会创建两个异步网络连接

    • 命令连接。向主服务器发送命令,并接收回复

    • 订阅连接。订阅主服务器的 xx 频道

      __sentinel__:hello
      
Sentinel 获取主服务器信息
  • 默认每 10s 一次,发送 info 命令,通过分析 info 命令的回复来获取主服务器的当前信息
Sentinel 获取从服务器信息
向主服务器和从服务器发送信息
  • 默认每 2s 一次通过命令连接向所有被监视的服务器发送命令:

    publish __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"
    
Sentinel 之间的连接

Sentinel 之间只会创建命令连接,因为 Sentinel 需要通过接受主服务器或者从服务器发来的频道信息来发现未知的 Sentinel,所以才需要建立订阅连接。

检查主观下线状态
  • 默认每 1s 一次向所有与它创建了命令连接的实例发送 PING 命令,并通过实例返回的 PING 命令回复来判断实例是否在线。
  • Sentinel 配置文件的 down-after-milliseconds 选项
  • 多个 Sentinel 设置的主观下线时长可能不同
检查客观下线状态
  • Sentinel 使用

    sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid>
    

    命令询问其他 Sentinel 是否同意主服务器已下线

  • 目标 Sentinel 向源 Sentinel 回复

    <down_state>
    <leader_runid>
    <leader_epoch>
    
  • 当认为主服务器已经进入下线状态的 Sentinel 的数量超过配置中 quorum 参数的值时,则进入客观下线状态

选举领头 Sentinel
  • 每次进行领头 Sentinel 选举之后,不论是否成功,所有 Sentinel 配置纪元自增一次。
  • 在一个配置纪元里面,所有 Sentinel 都有一次将某个 Sentinel 设置为局部领头的机会,一旦设置,不能再改。
  • 每个发现主服务器进入客观下线的 Sentinel 都会要求其他 Sentinel 将自己设置为局部领头。
  • 当源 Sentinel 向目标 Sentinel 发送 sentinel is-master-down-by-addr 命令,并且 runid 参数不是 * 而是源 Sentinel 运行 id 时,表示源 Sentinel 要求目标 Sentinel 将前者设置为后者的局部领头。
  • 设置局部头领的规则是先到先得。
  • 如果在给定时限内没有选举成功,将在一段时间后,再次选举。
故障转移
  • 选出新的主服务器
  • 修改从服务器的复制目标
  • 将旧的主服务器变为从服务器

集群

命令
# 连接节点
cluster meet <ip> <port>

# 查看集合信息
cluster nodes
cluster info
数据结构
struct clusterNode {
    // 保存连接节点所需的有关信息
    clusterLink *link;
    
    // 二进制位数组
    unsigned char slots[16384/8];
    
    int numslots;
    
    // ...
}

struct clusterLink {
    // 连接的创建时间
    mstime_t ctime;
    
    int fd;
    
    sds sndbuf;
    
    sds rcvbuf;
    
    struct clusterNode *node;
}

struct clusterState {
    clusterNode *myself;
    // 集群当前的配置纪元,用于实现故障转移
    uint64_t currentEpoch;
    int state;
    int size;
    dict *nodes;
    clusterNode *slots[16384];
    // 保存槽和键之间的关系
    zskiplist *slots_to_keys;
    // ...
}
cluster meet 命令的实现

在这里插入图片描述

槽指派
  • 集群的整个数据库被分为 16384 个槽

  • cluster addslots <slot> [slots ...]
    
  • 在集群中执行命令
    在这里插入图片描述

  • 计算键属于哪个槽

    def slot_number(key):
    	return CRC16(key) & 16383
    
  • 查看给定键属于哪个槽的命令

    cluster keyslot <key>
    
重新分片的实现原理
  • 重新分片操作是由 Redis 的集群管理软件 redis-trib 负责执行的

  • 步骤

    • 向目标节点发送命令,让目标节点准备好从源节点导入属于 slot 的键值对

      cluster setslot <slot> importing <source_id>
      
    • 向源节点发送命令,让源节点准备好将属于 slot 的键值对迁移至目标节点

      cluster setslot <slot> migrating <target_id>
      
    • 迁移键
      在这里插入图片描述

    • 向集群中任意一个节点发送命令,将 slot 指派给目标节点

      cluster setslot <slot> node <target_id>
      
从节点
  • 设置从节点

    cluster replicate <node_id>
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值