当前位置: 首页 > java >正文

Redis学习其三(订阅发布,主从复制,哨兵模式)

文章目录

  • 9.Redis订阅与发布
    • 9.1发布订阅命令
    • 9.2示例
  • 10.Redis主从复制
    • 10.1概念
    • 10.2环境配置
    • 10.3集群搭建(一主二从配置)
    • 10.4使用规则&原理
  • 11.哨兵模式
    • 11.1基本概念
    • 11.2工作原理
    • 11.3使用案例
  • 12.缓存穿透,雪崩(待拓展)
    • 12.1缓存穿透
    • 12.2缓存击穿
    • 12.3缓存雪崩

9.Redis订阅与发布

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

Redis 发布订阅 | 菜鸟教程

9.1发布订阅命令

下表列出了 redis 发布订阅常用命令:
在这里插入图片描述

9.2示例

------------订阅端----------------------
127.0.0.1:6379> SUBSCRIBE sakura # 订阅sakura频道
Reading messages... (press Ctrl-C to quit) # 等待接收消息
1) "subscribe" # 订阅成功的消息
2) "sakura"
3) (integer) 1
1) "message" # 接收到来自sakura频道的消息 "hello world"
2) "sakura"
3) "hello world"
1) "message" # 接收到来自sakura频道的消息 "hello i am sakura"
2) "sakura"
3) "hello i am sakura"--------------消息发布端-------------------
127.0.0.1:6379> PUBLISH sakura "hello world" # 发布消息到sakura频道
(integer) 1
127.0.0.1:6379> PUBLISH sakura "hello i am sakura" # 发布消息
(integer) 1-----------------查看活跃的频道------------
127.0.0.1:6379> PUBSUB channels
1) "sakura"-------------其他指令--------------
#订阅符合模式的频道(PSUBSCRIBE)
#订阅所有以 news. 开头的频道
PSUBSCRIBE news.*#退订指定频道(UNSUBSCRIBE)
UNSUBSCRIBE sports.news#退订符合模式的频道(PUNSUBSCRIBE)
PUNSUBSCRIBE news.*#查看订阅与发布系统状态(PUBSUB)
#查看频道的订阅者数量
PUBSUB NUMSUB tech.news#查看符合模式的频道数量
PUBSUB NUMPAT news.*

10.Redis主从复制

10.1概念

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower), 数据的复制是单向的!只能由主节点复制到从节点(主节点以写为主、从节点以读为主)。

默认情况下,每台Redis服务器都是主节点,一个主节点可以有0个或者多个从节点,但每个从节点只能由一个主节点。

作用

  1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
  2. 故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
  3. 负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
  4. 高可用基石:主从复制还是哨兵和集群能够实施的基础。

为什么使用集群

  1. 单台服务器难以负载大量的请求
  2. 单台服务器故障率高,系统崩坏概率大
  3. 单台服务器内存容量有限。

10.2环境配置

配置文件有一个replication模块 。

查看当前库的信息:info replication

127.0.0.1:6379> info replication
# Replication
role:master # 角色
connected_slaves:0 # 从机数量
master_replid:3b54deef5b7b7b7f7dd8acefa23be48879b4fcff
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

既然需要启动多个服务,就需要多个配置文件。每个配置文件对应修改以下信息:

  • 端口号
  • pid文件名
  • 日志文件名
  • rdb文件名

启动单机多服务集群:

在这里插入图片描述

10.3集群搭建(一主二从配置)

默认情况下,每台Redis服务器都是主节点;所以只用配置从机即可。

因为是单机多服务,一主(79)二从(80,81)。(这里79是指6379端口,也是服务的标识)。

使用SLAVEOF host port就可以为从机配置主机了。

在这里插入图片描述

然后主机上也能看到从机的状态:

在这里插入图片描述

我们这里是使用命令搭建,是暂时的,真实开发中应该在从机的配置文件中进行配置,这样的话是永久的。

10.4使用规则&原理

  1. 从机只能读,不能写,主机可读可写但是多用于写。

     127.0.0.1:6381> set name sakura # 从机6381写入失败
    (error) READONLY You can't write against a read only replica.127.0.0.1:6380> set name sakura # 从机6380写入失败
    (error) READONLY You can't write against a read only replica.127.0.0.1:6379> set name sakura
    OK
    127.0.0.1:6379> get name
    "sakura"
    
  2. 当主机断电宕机后,默认情况下从机的角色不会发生变化 ,集群中只是失去了写操作,当主机恢复以后,又会连接上从机恢复原状。

  3. 当从机断电宕机后,若不是使用配置文件配置的从机,再次启动后作为主机是无法获取之前主机的数据的,若此时重新配置称为从机,又可以获取到主机的所有数据。这里就要提到一个同步原理。

  4. 第二条中提到,默认情况下,主机故障后,不会出现新的主机,有两种方式可以产生新的主机:

    • 从机手动执行命令slaveof no one,这样执行以后从机会独立出来成为一个主机。(人为选定,哪个从机执行的命令哪个就会变为主机)
    • 使用哨兵模式(自动选举)

