redis 优化系列(四)哨兵机制

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis Sentinel(哨兵) 是一个分布式集群架构,其中包含若干个 Sentinel 节点和 Redis 数据节点,每个 Sentinel 节点会对数据节点和其余 Sentinel 节点进行监控,当它发现节点不可达时,会对节点做下线标识。

一、redis主从复制的问题:

Redis 复制有一个缺点,当主机 Master 宕机以后,我们需要人工操作来解决切换,比如使用 slaveof no one 。实际上主从复制并没有实现,高可用, 高可用侧重备份机器, 利用集群中系统的冗余,当系统中某台机器发生损坏的时候,其他后备的机器可以迅速的接替它来启动服务。

如下图所示:

网络异常,图片无法展示
|

一旦主节点宕机,写服务无法使用,就需要手动去切换,重新选取主节点,手动设置主从关系。

那么如何解决呢?如果我们有一个监控程序能够监控各个机器的状态及时作出调整,将手动的操作变成自动的。redis的Sentinel(哨兵)的出现就是为了解决这个问题。

二、哨兵机制的原理及实现

Redis Sentinel(哨兵) 是一个分布式集群架构,其中包含若干个 Sentinel 节点和 Redis 数据节点,每个 Sentinel 节点会对数据节点和其余 Sentinel 节点进行监控,当它发现节点不可达时,会对节点做下线标识。如果被标识的是主节点,它还会和其他 Sentinel 节点进行“协商”,当大多数 Sentinel 节点都认为主节点不可达时,它们会选举出一个 Sentinel 节点来完成自动故障转移的工作,同时会将这个变化实时通知给 Redis 应用方。整个过程完全是自动的,不需要人工来介入,所以这套方案很有效地解决了 Redis 的高可用问题。

注:哨兵(Sentinel) 其实也是一个redis只不过它不是用来存储数据的,而哨兵不止一台,会有多台(最好或者必须 部署多台哨兵)。哨兵是一个独立进程,作为进程,它会独立运行。

一句话解释:哨兵是用来监控redis master主节点的状态的工具,并做出相应反映。比如说 当前redis的主节点挂掉了,哨兵会自动从redis 从节点中选举出一台继续作为主节点,来继续提供redis主从集群服务。

如下图所示:

网络异常,图片无法展示
|

注意:由上图可知,client客户端并不是直接连接的redis主机,而是连接的哨兵(哨兵是一个集群,有多台哨兵),然后哨兵监控主节点的redis状态(不是实时监控,而是定时监控),然后哨兵会返回主机的相关服务信息

****

2.1 基本的故障转移流程:

1)主节点出现故障,此时两个从节点与主节点失去连接,主从复制失败。

网络异常,图片无法展示
|

2)每个 Sentinel 节点通过定期监控发现主节点出现了故障

网络异常,图片无法展示
|

3)多个 Sentinel 节点对主节点的故障达成一致会选举出其中一个节点作为领导者负责故障转移。

网络异常,图片无法展示
|

4)Sentinel 领导者节点执行了故障转移,整个过程基本是跟我们手动调整一致的,只不过是自动化完成的。

网络异常,图片无法展示
|

5)故障转移后整个 Redis Sentinel 的结构,重新选举了新的redis master 主节点。

网络异常,图片无法展示
|

****

2.2 Redis Sentinel 具有以下几个功能:

①、监控:Sentinel 节点会定期检测 Redis 数据节点、其余 Sentinel 节点是否可达。(一个哨兵可以监控多套主从结构,主节点)****

②、通知:Sentinel 节点会将故障转移的结果通知给应用方。

③、主节点故障转移:实现从节点晋升为主节点并维护后续正确的主从关系。

④、配置提供者:在 Redis Sentinel 结构中,客户端在初始化的时候连接的是 Sentinel 节点集合,从中获取主节点信息。

同时Redis Sentinel 包含了若个 Sentinel 节点(一般起步至少是3台),这样做也带来了两个好处:

①、对于节点的故障判断是由多个 Sentinel 节点共同完成,这样可以有效地防止误判。

②、Sentinel 节点集合是由若干个 Sentinel 节点组成的,这样即使个别 Sentinel 节点不可用,整个 Sentinel 节点集合依然是健壮的。

但是 Sentinel 节点本身就是独立的 Redis 节点,只不过它们有一些特殊,它们不存储数据,只支持部分命令。

三、案例:配置哨兵

环境:

1台master主节点 redis-master(ip:172.10.0.2)

2台slave从节点   redis-slave(ip:172.10.0.3)、redis-slave2(ip:172.10.0.4)

3台哨兵服务节点  redis-sentinel1(ip:172.10.0.9)、redis-sentinel2(ip:172.10.0.10)、redis-sentinel3(ip:172.10.0.11)

架构环境列表如下:

容器名称         容器IP地址      映射端口号       服务运行模式

redis-sentinel1    172.10.0.9      22530->26379      sentinel

redis-sentinel2    172.10.0.10     22531->26379      sentinel

redis-sentinel3    172.10.0.11     22532->26379      sentinel

redis-master      172.10.0.2      6380->6379        Master

redis-slave       172.10.0.3      6381->6379        Slave

redis-slave2      172.10.0.4      6382->6379        Slave

3.1 由于前面几篇博文我们已经创建了一主一从,所以这里在创建一台redis从节点,变成1主2从的架构

#创建一台redis从节点``docker run -itd --name redis-slave2 --net mynetwork -p 6382:6379 --ip 172.10.0.4 redis` `#进入该容器并修改redis配置文件,指定主节点配置``docker ``exec` `-it redis-slave2 ``bash` `#修改配置文件(这里就不演示了。。可看该系列博文的第一篇)

3.2 创建三台哨兵服务节点,并分别进入三台哨兵服务节点容器里面

#创建三台哨兵服务节点``docker run -itd --name redis-sentinel1 --net mynetwork -p 22530:26379 --ip 172.10.0.9 redis``docker run -itd --name redis-sentinel2 --net mynetwork -p 22531:26379 --ip 172.10.0.10 redis``docker run -itd --name redis-sentinel3 --net mynetwork -p 22532:26379 --ip 172.10.0.11 redis` `#分别进入三台哨兵服务节点容器里面``docker ``exec` `-it redis-sentinel1 ``bash``docker ``exec` `-it redis-sentinel2 ``bash``docker ``exec` `-it redis-sentinel3 ``bash

3.3 分别修改三台哨兵配置文件(redis-sentinel.conf)

vi` `/etc/redis-sentinel``.conf` `#1、为了省事方便。。我们做如下这2项修改。。``将 ``# bind 127.0.0.1 192.168.1.1 修改为 bind 0.0.0.0``将 ``# protected-mode no 修改为 protected-mode no 也就是取消前面的#号` `#2、修改哨兵服务要监控的主节点redis的ip地址``将 sentinel monitor mymaster 127.0.0.1 6379 2 修改为 sentinel monitor mymaster 172.10.0.2 6379 2` `#3、保存修改后的文件``#4、redis-sentinel2和redis-sentinel3容器里面的哨兵配置文件redis-sentinel.conf的修改也是这样修改。。

网络异常,图片无法展示
|

网络异常,图片无法展示
|

3.4 分别进入三台哨兵服务节点容器里面启动三台哨兵服务

#redis-sentinel1容器里面执行以下命令``redis-sentinel ``/etc/redis-sentinel``.conf &` `#redis-sentinel2容器里面执行以下命令``redis-sentinel ``/etc/redis-sentinel``.conf &` `#redis-sentinel3容器里面执行以下命令``redis-sentinel ``/etc/redis-sentinel``.conf &

3.5 为了验证是否配置成功,可以查看哨兵日志(查看任意一台哨兵里面的日志即可,因为3台哨兵服务节点配置都是一模一样的)

vi` `/var/log/redis/sentinel``.log

网络异常,图片无法展示
|

3.6 进入redis主节点这台服务容器里面,并kill掉这台服务的进程,使之挂掉。让哨兵服务自动从N台从redis服务节点中选取其中一台从服务节点成为新的主(master)节点

①、进入主节点服务容器里面

docker ``exec` `-it redis-master ``bash

②、查看redis端口占用详情

netstat` `-apn |``grep` `6379

网络异常,图片无法展示
|

③、kill掉该进程,然后再次查看端口占用情况,如果结果中没有相关端口对应的相关进程则kill成功,具体看以下截图

kill` `31` `netstat` `-apn |``grep` `6379

网络异常,图片无法展示
|

至此。。我们就把主节点的redis给kill掉了,然后稍等几秒钟(或几十秒钟,具体看配置文件中的配置),查看一下哨兵在这几台从redis节点中选取了那一台从节点使之变成了主节点

3.7 再次查看哨兵日志,看一下哨兵选取了那台从节点变成了主节点

vi` `/var/log/redis/sentinel``.log

网络异常,图片无法展示
|

从以上图片中可以看到哨兵选举了172.10.0.3这台ip地址的从节点作为redis主从架构中的主节点,也就是使这台没有挂掉的从节点从slave晋升成为了master。ps:172.10.0.3这台ip地址对应的容器名字:redis-slave

3.8 进入redis-slave这台服务容器查看redis相关服务信息验证一下是否已成为主节点

网络异常,图片无法展示
|

ok。。从以上截图中可以看到该节点确实已经成为了主节点,并且 offset 偏移量也不是从0开始的。。也就是意味着主从复制数据并不是从头开始的。。至此哨兵搭建使用成功。。

