Redis-Sentinel(哨兵模式),看这篇就够了哦

文章目录

  • 简介
  • 启动并初始化Sentinel
    • 初始化Sentinel服务器
    • 替换普通Redis代码为Sentinel的专用代码
    • 初始化 Sentinel 状态
    • 初始化Sentinel监视的主服务器列表
    • 创建连向主服务器的网络连接
  • 获取主服务器信息
  • 获取从服务器信息
  • 向主服务器和从服务器发送信息
  • 接收来自主从服务器频道的信息
    • 接收信息
    • 更新sentinels字典
  • 创建连向其他sentinel的连接
  • 检测Master是否主观下线
  • 检测Master是否客观下线
  • 选举领头sentinel
  • 故障转移
  • 选出新的主服务器
  • 修改从服务器的复制目标
  • 将旧的主服务器变为从服务器

简介

Sentinel(哨兵) 是redis的高可用性解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进行下线时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。然后由新的主服务器代替已下线的主服务器继续处理命令请求。

例如下图所示:

Redis-Sentinel(哨兵模式),看这篇就够了哦_第1张图片

当Server1 掉线后:

Redis-Sentinel(哨兵模式),看这篇就够了哦_第2张图片

升级Server2 为新的主服务器:

Redis-Sentinel(哨兵模式),看这篇就够了哦_第3张图片

启动并初始化Sentinel

启动一个Sentinel可以使用命令:

redis-sentinel /path/to/your/sentinel.conf

或者:redis-server /path/to/your/sentinel.conf --sentinel
这两个命令执行的效果是一样的。

当一个Sentinel启动时它需要经历如下步骤:

  • 初始化Sentinel服务器
  • 替换普通Redis代码为Sentinel的专用代码
  • 初始化Sentinel状态
  • 根据用户给定的Sentinel配置文件,初始化Sentinel监视的主服务器列表
  • 创建连接主服务器的网络连接

初始化Sentinel服务器

因为sentinel执行的工作和普通redis服务器执行的工作不同,所以sentinel的初始化过程和普通redis服务器的初始化过程并不完全相同,Sentinel并不需要读取RDB/AOF文件来还原数据状态。
Redis-Sentinel(哨兵模式),看这篇就够了哦_第4张图片

替换普通Redis代码为Sentinel的专用代码

端口:sentinel.c/REDIS_SENTINEL_PORT:26379

命令表:sentinel.c/sentinelcmds

启动 Sentinel 的第二个步骤就是将一部分普通 Redis 服务器使用的代码替换成 Sentinel 专用代码。

比如说, 普通 Redis 服务器使用 redis.h/REDIS_SERVERPORT 常量的值作为服务器端口:

#define REDIS_SERVERPORT 6379

而 Sentinel 则使用 sentinel.c/REDIS_SENTINEL_PORT 常量的值作为服务器端口:

#define REDIS_SENTINEL_PORT 26379

普通 Redis 服务器使用 redis.c/redisCommandTable 作为服务器的命令表:

struct redisCommand redisCommandTable[] = {
    {"get",getCommand,2,"r",0,NULL,1,1,1,0,0},
    {"set",setCommand,-3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
    {"setnx",setnxCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
    // ...
    {"script",scriptCommand,-2,"ras",0,NULL,0,0,0,0,0},
    {"time",timeCommand,1,"rR",0,NULL,0,0,0,0,0},
    {"bitop",bitopCommand,-4,"wm",0,NULL,2,-1,1,0,0},
    {"bitcount",bitcountCommand,-2,"r",0,NULL,1,1,1,0,0}

而 Sentinel 则使用 sentinel.c/sentinelcmds 作为服务器的命令表, 并且其中的 INFO 命令会使用 Sentinel 模式下的专用实现 sentinel.c/sentinelInfoCommand 函数, 而不是普通 Redis 服务器使用的实现 redis.c/infoCommand 函数:

struct redisCommand sentinelcmds[] = {
    {"ping",pingCommand,1,"",0,NULL,0,0,0,0,0},
    {"sentinel",sentinelCommand,-2,"",0,NULL,0,0,0,0,0},
    {"subscribe",subscribeCommand,-2,"",0,NULL,0,0,0,0,0},
    {"unsubscribe",unsubscribeCommand,-1,"",0,NULL,0,0,0,0,0},
    {"psubscribe",psubscribeCommand,-2,"",0,NULL,0,0,0,0,0},
    {"punsubscribe",punsubscribeCommand,-1,"",0,NULL,0,0,0,0,0},
    {"info",sentinelInfoCommand,-1,"",0,NULL,0,0,0,0,0}
};

Sentinel用于较少的Redis命令,大部分命令在Sentinel客户端都不支持,并且Sentinel拥有一些特殊的功能,这些需要Sentinel在启动时将Redis服务器使用的代码替换为Sentinel的专用代码。在此期间Sentinel会载入与普通Redis服务器不同的命令表。
Sentinel不支持SET、DBSIZE等命令;保留支持PING、PSUBSCRIBE、SUBSCRIBE、UNSUBSCRIBE、INFO等指令;这些指令在Sentinel工作中提供了保障。

初始化 Sentinel 状态

在应用了 Sentinel 的专用代码之后, 接下来, 服务器会初始化一个 sentinel.c/sentinelState 结构(后面简称“Sentinel 状态”), 这个结构保存了服务器中所有和 Sentinel 功能有关的状态。

struct sentinelState{
    // 当前纪元,用于实现故障转移
    uint64_t current_epoch;
    // 保存了所有被这个sentinel监视的主服务器
    // 字典的键是主服务器的名字
    // 字典的值是一个指向sentinelRedisInstance和结构的指针
    dict *masters;
    // 是否进入了 TILT 模式?
    int tilt;
    // 目前正在执行时的脚本的数量
    int running_scripts;
    // 进入tilt模式的时间
    mstime_t tilt_start_time;
    // 最后一次执行时间处理器的时间
    mstime_t previous_time;
    // 一个fifo队列,包含了所有需要执行的用户脚本
    list *scripts_queue;
}sentinel;

初始化Sentinel监视的主服务器列表

Sentinel状态中的masters字典记录了所有被sentinel监视的主服务器的相关信息,其中:

  • 字典的键是被监视主服务器的名字
  • 而字典的值则是被监视主服务器对应的 sentinel.c/sentinelRedisInstance 结构

每个sentinelRedisInstance结构(后面简称“实例结构”)代表一个被Sentinel监视的服务器实例,这个实例可以是主服务器,从服务器,或者是另外一个sentinel。

实例结构属性包含:

typedef struct sentinelRedisInstance {

    // 标识值,记录了实例的类型,以及该实例的当前状态
    int flags;

    // 实例的名字
    // 主服务器的名字由用户在配置文件中设置
    // 从服务器以及 Sentinel 的名字由 Sentinel 自动设置
    // 格式为 ip:port ,例如 "127.0.0.1:26379"
    char *name;

    // 实例的运行 ID
    char *runid;

    // 配置纪元,用于实现故障转移
    uint64_t config_epoch;

    // 实例的地址
    sentinelAddr *addr;

    // SENTINEL down-after-milliseconds 选项设定的值
    // 实例无响应多少毫秒之后才会被判断为主观下线(subjectively down)
    mstime_t down_after_period;

    // SENTINEL monitor     选项中的 quorum 参数
    // 判断这个实例为客观下线(objectively down)所需的支持投票数量
    int quorum;

    // SENTINEL parallel-syncs   选项的值
    // 在执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量
    int parallel_syncs;

    // SENTINEL failover-timeout   选项的值
    // 刷新故障迁移状态的最大时限
    mstime_t failover_timeout;

    // ...

} sentinelRedisInstance;

sentinelRedisInstance.addr属性是一个指向sentinelAddr结构的指针,这个结构保存着实例的IP地址和端口号

typedef struct sentinelAddr {

    char *ip;

    int port;

} sentinelAddr;

对Sentinel状态的初始化将引发对masters字典的初始化,而masters字典的初始化是根据被载入的Sentinel配置文件来进行的。

如果用户在启动 Sentinel 时, 指定了包含以下内容的配置文件:


#####################
# redis-master1 configure #
#####################

sentinel monitor redis-master1 127.0.0.1 6379 2

sentinel down-after-milliseconds redis-master1 30000

sentinel parallel-syncs redis-master1 1

sentinel failover-timeout redis-master1 900000

#####################
# redis-master2 configure #
#####################

sentinel monitor redis-master2 127.0.0.1 12345 5

sentinel down-after-milliseconds redis-master2 50000

sentinel parallel-syncs redis-master2 5

sentinel failover-timeout redis-master2 450000

那么 Sentinel 将为主服务器 redis-master1 创建如下图所示的实例结构:

Redis-Sentinel(哨兵模式),看这篇就够了哦_第5张图片
并且为主服务器 redis-master2 创建如下图所示的实例结构:

Redis-Sentinel(哨兵模式),看这篇就够了哦_第6张图片
这两个实例结构又会被保存到 Sentinel 状态的 masters 字典中, 如下图所示:

Redis-Sentinel(哨兵模式),看这篇就够了哦_第7张图片

创建连向主服务器的网络连接

当实例结构初始化完成之后,Sentinel将会开始创建连接Master的网络连接,这一步Sentinel将成为Master的客户端。
Sentinel和Master之间会创建一个命令连接和一个订阅连接:

  • 一个是命令连接, 这个连接专门用于向主服务器发送命令, 并接收命令回复
  • 一个是订阅连接,订阅连接用于Sentinel之间进行信息广播,每个Sentinel和自己监视的主从服务器之间会订阅sentinel:hello频道(注意Sentinel之间不会创建订阅连接,它们通过订阅sentinel:hello频道来获取其他Sentinel的初始信息)

这里需要说一下为什么需要两个连接?

在 Redis 目前的发布与订阅功能中, 被发送的信息都不会保存在 Redis 服务器里面, 如果在信息发送时, 想要接收信息的客户端不在线或者断线, 那么这个客户端就会丢失这条信息。

因此, 为了不丢失 sentinel:hello 频道的任何信息, Sentinel 必须专门用一个订阅连接来接收该频道的信息。

而另一方面, 除了订阅频道之外, Sentinel 还又必须向主服务器发送命令, 以此来与主服务器进行通讯, 所以 Sentinel 还必须向主服务器创建命令连接。

并且因为 Sentinel 需要与多个实例创建多个网络连接, 所以 Sentinel 使用的是异步连接。

当Sentinel服务器初始化完成之后,会每10s向已经连接的被监视的服务器发送INFO命令,主服务器会返回自身的信息,以及它下面的从服务器的信息。

Sentinel也会去主动连接从服务器

Redis-Sentinel(哨兵模式),看这篇就够了哦_第8张图片

获取主服务器信息

sentinel默认会每10秒一次,给主服务器发送info命令,并且通过分析info命令,来判断当前主服务器的信息。

通过分析info命令,sentinel会得到两方面的信息:一是主服务器的运行ID以及其role域记录的服务器角色,二是关于主服务器属下所有从服务器的信息,由slave字符串开头,每行IP记录一个IP地址、端口号、offset(用于与主服务器aof)、lag(延迟时间)等。

因此,sentinel无序建立和从服务器的连接,也可以知道从服务器的情况。sentinel只需要将info获得的返回结果,分析并更新到sentinel的sentinelState结构体的相应属性即可。

另外,sentinel在更新结构体时,还会分析每一个从服务器是否存在,如果是现有的则更新结构体,如果不是现有的则新增一个结构体。
Redis-Sentinel(哨兵模式),看这篇就够了哦_第9张图片
从上述可知,主从服务器sentinelRedisInstance的主要区别,一是flags属性主是SRI_MASTER而从是SRI_SLAVE;二是名称主服务器是sentinel起的,从服务器是IP:端口号;三是主服务器有个slaves属性,指向一个字典,该字典键是从服务器的IP:端口号,值是表示从服务器的sentinelRedisInstance。

获取从服务器信息

当sentinel发现有新的从服务器,除了会为其创建实例结构,还会与其建立连接,连接也是包括订阅连接和命令连接。且默认下,每十秒也会给从服务器发送info命令。

Redis-Sentinel(哨兵模式),看这篇就够了哦_第10张图片
根据info命令,可以提取出以下主要信息:运行ID、角色、主服务器ip与端口、主从连接状态、从服务器优先级、从服务器偏移量

向主服务器和从服务器发送信息

在默认情况下, Sentinel会以每两秒一次的频率,通过命令连接向所有被监视的主服务器和从服务器发送以下格式的命令:

publish _sentinel_:hello ",,,,,,"

这条命令向服务器的_sentinel_:hello频道发送了一条信息,信息的内容由多个参数组成:

其中,以s_开头的参数记录的是Sentinel本身的信息,而m_开头的参数记录的则是主服务器的信息。
Redis-Sentinel(哨兵模式),看这篇就够了哦_第11张图片

接收来自主从服务器频道的信息

接收信息

当Sentinel与一个主服务器或者从服务器建立起订阅连接之后,Sentinel就会通过订阅连接,向服务器发送以下命令:subscribe sentinel:hello,Sentinel对_sentinel_:hello频道的订阅会一直持续到Sentinel与服务器的连接断开为止。

Redis-Sentinel(哨兵模式),看这篇就够了哦_第12张图片
此时实例结构信息如下图所示:

Redis-Sentinel(哨兵模式),看这篇就够了哦_第13张图片

当Sentinel从_sentinel_:hello频道接收到信息时,Sentinel会对这条信息进行分析,提取出信息中的 Sentinel IP地址,Sentinel 端口号,Sentinel 运行ID等八个参数,并进行以下检查:

  • 如果获取到的 runid 与 Sentinel 自己的 runid 相同,那么说明这条信息是 Sentinel 自己发送的,Sentinel 将丢弃这条信息,不做进一步处理
  • 如果信息中记录的 runid 和接收信息的 Sentinel 的 runid 不相同,那么说明这条信息是监视同一个服务器的其他Sentinel 发来的,接收信息的 Sentinel 将根据信息中的各个参数,对相应主服务器的实例结构进行更新

更新sentinels字典

Sentinel 为主服务器创建的实例结构中的 snetinels 字典保存了除 Sentinel 本身之外,所有同样监视这个主服务器的其他 Sentinel 信息,字典的键是sentinel的ip:port,值是对应的sentinel实例。

当一个 sentinel 接受到其他 sentinel 发来的信息时,目标 sentinel 会从信息中提取出以下两方面的参数:

  • 与sentinel有关的参数:sentinel 的ip地址,端口号,运行id和配置纪元
  • 与主服务器有关的参数:sentinel 正在监视的主服务器的名字,ip地址,端口号和配置纪元

根据信息中提取出的主服务器参数,目标sentinel会在自己的 sentinel 状态的 masters 字典中查找相应的主服务器实例结构,然后根据提取出的 sentinel 参数,检查主服务器实例结构的 sentinels 字典中,sentinel 的实例结构是否存在:

  • 如果 sentinel 的实例结构已经存在,那么对源 sentinel 的实例结构进行更新
  • 如果 sentinel 的实例结构不存在,说明 sentinel 是刚刚开始监视主服务器的新 sentinel。目标 sentinel 会为sentinel 创建一个新的实例结构,并将这个结构添加到 sentins 字典里面

创建连向其他sentinel的连接

当sentinel通过频道信息发现一个新的sentinel时,它不仅会为新sentinel在sentinels字典中创建相应的实例结构,还会创建一个连向新sentinel的命令连接,而新sentinel也同样会创建连向这个sentinel的命令连接,最终监视同一主服务器的多个sentinel将形成相互连接的网络。

Redis-Sentinel(哨兵模式),看这篇就够了哦_第14张图片

检测Master是否主观下线

默认情况下,Sentinel 每隔1秒钟,向sentinelRedisInstance 实例中的所有 Master、Slave、Sentinel 发送 PING 命令,通过其他服务器的回复来判断其是否仍然在线。

sentinel down-after-milliseconds redis-master 50000

在Sentinel 的配置文件中,down-after-nilliseconds 选项指定了 sentinel 判断实例进入主观下线所需的时间长度,实例在 down-after-milliseconds 毫秒内,连续向 sentinel 返回无效回复,那么 sentinel 会修改这个实例所对应的实例结构,在结构的 flags 属性中打开 sri_s_down 标识,以此来表示这个实例已经进入主观下线状态。

Redis-Sentinel(哨兵模式),看这篇就够了哦_第15张图片

down-after-nilliseconds选项需要注意的是:

对于监视同一个主服务器的多个Sentinel来说,这些 Sentinel 所设置的 down-after-nilliseconds 选项的值也可能不同,因此,当一个 Sentinel 将主服务器判断为主观下线时,其他 Sentinel 可能仍然认为主服务器处于在线的状态,比如:
Sentinel1 的配置:

sentinel monitor master 127.0.0.1 6379 2
sentinel down-after-milliseconds master 50000

而 Sentinel2 的配置:

sentinel monitor master 127.0.0.1 6379 2
sentinel down-after-milliseconds master 10000

那么当 master 的断线时长超过 10000 毫秒之后,Sentinel2 会将 master 判断为主观下线,而Sentinel1 认为 master 仍然在线。只有当 master 的断线时长超过 50000 毫秒之后,Sentinel1 和Sentinel2 才会都认为 master 进入了主观下线状态。

检测Master是否客观下线

当前Sentinel认为其下线只能处于主观下线状态,要想判断当前Master是否客观下线,还需要询问其他Sentinel,并且所有认为Master主观下线或者客观下线的总和需要达到quorum配置的值,当前Sentinel才会将Master标志为客观下线。

Redis-Sentinel(哨兵模式),看这篇就够了哦_第16张图片
当前Sentinel向sentinelRedisInstance实例中的其他Sentinel发送如下命令:

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

命令询问其他sentinel是否同意主服务器已下线,如下图参数:

Redis-Sentinel(哨兵模式),看这篇就够了哦_第17张图片

接收到命令的 Sentinel,会根据命令中的参数检查主服务器是否下线,检查完成后会返回如下图参数:

Redis-Sentinel(哨兵模式),看这篇就够了哦_第18张图片
接收命令中的回复

根据其他 sentinel 发回的命令回复,sentinel 将统计其他 sentinel 同意主服务器已下线的数量,当这一数量达到配置指定的判断客观下线所需的数量时,sentinel 会将主服务器实例结构 flags 属性的 SRI_O_DOWN 标识打开,表示主服务器已经进入客观下线状态。

客观下线状态的判断条件::

当认为主服务器已经进入下线状态的 Sentinel 的数量,超过 Sentinel 配置中设置的 quorum 参数的值,那么该Sentinel就会认为主服务器已经进入客观下线状态。比如说,如果 Sentinel 在启动时载入了以下配置:sentinel monitor master 127.0.0.1 6379 2,那么包括当前 Sentinel 在内,只要总共有两个 Sentinel 认为主服务器已经进入下线状态,那么当前 Sentinel 就将主服务器判断为客观下线。
又比如说,如果 Sentinel 在启动时载入了以下配置:sentinel monitor master 127.0.0.1 6379 5
那么包括当前 Sentinel 在内,总共要有五个 Sentinel 都认为主服务器已经下线,当前 Sentinel 才会将主服务器判断为客观下线。

选举领头sentinel

当一个主服务器被判断为客户下线后,监视这个下线主服务器的各个sentinel 会进行协商,选举出一个领头sentinel,并由领头 sentinel 对下线主服务器进行故障转移操作:

以下是选举领头 sentinel 的规则和方法

  • 所有在线的 Sentinel 都有被选为领头 Sentinel 的资格,换句话说,监视同一个主服务器的 多个在线 Sentinel 中的任意一个都有可能成为领头Sentinel
  • 每次进行领头 Sentinel 选举之后,不论选举是否成功,所有 Sentinel 的配置纪元 (configuration epoch)的值都会自增一次。 配置纪元实际上就是一个计数器,并没有什么特 别的。
  • 在一个配置纪元里面, 所有 Sentinel 都有一次将某个 Sentinel 设置为局部领头 Sentinel 的机会 并且局部领头一旦设置,在这个配置每个发现主服务器进入客观下线的 Sentinel 都会要求其他 Sentinel 将自己设置为局部领头Sentinel。
  • 当一个 Sentinel(源Sentinel)向另一个 Sentinel(目标Sentinel)发送 SENTINEL ismaster-down-by-addr 命令,并且命令中的 runid 参数不是*符号而是源 Sentinel 的 runid 时,这表示源 Sentinel 要求目标 Sentinel 将前者设置为后者的局部领头 Sentinel
  • Sentinel 设置局部领头 Sentinel 的规则是先到先得:最先向目标 Sentinel 发送设置要求的源 Sentinel 将成为目标 Sentinel 的局部领头 Sentinel ,而之后接收到的所有设置要求都会被目标 Sentinel 拒绝
  • 目标 Sentinel 在接收到 SENTINEL is-master-down-by-addr 命令之后,将向源 Sentinel 返回 一条命令回复,回复中的 leader_runid 参数和 leader_epoch 参数分别记录了目标 Sentinel 的局部领头 Sentinel 的 runid 和配置纪元
  • 源 Sentinel 在接收到目标 Sentinel 返回的命令回复之后,会检查回复中 leader_epoch 参数 的值和自己的配置纪元是否相同,如果相同的话,那么源 Sentinel 继续取出回复中的 leader_runid 参数, 如果 leader_runid 参数的值和源 Sentinel 的 runid 一致,那么表示目标 Sentinel 将源 Sentinel 设置成了局部领头 Sentinel
  • 如果有某个 Sentinel 被半数以上的 Sentinel 设置成了局部领头 Sentinel,那么这个 Sentinel 成为领头 Sentinel。举个例子,在一个由 10 个 Sentinel 组成的 Sentinel 系统里面,只要有大于等于 10/2+1=6 个 Sentinel 将某个Sentinel 设置为局部领头 Sentinel,那么被设置的那个 Sentinel 就会成 为领头 Sentine
  • 因为领头 Sentinel 的产生需要半数以上 Sentinel 的支持,并且每个 Sentinel 在每个配置纪元里面只能设置一次局部领头 Sentinel,所以在一个配置纪元里面,只会出现一个领头 Sentinel
  • 如果在给定时限内,没有一个Sentinel 被选举为领头 Sentinel ,那么各个 Sentinel 将在一段时间之后再次进行选举,直到选出领头 Sentinel 为止

故障转移

选出的领头 Sentinel 开始执行故障转移,操作分为三个步骤:

  • 在已下线的主服务器的从服务器中选中一个从服务器,并将其转换为主服务器
  • 让已下线的主服务器属下的从服务器改为复制新的主服务器
  • 如果已下线的主服务器回复了的话,让其作为新的主服务器的从服务器

选出新的主服务器

故障转移操作第一步要做的就是在已下线主服务器属下的所有从服务器中,挑选出一个状态良好,数据完整的从服务器,然后向这个从服务器发送 slaveof no one 命令,将这个从服务器转换为主服务器。

新的主服务器是怎么挑选出来的?

领头Sentinel会将已下线主服务器的所有从服务器保存到一个列表里面,然后按照以下规则,一项一项地对列表进行过滤:

  • 删除列表中所有处于下线或者断线状态的从服务器,这可以保证列表中剩余的从服务器都是正常在线的。
  • 删除列表中所有最近五秒内没有回复过领头 Sentinel 的 INFO 命令的从服务器,这可以保证列表中剩余的从服务器都是最近成功进行过通信的。
  • 删除所有与已下线主服务器连接断开超过 down-after-milliseconds * 10毫秒的从服务器: down-after-milliseconds 选项指定了判断主服务器下线所需的时间,而删除断开时长超过down-after-milliseconds * 10毫秒的从服务器,则可以保证列表中剩余的从服务器都没有过早地与主服务器断开连接,换句话说,列表中剩余的从服务器保存的数据都是比较新的。
  • 之后,领头 Sentinel 将根据从服务器的优先级,对列表中剩余的从服务器进行排序,并选出其中优先级最高的从服务器。
  • 如果有多个具有相同最高优先级的从服务器,那么领头Sentinel 将按照从服务器的复制偏移量,对具有相同最高优先级的所有从服务器进行排序,并选出其中偏移量最大的从服务器(复制偏移量最大的从服务器就是保存着最新数据的从服务器)。
  • 最后,如果有多个优先级最高、复制偏移量最大的从服务器,那么领头 Sentinel 将按照 runid 对这些从服务器进行排序,并选出其中 runid 最小的从服务器。

修改从服务器的复制目标

通过向从服务器发送 slaveof 命令来实现

将旧的主服务器变为从服务器

当旧的主服务器上线之后,向他发送 slaveof 命令

你可能感兴趣的:(redis,redis,服务器,缓存)