如果主机断开了连接,我们可以使用SLAVEOF no one让自己变成主机!其他的节点就可以手动连接到最新的主节点(手动)!如果这个时候旧主机修复了,如果想恢复之前的主从模式,需要重新连接,也就是说新主机还是作为集群主机,而恢复的旧主机相当于一个单独的redis服务(默认主机)。

如果有新的从机进入集群,则会和集群的数据保持一致,总之,集群的数据总是一致的,无论宕机重连还是新增从机。那他是如何保证的呢?

  1. 全量复制
    • 主节点执行 BGSAVE 生成 RDB 文件,并将文件发送给从节点。
    • 从节点清空当前数据,加载 RDB 文件。
  2. 增量复制
    • 主节点将写命令写入复制缓冲区(replication buffer)。
    • 从节点通过长连接接收这些命令并执行,保持数据同步。

11.哨兵模式

Redis 哨兵(Sentinel)模式是在主从复制的基础上,为了实现 Redis 主节点故障自动切换而设计的一种高可用方案。它可以自动监控 Redis 主节点和从节点的运行状态,当主节点出现故障时,自动将一个从节点晋升为主节点,其他从节点指向新的主节点进行数据复制,从而保证系统的高可用性。

11.1基本概念

  • 哨兵节点:哨兵模式由一个或多个哨兵节点组成,哨兵节点是特殊的 Redis 节点,不存储数据,主要负责监控 Redis 主从节点的运行状态,并且在主节点出现故障时自动执行故障转移操作。
  • 监控:哨兵节点会定期向主节点和从节点发送 PING 命令,通过节点的响应情况判断节点是否正常运行。
  • 故障转移:当哨兵节点发现主节点出现故障(主观下线和客观下线判断)后,会从从节点中挑选一个合适的节点晋升为主节点,然后通知其他从节点切换到新的主节点进行数据复制。

单哨兵模式:

在这里插入图片描述

多哨兵模式:

在这里插入图片描述

11.2工作原理

  1. 监控:哨兵节点以一定的频率向主节点和从节点发送心跳检测命令(PING 命令),以判断节点是否正常运行。每个哨兵节点都有一个 down-after-milliseconds 配置参数,用于指定如果在指定时间内没有收到节点的响应,就认为该节点主观下线(Subjectively Down,简称 SDOWN)。
  2. 主观下线判断:如果一个哨兵节点发现主节点在 down-after-milliseconds 时间内没有响应 PING 命令,或者直接连接主节点失败,那么这个哨兵节点就会将主节点标记为主观下线状态。
  3. 客观下线判断:当一个哨兵节点将主节点标记为主观下线后,它会向其他哨兵节点发送 is-master-down-by-addr 命令,询问其他哨兵节点对主节点的判断。当有足够数量(超过配置的 quorum 值)的哨兵节点都认为主节点主观下线时,就会将主节点标记为客观下线(Objectively Down,简称 ODOWN)。只有主节点会被标记为客观下线,从节点只会被标记为主观下线。
  4. 故障转移:当主节点被标记为客观下线后,哨兵节点会发起一次选举(投票/选举算法),选举出一个哨兵节点来执行故障转移操作。选举过程基于 Raft 算法实现。被选举出的哨兵节点会从从节点中挑选一个节点晋升为主节点,挑选依据包括节点的优先级(slave-priority 配置)、复制偏移量(复制的数据量)等。然后,哨兵节点会向新的主节点发送 slaveof no one 命令,使其成为主节点,接着向其他从节点发送 slaveof 命令,让它们指向新的主节点进行数据复制。
  5. 通知:故障转移完成后,哨兵节点会向客户端发送通知,告知主节点已经发生了变化。

11.3使用案例

在 Redis 哨兵模式里,每个哨兵都是以独立进程的形式存在。可以通过 redis-sentinel 命令来启动哨兵服务。

哨兵的核心配置

sentinel monitor mymaster 127.0.0.1 6379 1
  • 数字1表示 :当一个哨兵主观认为主机断开,就可以客观认为主机故障,然后开始选举新的主机。

测试(xxx代表配置文件路径)

redis-sentinel xxx/sentinel.conf 

成功启动哨兵模式

在这里插入图片描述

此时哨兵监视着我们的主机6379,当我们断开主机后:

在这里插入图片描述

哨兵模式优缺点

优点:

  1. 哨兵集群,基于主从复制模式,所有主从复制的优点它都有
  2. 主从可以切换,故障可以转移,系统的可用性更好
  3. 哨兵模式是主从模式的升级,手动到自动,更加健壮

缺点:

  1. Redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦
  2. 实现哨兵模式的配置其实是很麻烦的,里面有很多配置项

完整的哨兵模式配置文件 sentinel.conf

