百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

redis专题系列16 -- redis 集群模式之哨兵模式

mhr18 2024-10-26 10:54 22 浏览 0 评论

虽然redis为我们提供了主从模式,但master一旦宕机,那么整个集群则不能够继续写入,需要人工手动指定slave节点为master,这段时间会造成部分请求失败,费时费力,用户体验极差。为了实现master自动切换,redis为我们提供了哨兵模式,以提高redis集群的高可用。

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

集群架构


它由两部分组成:

  • 哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的Redis节点,不存储数据。
  • 数据节点:主节点和从节点都是数据节点。

集群部署简单示例

系统环境: Win10 X64 , redis版本:3.2.100

1.在安装环境下,copy两份redis配置文件,分别为redis.windows.6380.conf,redis.windows.6381.conf,内容如下:

#redis.conf

port 6379

daemonize yes

logfile ""

dbfilename "dump-6379.rdb"

#redis.windows.6380.conf

port 6380

daemonize yes

logfile ""

dbfilename ""

slaveof 127.0.0.1 6379

#redis.windows.6381.conf

port 6381

daemonize yes

logfile ""

dbfilename "dump-6381.rdb"

slaveof 127.0.0.1 6379

配置完成后,一次启动主节点和2个从节点。

redis path\redis.windows.conf

redis path\redis.windows.6380.conf

redis path\redis.windows.6381.conf

查看主从节点状态:

127.0.0.1:6379> info replication

# Replication

role:master

connected_slaves:2

slave0:ip=127.0.0.1,port=6381,state=online,offset=113,lag=1

slave1:ip=127.0.0.1,port=6380,state=online,offset=113,lag=1

master_repl_offset:113

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:2

repl_backlog_histlen:112

2.部署哨兵节点

#sentine.conf

port 26379

daemonize yes

logfile ""

sentinel monitor mymaster 127.0.0.1 6379 2

sentinel failover-timeout mymaster 15000

sentinel config-epoch mymaster 1

bind 127.0.0.1

#sentinel.26380.conf

port 26380

daemonize yes

logfile ""

sentinel monitor mymaster 127.0.0.1 6379 2

sentinel failover-timeout mymaster 15000

sentinel config-epoch mymaster 1

bind 127.0.0.1

本配置文件力求简化,方便大家排查纠错,后续再将哨兵的配置参数详解。

sentinel monitor mymaster 127.0.0.1 6379 2 意思是当前哨兵监控的主节点为127.0.0.1:6379, 节点名称为mymaster(可自定义),最后的2用来判断节点故障:只要2个节点主观认为节点不可用, 才会判定为故障节点并进行故障转移。

在linux上哨兵节点有2中命令来启动:

redis-sentinel sentinel.conf

redis-server sentinel.conf --sentinel

但在windows上我们只能采用第二种启动方式,

启动哨兵节点

redis-server path\sentinel.conf --sentinel

redis-server path\sentinel.26380.conf --sentinel

启动成功后,查看哨兵节点监控信息:

127.0.0.1:26379> info sentinel

# Sentinel

sentinel_masters:1

sentinel_tilt:0

sentinel_running_scripts:0

sentinel_scripts_queue_length:0

sentinel_simulate_failure_flags:0

master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=2

此时可以看到,哨兵节点监控主节点为 127.0.0.1:6379 ,并同时发现了另外两个从节点及总共2个哨兵节点(包含其本身)

细心的朋友会发现哨兵节点的配置文件也追加了新的信息:

# Generated by CONFIG REWRITE

dir "C:\\Users\\jli2"

sentinel config-epoch mymaster 0

sentinel leader-epoch mymaster 0

sentinel known-slave mymaster 127.0.0.1 6380

sentinel known-slave mymaster 127.0.0.1 6381

sentinel known-sentinel mymaster 127.0.0.1 26379 d0b006d092d8da0567bcda0be9983409de053354

sentinel current-epoch 0

其中,dir只是显式声明了数据和日志所在的目录(在哨兵语境下只有日志);known-slave和known-sentinel显示哨兵已经发现了从节点和其他哨兵;带有epoch的参数与配置纪元有关(配置纪元是一个从0开始的计数器,每进行一次领导者哨兵选举,都会+1;领导者哨兵选举是故障转移阶段的一个操作,在后文原理部分会介绍), d0b006d092d8da0567bcda0be9983409de053354 指另外一个哨兵节点的id(如果没有配置,哨兵启动时会自动生成)。

