Redis中的Sentinel(一)

Sentinel

概述

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

例子

  • 举个例子。图中展示了一个Sentinel系统监视服务器的例子其中:
    1.用双环图案表示的是当前的主服务器server1
    2.用单环图表示的是主服务器的三个从服务器server2、server3以及server4
    3.server2、server3、server4三个从服务器正在复制主服务器server1,而Sentinel系统则在监视所有四个服务器
  • 假设这时,主服务器server1进入下线状态,那么从服务器server2、server3、server4对主服务器的复制操作将被中止,并且Sentinel系统会察觉到server1已下线,如图所示(下线的服务器用虚线表示)
  • 当server1的下线时长超过用户设定的下线时长上限时,Sentinel系统就会对
    server1执行故障转义操作:
    1.首先,Sentinel系统会挑选server1属下的其中一个从服务器,并将这个被选中的
    从服务器升级为新的主服务器
    2.之后,Sentinel系统会向server1属性的所有从服务器发送新的复制指令,让它们称为新的主服务器的从服务器,当所有从服务器都开始复制新的主服务器时,故障转移操作执行完毕
    3.另外,Sentinel还会继续监视已下线的server1,并在它重新上线时,将它设置为新的
    主服务器的从服务器

如图所示。Sentinel将系统2升级为新的主服务器,并让服务器server3和server4成为

sever2的从服务器的过程,之后,如果server1重新上线的话,它将被Sentinel系统降级

为server2的从服务器

启动并初始化Sentinel

c 复制代码
redis-sentinel /path(你自己的路径)/sentinel.conf

或者

c 复制代码
redis-server /path(你自己的路径)/sentinel.conf -- sentinel

这两个命令的效果完全相同。

当一个Sentinel启动时,他需要执行以下步骤:

  • 1.初始化服务器
  • 2.将普通Redis服务器使用的代码替换成Sentinel专用代码
  • 3.初始化Sentinel状态
  • 4.根据给定的配置文件,初始化Sentinel的监视主服务器列表。}
  • 5.创建连向主服务器的网络连接

初始化服务器。

首先,因为Sentinel本质上只是一个运行在特殊模式下的Redis服务器,所以启动Sentinel的第一步,就是初始化一个普通的Redsi服务器,不过因为Sentinel执行的工作和普通Redis服务器执行的工作不同,

所以Sentinel的初始化过程和普通Redis服务器的初始化过程并不完全相同。例如,普通服务器在初始化时会通过载入RDB文件或者AOF文件来还原数据库状态,但是因为Sentinel并不使用数据库,所以初始化Sentinel时就不会载入RDB文件或者AOF文件

使用Sentinel专用代码。

启动Sentinel的第二个步骤就是将一部分普通Redis服务器使用的代码替换成Sentinel专用代码。比如说,普通Redis服务器使用redis.h/REDIS_SERVERPORT常量的值作为服务器端口:

c 复制代码
#define REDIS_SERVERPORT 6379

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

c 复制代码
#define REDIS_SENTINEL_PORT 26379

除此之外,普通Redis服务器使用redis.c(6.0版本以上可能在server.c)/redisCommandTable作为服务器的命令表:

c 复制代码
struct redisCommand redisCommandTable[] = {
    {"get",getCommand,2,"read-only fast @string",0,NULL,1,1,1,0,0,0},
{"getex",getexCommand,-2,"write fast @string",0,NULL,1,1,1,0,0,0},
{"set",setCommand,-3,"write use-memory @string",0,NULL,1,1,1,0,0,0},
{"setnx",setnxCommand,3,
     "write use-memory fast @string",0,NULL,1,1,1,0,0,0},
{"setex",setexCommand,4,"write use-memory @string",0,NULL,1,1,1,0,0,0},
{"append",appendCommand,3,"write use-memory fast @string",0,NULL,1,1,1,0,0,0},
{"strlen",strlenCommand,2,"read-only fast @string",0,NULL,1,1,1,0,0,0},
{"del",delCommand,-2,"write @keyspace",0,NULL,1,-1,1,0,0,0},
{"unlink",unlinkCommand,-2,"write fast @keyspace",0,NULL,1,-1,1,0,0,0},
{"exists",existsCommand,-2,"read-only fast @keyspace",0,NULL,1,-1,1,0,0,0},
{"mget",mgetCommand,-2,"read-only fast @string",0,NULL,1,-1,1,0,0,0},
// ....
}

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

实现redis.c/infoCommand函数:

c 复制代码
struct redisCommand sentinelcmds[] = {
    {"ping",pingCommand,1,"fast @connection",0,NULL,0,0,0,0,0},
    {"sentinel",sentinelCommand,-2,"admin",0,NULL,0,0,0,0,0},
    {"subscribe",subscribeCommand,-2,"pub-sub",0,NULL,0,0,0,0,0},
    {"unsubscribe",unsubscribeCommand,-1,"pub-sub",0,NULL,0,0,0,0,0},
    {"psubscribe",psubscribeCommand,-2,"pub-sub",0,NULL,0,0,0,0,0},
    {"punsubscribe",punsubscribeCommand,-1,"pub-sub",0,NULL,0,0,0,0,0},
    {"publish",sentinelPublishCommand,3,"pub-sub fast",0,NULL,0,0,0,0,0},
    {"info",sentinelInfoCommand,-1,"random @dangerous",0,NULL,0,0,0,0,0},
    {"role",sentinelRoleCommand,1,"fast read-only @dangerous",0,NULL,0,0,0,0,0},
    {"client",clientCommand,-2,"admin random @connection",0,NULL,0,0,0,0,0},
    {"shutdown",shutdownCommand,-1,"admin",0,NULL,0,0,0,0,0},
    {"auth",authCommand,-2,"no-auth fast @connection",0,NULL,0,0,0,0,0},
    {"hello",helloCommand,-1,"no-auth fast @connection",0,NULL,0,0,0,0,0},
    {"acl",aclCommand,-2,"admin",0,NULL,0,0,0,0,0,0},
    {"command",commandCommand,-1, "random @connection", 0,NULL,0,0,0,0,0,0}
};

sentinel命令表也解释了为什么在Sentinel模式下Redis服务器不能执行诸如SET、DBSIZE、EVAL等等这些命令,因为服务器根本没有在命令表中载入这些命令。PING、SENTINEL、INFO、SUBSCRIBE、UNSUBSCRIBE、PSUBSCRIBE和PUNSUBSCRIBE这七个命令就是客户端可以对Sentinel执行的全部命令了

相关推荐
Arbori_262153 分钟前
获取oracle表大小
数据库·oracle
王强你强10 分钟前
MySQL 高级查询:JOIN、子查询、窗口函数
数据库·mysql
草巾冒小子11 分钟前
brew 安装mysql,启动,停止,重启
数据库·mysql
用户62799471826218 分钟前
南大通用GBase 8c分布式版本gha_ctl 命令-HI参数详解
数据库
斯汤雷26 分钟前
Matlab绘图案例,设置图片大小,坐标轴比例为黄金比
数据库·人工智能·算法·matlab·信息可视化
腥臭腐朽的日子熠熠生辉31 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian33 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
SQLplusDB33 分钟前
Oracle 23ai Vector Search 系列之3 集成嵌入生成模型(Embedding Model)到数据库示例,以及常见错误
数据库·oracle·embedding
杉之38 分钟前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
喝醉酒的小白1 小时前
SQL Server 可用性组自动种子设定失败问题
数据库