四、Sentinel 的核心配置

①、sentinel monitor mymaster 127.0.0.1 7000 2

监控的主节点的名字、IP 和端口,最后一个2的意思是有几台 Sentinel 发现有问题,就会发生故障转移,例如 配置为2,代表至少有2台 Sentinel 节点认为主节点不可达,那么这个不可达的判定才是客观的。对于设置的越小,那么达到下线的条件越宽松,反之越严格。一般建议将其设置为 Sentinel 节点的一半加1

②、sentinel down-after-millseconds mymaster 30000

这个是超时的时间(单位:毫秒)。打个比方,当你去 ping 一个机器的时候,多长时间后仍 ping 不通,那么就认为它是有问题的

③、sentinel parallel-syncs mymaster 1

当 Sentinel 节点集合对主节点故障判定达成一致时,Sentinel 领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,parallel-syncs 就是用来限制在一次故障转移之后,每次向新的主节点发起复制操作的从节点个数,指出 Sentinel 属于并发还是串行。1代表每次只能复制一个,可以减轻 Master 的压力

网络异常,图片无法展示
|

④、sentinel auth-pass <master-name><password>

如果 Sentinel 监控的主节点配置了密码,sentinel auth-pass 配置通过添加主节点的密码,防止 Sentinel 节点对主节点无法监控

⑤、sentinel failover-timeout mymaster 180000

表示故障转移的时间

五、Sentinel常用命令

sentinel支持的合法命令如下:

①、sentinel masters 显示被监控的所有master以及它们的状态

②、sentinel master <master name> 显示指定master的信息和状态

③、sentinel slaves <master name> 显示指定master的所有slave以及它们的状态

④、sentinel get-master-addr-by-name <master name> 返回指定master的ip和端口,如果正在进行failover或者failover已经完成,将会显示被提升为master的slave的ip和端口

⑤、sentinel failover <master name> 强制sentinel执行failover,并且不需要得到其他sentinel的同意。但是failover后会将最新的配置发送给其他sentinel

⑥、sentinel failover-timeout mymaster 10000 这个参数设置集群 从 判断节点挂掉,到执行failover操作(即重新选举master节点)的时间

⑦、sentinel remove <name> 命令sentinel放弃对某个master的监听

六、应用端调用

Master可能会因为某些情况宕机了,如果在客户端是固定一个地址去访问,肯定是不合理的,所以客户端请求是请求哨兵,从哨兵获取主机地址的信息,或者是从机的信息。可以简单实现一个例子

1、随机选择一个哨兵连接,获取主机、从机信息

2、模拟客户端定时访问,实现简单轮训效果,轮询从节点

3、连接失败重试访问

代码简单模拟实现(php代码举例)