3.故障转移示例

S1.我们尝试kill掉主节点的后台服务,根据端口后找到其pid,拿到pid后,执行kill命令,在win10下,操作如下:

查找6379的pid有两种方法:

1>.启动日志


2>.查找端口号为6379进程的pid, 命令: netstat |findstr 6379

S2.强制kill掉进程号为444的进程:

S3.故障节点转移需要一段时间,过段时间,观察哨兵节点的监控信息:

127.0.0.1:26379> info sentinel

# Sentinel

sentinel_masters:1

sentinel_tilt:0

sentinel_running_scripts:0

sentinel_scripts_queue_length:0

sentinel_simulate_failure_flags:0

master0:name=mymaster,status=ok,address=127.0.0.1:6380,slaves=2,sentinels=2

但是同时可以发现,哨兵节点认为新的主节点仍然有2个从节点,这是因为哨兵在将6380切换成主节点的同时,将6379节点置为其从节点;虽然6379从节点已经挂掉,但是由于哨兵并不会对从节点进行客观下线(其含义将在原理部分介绍),因此认为该从节点一直存在。当6379节点重新启动后,会自动变成6380节点的从节点。下面验证一下。

同时你也可以在任何数据节点看到6379和6380的主从关系:

S4. 数据节点配置文件的更新

# redis.conf 即原来的主节点配置信息,变为6380的从节点

port 6379

daemonize yes

logfile ""

dbfilename "dump-6379.rdb"

bind 127.0.0.1

# Generated by CONFIG REWRITE

dir "C:\\Redis-x64-3.2.100"

slaveof 127.0.0.1 6380

#redis.windows.6380.conf 新主节点

port 6380

daemonize yes

logfile ""

dbfilename "dump-6380.rdb"

# Generated by CONFIG REWRITE

dir "C:\\Users\\jli2"

#redis.windows.6381.conf 更新为6380的从节点

port 6381

daemonize yes

logfile ""

dbfilename "dump-6381.rdb"

slaveof 127.0.0.1 6380

# Generated by CONFIG REWRITE

dir "C:\\Users\\jli2"

#两个哨兵节点

#26379

port 26379

daemonize yes

logfile ""

sentinel myid d0b006d092d8da0567bcda0be9983409de053354

sentinel monitor mymaster 127.0.0.1 6380 2

bind 127.0.0.1

# Generated by CONFIG REWRITE

dir "C:\\Users\\jli2"

sentinel config-epoch mymaster 1

sentinel leader-epoch mymaster 1

sentinel known-slave mymaster 127.0.0.1 6379

sentinel known-slave mymaster 127.0.0.1 6381

sentinel known-sentinel mymaster 127.0.0.1 26380 37e8c55a99ca7ce1c97a1ff19967fd98f2b296d1

sentinel current-epoch

#26379

port 26380

daemonize yes

logfile ""

sentinel myid 37e8c55a99ca7ce1c97a1ff19967fd98f2b296d1

sentinel monitor mymaster 127.0.0.1 6380 2

sentinel failover-timeout mymaster 15000

bind 127.0.0.1

# Generated by CONFIG REWRITE

dir "C:\\Users\\jli2"

sentinel config-epoch mymaster 1

sentinel leader-epoch mymaster 1

sentinel known-slave mymaster 127.0.0.1 6379

sentinel known-slave mymaster 127.0.0.1 6381

sentinel known-sentinel mymaster 127.0.0.1 26379 d0b006d092d8da0567bcda0be9983409de053354

sentinel current-epoch 1

哨兵集群部署注意事项

哨兵系统中的主从节点,与普通的主从节点并没有什么区别,故障发现和转移是由哨兵来控制和完成的。

哨兵节点本质上是Redis节点。

每个哨兵节点,只需要配置监控主节点,便可以自动发现其他的哨兵节点和从节点。

在哨兵节点启动和故障转移阶段,各个节点的配置文件会被重写(Config Rewrite)。

例子中,一个哨兵只监控了一个主节点;实际上,一个哨兵可以监控多个主节点,通过配置多条sentinel monitor即可实现。