# Example sentinel.conf# 哨兵sentinel实例运行的端口 默认26379
port 26379# 哨兵sentinel的工作目录
dir /tmp# 哨兵sentinel监控的redis主节点的 ip port 
# master-name  可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,
这个数字越小,完成failover所需的时间就越长,
但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1# 故障转移的超时时间 failover-timeout 可以用在以下这些方面: 
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。  
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000# SCRIPTS EXECUTION#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,
#这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,
#一个是事件的类型,
#一个是事件的描述。
#如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script <master-name> <script-path>sentinel notification-script mymaster /var/redis/notify.sh# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。 
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

12.缓存穿透,雪崩(待拓展)

12.1缓存穿透

缓存穿透:缓存穿透是指客户端请求的数据在缓存和数据库中都不存在,导致请求每次都 “穿透” 缓存,直接击中数据库。由于缓存无法命中,所有请求都会落到数据库上,若存在大量此类请求(如恶意攻击),可能导致数据库过载宕机。

解决方案

  1. 缓存空值
    当数据库查询结果为空时,在缓存中存储一个空值(如null),并设置较短的过期时间(避免长期占用缓存)。后续相同请求会直接命中缓存的空值,不再访问数据库。
    示例:查询user:999999返回空,缓存user:999999 → null,过期时间设为 5 分钟。
  2. 布隆过滤器
    在缓存层之前添加布隆过滤器,预先存储所有可能存在的合法数据(如用户 ID、商品 ID)。请求到来时,先通过布隆过滤器判断数据是否存在:
    • 若不存在,直接返回空,不访问缓存和数据库;
    • 若存在(存在一定误判率),再走正常的缓存→数据库流程。
      适合场景:数据量极大(如 10 亿级 ID),且对误判可容忍的场景。
  3. 接口层限流与校验
    对接口添加限流措施(如限制每秒请求量),并校验请求参数的合法性(如用户 ID 格式是否正确),过滤明显的恶意请求。

12.2缓存击穿

概念

相较于缓存穿透,缓存击穿的目的性更强,一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。这就是缓存被击穿,只是针对其中某个key的缓存不可用而导致击穿,但是其他的key依然可以使用缓存响应。

比如热搜排行上,一个热点新闻被同时大量访问就可能导致缓存击穿。

解决方案

  1. 设置热点数据永不过期

    这样就不会出现热点数据过期的情况,但是当Redis内存空间满的时候也会清理部分数据,而且此种方案会占用空间,一旦热点数据多了起来,就会占用部分空间。

  2. 加互斥锁(分布式锁)

    在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。保证同时刻只有一个线程访问。这样对锁的要求就十分高。

12.3缓存雪崩

缓存雪崩:缓存雪崩是指大量缓存 key 在同一时间过期失效,或缓存服务器整体故障(如 Redis 集群宕机),导致所有请求瞬间落到数据库上,造成数据库压力激增,甚至崩溃。

常见原因

  • 批量设置缓存时,使用了相同的过期时间(如凌晨 0 点统一过期)。
  • Redis 集群因网络故障、硬件问题等整体不可用。

解决方案

  • redis高可用

    这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群

  • 限流降级

    这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

  • 数据预热

    数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

http://www.xdnf.cn/news/15683.html

相关文章:

  • Windows 安装WSL +Docker 部署通义千问大模型(同步解决Ubuntu启动命令闪退)
  • 图片平铺下去总是有个缝隙的解决方案
  • Vue常见指令
  • 【解码文本世界的“隐形分界线”:Windows与Linux回车换行之谜】
  • Python网络爬虫之selenium库
  • coredns使用etcd
  • Gitee 远程库多人如何协作?
  • CCF编程能力等级认证GESP—C++1级—20250628
  • QT窗口(4)-浮动窗口
  • Kotlin封装
  • 萤石摄像头C++SDK应用实例
  • 微信小程序 wx.request() 的封装
  • Github库镜像到本地私有Gitlab服务器
  • PortSwigger Labs 之 点击劫持利用
  • RPC 与 Feign 的区别笔记
  • Spring AI开发智能客服(Tool calling)
  • 开启modbus tcp模拟调试
  • 【LeetCode 热题 100】199. 二叉树的右视图——(解法一)BFS
  • 自己动手实现 strlen:从循环到递归的四种写法
  • Postman/Apipost中使用Post URL编码发送含换行符参数的问题分析
  • 现代R语言机器学习:Tidymodel/Tidyverse语法+回归/树模型/集成学习/SVM/深度学习/降维/聚类分类与科研绘图可视化
  • 串口(Serial Port)是什么?
  • 在 React 中根据数值动态设置 SVG 线条粗细
  • 【52】MFC入门到精通——MFC串口助手(二)---通信版(发送数据 、发送文件、数据转换、清空发送区、打开/关闭文件),附源码
  • 9. isaacsim4.2教程-ROS加相机/CLOCK
  • vs openssl编译提示无法打开文件“libssl.lib”或“libcrypto.lib”
  • 回归预测 | MATLAB实现SA-BP模拟退火算法优化BP神经网络多输入单输出回归预测
  • 搜广推校招面经九十五
  • stm32驱动双步进电机
  • Linux入门篇学习——借助 U 盘或 TF 卡拷贝程序到开发板上