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执行的全部命令了

相关推荐
潘多编程14 分钟前
Java中的状态机实现:使用Spring State Machine管理复杂状态流转
java·开发语言·spring
&梧桐树夏14 分钟前
【算法系列-链表】删除链表的倒数第N个结点
数据结构·算法·链表
QuantumStack18 分钟前
【C++ 真题】B2037 奇偶数判断
数据结构·c++·算法
_阿伟_33 分钟前
SpringMVC
java·spring
代码在改了40 分钟前
springboot厨房达人美食分享平台(源码+文档+调试+答疑)
java·spring boot
权^1 小时前
MySQL--聚合查询、联合查询、子查询、合并查询(上万字超详解!!!)
大数据·数据库·学习·mysql
wclass-zhengge1 小时前
Redis篇(最佳实践)(持续更新迭代)
redis·缓存·bootstrap
wclass-zhengge1 小时前
数据结构篇(绪论)
java·数据结构·算法
Dylanioucn1 小时前
【分布式微服务云原生】探索Redis:数据结构的艺术与科学
数据结构·redis·分布式·缓存·中间件
何事驚慌1 小时前
2024/10/5 数据结构打卡
java·数据结构·算法