基本原理

在原理讲解之前,先了解几个概念:

定时任务:每个哨兵节点维护了3个定时任务。定时任务的功能分别如下:通过向主从节点发送info命令获取最新的主从结构;通过发布订阅功能获取其他哨兵节点的信息;通过向其他节点发送ping命令进行心跳检测,判断是否下线。

主观下线:在心跳检测的定时任务中,如果其他节点超过一定时间没有回复,哨兵节点就会将其进行主观下线。顾名思义,主观下线的意思是一个哨兵节点“主观地”判断下线;与主观下线相对应的是客观下线。

客观下线:哨兵节点在对主节点进行主观下线后,会通过sentinel is-master-down-by-addr命令询问其他哨兵节点该主节点的状态;如果判断主节点下线的哨兵数量达到一定数值,则对该主节点进行客观下线。

需要特别注意的是,客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作。

选举领导者哨兵节点:当主节点被判断客观下线以后,各个哨兵节点会进行协商,选举出一个领导者哨兵节点,并由该领导者节点对其进行故障转移操作。

监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法;Raft算法的基本思路是先到先得:即在一轮选举中,哨兵A向B发送成为领导者的申请,如果B没有同意过其他哨兵,则会同意A成为领导者。选举的具体过程这里不做详细描述,一般来说,哨兵选择的过程很快,谁先完成客观下线,一般就能成为领导者。

故障转移:选举出的领导者哨兵,开始进行故障转移操作,该操作大体可以分为3个步骤:

通过上述几个关键概念,可以基本了解哨兵的工作原理。为了更形象的说明,下图展示了领导者哨兵节点的日志,包括从节点启动到完成故障转移。

下面结合哨兵leader节点的log理解一下:

STEP1: 获取到了主从节点的信息,并通过sub订阅到了其他哨兵的信息。

STEP2:通过ping命令,对主节点进行主管下线

STEP3: 通过询问其他哨兵节点关于主节点的信息来进行主管下线

STEP4:新纪元开始,通过raft算法,选举哨兵leader节点

STEP5:完成故障转移

STEP6:6379重启后设置为从节点。

经验之谈

哨兵节点的数量应不止一个。一方面增加哨兵节点的冗余,避免哨兵本身成为高可用的瓶颈;另一方面减少对下线的误判。此外,这些不同的哨兵节点应部署在不同的物理机上。

哨兵节点的数量应该是奇数,便于哨兵快速通过投票做出“决策”:领导者选举的决策、客观下线的决策等。

各个哨兵节点的配置应一致,包括硬件、参数等;此外,所有节点都应该使用ntp或类似服务,保证时间准确、一致。

哨兵的配置提供者和通知客户端功能,需要客户端的支持才能实现,如前文所说的Jedis;如果开发者使用的库未提供相应支持,则可能需要开发者自己实现。

当哨兵系统中的节点在Docker(或其他可能进行端口映射的软件)中部署时,应特别注意端口映射可能会导致哨兵系统无法正常工作,因为哨兵的工作基于与其他节点的通信,而Docker的端口映射可能导致哨兵无法连接到其他节点。例如,哨兵之间互相发现,依赖于它们对外宣称的IP和port,如果某个哨兵A部署在做了端口映射的Docker中,那么其他哨兵使用A宣称的port无法连接到A。

常用配置参数说明

1.sentinel monitor {masterName} {masterIp} {masterPort} {quorum}

sentinel monitor是哨兵最核心的配置,在前文讲述部署哨兵节点时已说明,其中:masterName指定了主节点名称,masterIp和masterPort指定了主节点地址,quorum是判断主节点客观下线的哨兵数量阈值:当判定主节点下线的哨兵数量达到quorum时,对主节点进行客观下线。建议取值为哨兵数量的一半加1。

2.sentinel down-after-milliseconds {masterName} {time}

sentinel down-after-milliseconds与主观下线的判断有关:哨兵使用ping命令对其他节点进行心跳检测,如果其他节点超过down-after-milliseconds配置的时间没有回复,哨兵就会将其进行主观下线。该配置对主节点、从节点和哨兵节点的主观下线判定都有效。