class` `Round``{``  ``static` `$lastIndex` `=0;` `  ``public` `function` `select(``$list``)``  ``{``    ``$currentIndex` `= self::``$lastIndex``; ``//当前的index``    ``$value`    `=``$list``[``$currentIndex``];``    ` `    ``if``(``$currentIndex` `+1 > ``count``(``$list``) -1)``    ``{``      ``self::``$lastIndex` `=0;``    ``}``    ``else``    ``{``      ``self::``$lastIndex``++;``    ``}``    ` `    ``return` `$value``;``  ``}``}` `/********华丽的分割线*********/` `$sentinelConf` `= [``  ``[``'ip'``=>``'47.98.147.49'``,``'port'``=>22530],``  ``[``'ip'``=>``'47.98.147.49'``,``'port'``=>22531],``  ``[``'ip'``=>``'47.98.147.49'``,``'port'``=>22532]``];` `//随机访问``$sentinelInfo` `=``$sentinelConf``[``array_rand``(``$sentinelConf``)];` `$redis` `=``new` `Redis();``$redis``->connect(``$sentinelInfo``[``'ip'``], ``$sentinelInfo``[``'port'``]);``$slavesInfo` `=``$redis``->rawCommand(``'SENTINEL'``, ``'slaves'``, ``'mymaster'``);` `$slaves` `= [];` `foreach` `(``$slavesInfo` `as` `$val``)``{``  ``$slaves``[] = [``'ip'``=>``$val``[3], ``'port'``=>``$val``[5]];``}` `//加载到缓存当中,可以记录这次访问的时间跟上次的访问时间` `//模拟客户端访问(这里用了swoole的定时操作)``swoole_timer_tick(600,``function` `() ``use``(``$slaves``) {``  ` `  ``//轮询``  ``$slave``=(``new` `Round``())->select(``$slaves``);``  ``try``  ``{``    ``$redis` `=``new` `Redis();``    ``$redis``->connect(``$slave``[``'ip'``], ``$slave``[``'port'``]);``    ``var_dump(``$slave``, ``$redis``->get(``'wzyl'``));``  ``}``  ``catch` `(\RedisException ``$e``)``  ``{` `  ``}` `});` `//阻塞在这里

总结redis主从、哨兵、集群的概念:

【redis主从】:

是备份关系, 我们操作主库,数据也会同步到从库。 如果主库机器坏了,从库可以上。就好比你 D盘的片丢了,但是你移动硬盘里边备份有。

【redis哨兵】:

哨兵保证的是HA(高可用),保证特殊情况故障自动切换,哨兵盯着你的“redis主从集群”,如果主库死了,它会告诉你新的老大是谁。

哨兵:主要针对redis主从中的某一个单节点故障后,无法自动恢复的解决方案。(哨兵 保证redis主从的高可用)

【redis集群】:

集群保证的是高并发,因为多了一些兄弟帮忙一起扛。同时集群会导致数据的分散,整个redis集群会分成一堆数据槽,即不同的key会放到不不同的槽中。

集群主要针对单节点容量、高并发问题、线性可扩展性的解决方案。

集群:是为了解决redis主从复制中 单机内存上限和并发问题,假如你现在的服务器内存为256GB,当达到这个内存时redis就没办法再提供服务,同时数据量能达到这个地步写数据量也会很大,容易造成缓冲区溢出,造成从节点无限的进行全量复制导致主从无法正常工作。

相关文章
|
18天前
|
缓存 运维 监控
Redis 7.0 高性能缓存架构设计与优化
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Redis 7.0高性能缓存架构,探索函数化编程、多层缓存、集群优化与分片消息系统,用代码在二进制星河中谱写极客诗篇。
|
1月前
|
监控 NoSQL Redis
Redis哨兵机制
Redis哨兵机制用于解决主从复制中主节点故障无法自动恢复的问题。通过独立进程监控主节点状态,在主节点宕机时,多个哨兵协作选举新主节点并完成故障转移,实现高可用性。哨兵机制具备监控、故障转移和通知功能,支持自动切换主从关系,但无法提升存储容量和完全避免数据丢失。
|
4月前
|
缓存 NoSQL 算法
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
1168 7
|
5月前
|
缓存 NoSQL 算法
Redis数据库的键值过期和删除机制
我们需要注意的是,虽然Redis提供了这么多高级的缓存机制,但在使用过程中,必须理解应用的特性,选择合适的缓存策略,才能最大化Redis的性能。因此,在设计和实施应用程序时,理解应用的数据访问模式,以及这些模式如何与Redis的缓存机制相互作用,尤为重要。
198 24
|
7月前
|
缓存 NoSQL Redis
Redis如何优化频繁命令往返造成的性能瓶颈?
频繁的命令往返是Redis性能优化中需要重点关注的问题。通过使用Pipeline、Lua脚本、事务、合并命令、连接池以及合理设置网络超时,可以有效减少网络往返次数,优化Redis的性能。这些优化措施不仅提升了Redis的处理能力,还能确保系统在高并发情况下的稳定性和可靠性。
200 14
|
8月前
|
缓存 NoSQL Redis
Redis原理—3.复制、哨兵和集群
详细介绍了Redis的复制原理、哨兵原理和集群原理。
|
9月前
|
存储 监控 NoSQL
NoSQL与Redis配置与优化
通过合理配置和优化Redis,可以显著提高其性能和可靠性。选择合适的数据结构、优化内存使用、合理设置持久化策略、使用Pipeline批量执行命令、以及采用分布式集群方案,都是提升Redis性能的重要手段。同时,定期监控和维护Redis实例,及时调整配置,能够确保系统的稳定运行。希望本文对您在Redis的配置与优化方面有所帮助。
165 23
|
9月前
|
缓存 NoSQL JavaScript
Vue.js应用结合Redis数据库:实践与优化
将Vue.js应用与Redis结合,可以实现高效的数据管理和快速响应的用户体验。通过合理的实践步骤和优化策略,可以充分发挥两者的优势,提高应用的性能和可靠性。希望本文能为您在实际开发中提供有价值的参考。
197 11
|
9月前
|
NoSQL API Redis
在C程序中实现类似Redis的SCAN机制的LevelDB大规模key分批扫描
通过上述步骤,可以在C程序中实现类似Redis的SCAN机制的LevelDB大规模key分批扫描。利用LevelDB的迭代器,可以高效地遍历和处理数据库中的大量键值对。该实现方法不仅简单易懂,还具有良好的性能和扩展性,希望能为您的开发工作提供实用的指导和帮助。
135 7
|
9月前
|
存储 监控 NoSQL
NoSQL与Redis配置与优化
通过合理配置和优化Redis,可以显著提高其性能和可靠性。选择合适的数据结构、优化内存使用、合理设置持久化策略、使用Pipeline批量执行命令、以及采用分布式集群方案,都是提升Redis性能的重要手段。
174 7