Redis中的Sentinel(二)

Sentinel

初始化Sentinel状态。

在应用了Sentinel的专用代码之后,接下来,服务器会初始化一个sentinel.c/sentinelState结构(简称Sentinel状态),这个结构

保存了服务器中所有和Sentinel功能有关的状态(服务器的一般状态仍然由redis.h/redisServer保存);

c 复制代码
struct sentinelState {
// 当前纪元,用于实现故障转移
unit64_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状态的masters属性

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

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

每个sentinelRedisInstance结构(简称实例结构)代表一个被Sentinel监视的Redis服务器实例(instance),这个实例可以是主服务器、从服务器,或者另外一个Sentinel。实例结构包含的属性非常多,下方代码展示了实例结构在表示主服务器时使用的其中一部分属性

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

c 复制代码
typedef struct sentinelAddr {
char *ip;
int port;
} sentinelAddr;

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

sentinelRedisInstance结构

c 复制代码
typedef struct sentinelRedisInstance {
// 标识值,记录了实例的类型,以及该实例的当前状态
int flags;
// 实例的名字
// 主服务器的名字由用户在配置文件中设置
// 从服务器以及Sentinel的名字由Sentinel自动设置
// 格式为ip:port 例如"127.0.0.1:26379"
char *name;

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

// 配置纪元,用于实现故障转移
uint64_t coding_epoch;
// 实例的地址
sentinelAddr *addr;
// SENTINEL down-after-milliseconds选项设定的值
// 实例无响应多少毫秒之后才会被判断为主观下线(subjectively down)
mstime_t down_after_period;

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

// SENTINEL parallel-syncs <master-name> <number>选项的值
// 在执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量
int parallel_syncs;
// SENTINEL failover-timeout <master-name> < ms> 选项的值
// 刷新故障迁移状态的最大时限
mstime_t failover_timeout;
// ....
} sentinelRedisInstance;

例子

  • 举个例子。如果用户在启动Sentinel时,指定了包含以下内容的配置文件:
c 复制代码
# master1 configure
sentinel monitor master1 127.0.0.1 6379 2
sentinel down-after-milliseconds master1 3000
sentinel parallel-syncs master1 1
sentinel failover-timeout master1 900000
c 复制代码
# master2 configure
sentinel monitor master2 127.0.0.1 12345 5
sentinel down-after-milliseconds master2 50000
sentinel parallel-syncs master2 5
sentinel failover-timeout master2 450000

那么Sentinel将为主服务器master1创建如图所示的实例结构,并未主服务器master2创建如图所示的实例结构,而这两个实例结构又会被保存到Sentinel状态的masters字典中


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

初始化Sentinel的最后一步是创建连向被监视主服务器的网络连接,Sentinel将成为主服务器的客户端,它可以向主服务器发送命令,并从命令回复中获取相关的信息。对于每个被Sentinel监视的主服务器来说,Sentinel会创建两个连向主服务器的异步网络连接:

  • 1.一个是命令连接,这个链接专门用于向主服务器发送命令,并接收命令回复
  • 2.另一个是订阅连接,这个连接专门用于订阅主服务器的_sentinel_:hello频道

如图所示,展示了一个Sentinel向被它监视的两个主服务器master1和master2创建命令连接和订阅连接的例子

疑问

为什么有两个连接?

在Redis目前的发布与订阅功能中,被发送的信息都不会保存在Redis服务器里面,如果在信息发送时,想要接收信息的客户端不在线或者断线,那么这个客户端就会丢失这条信息。因此,为了不丢失_sentinel_:hello频道的任何信息,Sentinel必须专门用一个订阅连接来接收该频道的信息。

另一方面,除了订阅频道之外,Sentinel还必须向主服务器发送命令,以此来与主服务器进行通信,所以Sentinel还必须向主服务器创建命令连接。因为Sentinel需要与多个实例创建多个网络连接,所以Sentinel使用的是异步连接

通过这两个连接,Sentinel 可以实时监控 Redis 实例的状态,并在发生故障时迅速做出反应。此外,通过使用两个连接而不是一个,可以增加系统的健壮性,一旦其中一个连接出现问题,Sentinel 仍然可以通过另一个连接与 Redis 进行通信,以继续执行监视和管理操作。总之,Sentinel 向 Redis 主服务器创建两个连接是为了增强监视的可靠性和鲁棒性,确保 Sentinel 能够及时感知到 Redis 实例的状态变化并采取相应的措施。

相关推荐
CoderYanger1 分钟前
Java EE 进阶:5. Spring IoC&DI(第二弹):Spring IoC
java·开发语言·spring boot·spring·面试·职场和发展·java-ee
KaiwuDB5 分钟前
企业级数据库数据保护:KaiwuDB KaiwuDB V3.3.0 发布:S3 冷热分层存储与主备集群能力增强实战解析模场景备份恢复方案解析
数据库·时序数据库·kaiwudb·发版·多模时序数据库·冷热分层存储·主备集群
DataY12 分钟前
MySQL CDC 直接写进 Doris 汇总模型:同步即汇总,明细不用搬两遍
数据库
琳达爱分享15 分钟前
客服改了地址,发货任务把它改了回去:一次没人报错的覆盖
数据库
IT大白鼠18 分钟前
渗透测试实战从靶场搭建到渗透流程——第 8 篇 · 服务型靶标(上):MySQL 双版本写文件链
数据库·mysql·渗透测试
piaoyiren43 分钟前
Python FTP 服务端项目详细功能文档
网络·数据库·python
少年的范儿1 小时前
Windows 安装 MySQL 8.4 教程(ZIP 解压版):配置 my.ini、初始化数据库与启动服务
数据库·windows·mysql
悟天特斯1 小时前
安防一体化:从“各管各的“到“全局联动“
java·大数据·网络·人工智能·物联网
l1t1 小时前
DeepSeek总结的AI 智能体应该用哪种语言搜索其记忆:SQL 还是 SPARQL?
数据库·人工智能·sql
70后写java的老码农1 小时前
Spring Boot 3.x + ShardingSphere 5.x + MyBatis-Plus 3.x:订单分库分表实战(含两个踩坑记录)
java