down-after-milliseconds的默认值是30000,即30s;可以根据不同的网络环境和应用要求来调整:值越大,对主观下线的判定会越宽松,好处是误判的可能性小,坏处是故障发现和故障转移的时间变长,客户端等待的时间也会变长。例如,如果应用对可用性要求较高,则可以将值适当调小,当故障发生时尽快完成转移;如果网络环境相对较差,可以适当提高该阈值,避免频繁误判。

3.sentinel parallel - syncs {masterName} {number}

sentinel parallel-syncs与故障转移之后从节点的复制有关:它规定了每次向新的主节点发起复制操作的从节点个数。例如,假设主节点切换完成之后,有3个从节点要向新的主节点发起复制;如果parallel-syncs=1,则从节点会一个一个开始复制;如果parallel-syncs=3,则3个从节点会一起开始复制。

parallel-syncs取值越大,从节点完成复制的时间越快,但是对主节点的网络负载、硬盘负载造成的压力也越大;应根据实际情况设置。例如,如果主节点的负载较低,而从节点对服务可用的要求较高,可以适量增加parallel-syncs取值。parallel-syncs的默认值是1。

4.sentinel failover - timeout {masterName} {time}

sentinel failover-timeout与故障转移超时的判断有关,但是该参数不是用来判断整个故障转移阶段的超时,而是其几个子阶段的超时,例如如果主节点晋升从节点时间超过timeout,或从节点向新的主节点发起复制操作的时间(不包括复制数据的时间)超过timeout,都会导致故障转移超时失败。

failover-timeout的默认值是180000,即180s;如果超时,则下一次该值会变为原来的2倍。

常用命令

1.基础查询:

通过这些命令,可以查询哨兵系统的拓扑结构、节点信息、配置信息等。

2.增加/移除对主节点的监控:

sentinel monitor mymaster2 192.168.92.128 16379 2:与部署哨兵节点时配置文件中的sentinel monitor功能完全一样,不再详述。

sentinel remove mymaster2:取消当前哨兵节点对主节点mymaster2的监控。

3.强制故障转移:

sentinel failover mymaster:该命令可以强制对mymaster执行故障转移,即便当前的主节点运行完好;例如,如果当前主节点所在机器即将报废,便可以提前通过failover命令进行故障转移。

Java代码使用哨兵模式



Jedis客户端对哨兵提供了很好的支持。如上述代码所示,我们只需要向Jedis提供哨兵节点集合和masterName,构造Jedis SentinelPool对象;然后便可以像使用普通Redis连接池一样来使用了:通过pool.getResource()获取连接,执行具体的命令。

在整个过程中,我们的代码不需要显式的指定主节点的地址,就可以连接到主节点;代码中对故障转移没有任何体现,就可以在哨兵完成故障转移后自动的切换主节点。之所以可以做到这一点,是因为在JedisSentinelPool的构造器中,进行了相关的工作,主要包括以下两点:

遍历哨兵节点,获取主节点信息:遍历哨兵节点,通过其中一个哨兵节点+masterName获得主节点的信息;该功能是通过调用哨兵节点的sentinel get-master-addr-by-name命令实现,该命令示例如下


一旦获得主节点信息,停止遍历(因此一般来说遍历到第一个哨兵节点,循环就停止了)。

增加对哨兵的监听:这样当发生故障转移时,客户端便可以收到哨兵的通知,从而完成主节点的切换。具体做法是:利用Redis提供的发布订阅功能,为每一个哨兵节点开启一个单独的线程,订阅哨兵节点的+switch-master频道,当收到消息时,重新初始化连接池。

总结:

通过客户端原理的介绍,可以加深对哨兵功能的理解,如下:

配置提供者:客户端可以通过哨兵节点+masterName获取主节点信息,在这里哨兵起到的作用就是配置提供者。

需要注意的是,哨兵只是配置提供者,而不是代理。二者的区别在于:

通知:哨兵节点在故障转移完成后,会将新的主节点信息发送给客户端,以便客户端及时切换主节点。

内容有点多,希望大家慢慢系消化!!

相关推荐

如何检查 Linux 服务器是物理服务器还是虚拟服务器?

在企业级运维、故障排查和性能调优过程中,准确了解服务器的运行环境至关重要。无论是物理机还是虚拟机,都存在各自的优势与限制。在很多场景下,尤其是当你继承一台服务器而不清楚底层硬件细节时,如何快速辨识它是...

第四节 Windows 系统 Docker 安装全指南

一、Docker在Windows上的运行原理(一)架构限制说明Docker本质上依赖Linux内核特性(如Namespaces、Cgroups等),因此在Windows系统上无法直...

C++ std:shared_ptr自定义allocator引入内存池

当C++项目里做了大量的动态内存分配与释放,可能会导致内存碎片,使系统性能降低。当动态内存分配的开销变得不容忽视时,一种解决办法是一次从操作系统分配一块大的静态内存作为内存池进行手动管理,堆对象内存分...

Activiti 8.0.0 发布,业务流程管理与工作流系统

Activiti8.0.0现已发布。Activiti是一个业务流程管理(BPM)和工作流系统,适用于开发人员和系统管理员。其核心是超快速、稳定的BPMN2流程引擎。Activiti可以...

MyBatis动态SQL的5种高级玩法,90%的人只用过3种

MyBatis动态SQL在日常开发中频繁使用,但大多数开发者仅掌握基础标签。本文将介绍五种高阶技巧,助你解锁更灵活的SQL控制能力。一、智能修剪(Trim标签)应用场景:动态处理字段更新,替代<...

Springboot数据访问(整合Mybatis Plus)

Springboot整合MybatisPlus1、创建数据表2、引入maven依赖mybatis-plus-boot-starter主要引入这个依赖,其他相关的依赖在这里就不写了。3、项目结构目录h...

盘点金州勇士在奥克兰13年的13大球星 满满的全是...

见证了两个月前勇士与猛龙那个史诗般的系列赛后,甲骨文球馆正式成为了历史。那个大大的红色标志被一个字母一个字母地移除,在周四,一切都成为了过去式。然而这座,别名为“Roaracle”(译注:Roar怒吼...

Mybatis入门看这一篇就够了(mybatis快速入门)

什么是MyBatisMyBatis本是apache的一个开源项目iBatis,2010年这个项目由apachesoftwarefoundation迁移到了googlecode,并且改名为M...

Springboot数据访问(整合druid数据源)

Springboot整合druid数据源基本概念SpringBoot默认的数据源是:2.0之前:org.apache.tomcat.jdbc.pool.DataSource2.0及之后:com.z...

Linux 中的 &quot;/etc/profile.d&quot; 目录有什么作用 ?

什么是/etc/profile.d/目录?/etc/profile.d/目录是Linux系统不可或缺的一部分保留配置脚本。它与/etc/profile文件相关联,这是一个启动脚本,该脚...

企业数据库安全管理规范(企业数据库安全管理规范最新版)

1.目的为规范数据库系统安全使用活动,降低因使用不当而带来的安全风险,保障数据库系统及相关应用系统的安全,特制定本数据库安全管理规范。2.适用范围本规范中所定义的数据管理内容,特指存放在信息系统数据库...

Oracle 伪列!这些隐藏用法你都知道吗?

在Oracle数据库中,有几位特殊的“成员”——伪列,它们虽然不是表中真实存在的物理列,但却能在数据查询、处理过程中发挥出意想不到的强大作用。今天给大家分享Oracle伪列的使用技巧,无论...

Oracle 高效处理数据的隐藏神器:临时表妙用

各位数据库搬砖人,在Oracle的代码世界里闯荡,处理复杂业务时,是不是总被数据“搅得头大”?今天给大家安利一个超实用的隐藏神器——临时表!当你需要临时存储中间计算结果,又不想污染正式数据表...

Oracle 数据库查询:多表查询(oracle多表关联查询)

一、多表查询基础1.JOIN操作-INNERJOIN:返回两个表中满足连接条件的匹配行,不保留未匹配数据。SELECTa.emp_id,b.dept_nameFROMempl...

一文掌握怎么利用Shell+Python实现多数据源的异地备份程序

简介:在信息化时代,数据安全和业务连续性已成为企业和个人用户关注的焦点。无论是网站数据、数据库、日志文件,还是用户上传的文档、图片等,数据一旦丢失,损失难以估量。尤其是当数据分布在多个不同的目录、服务...

取消回复欢迎 发表评论: