大数据-51 Redis 分布式锁到哨兵机制:一文掌握Redis高可用架构

120 阅读10分钟

点一下关注吧!!!非常感谢!!持续更新!!!

🚀 AI篇持续更新中!(长期更新)

AI炼丹日志-30-新发布【1T 万亿】参数量大模型!Kimi‑K2开源大模型解读与实践,持续打造实用AI工具指南!📐🤖

💻 Java篇正式开启!(300篇)

目前2025年07月21日更新到:

Java-77 深入浅出 RPC Dubbo 负载均衡全解析:策略、配置与自定义实现实战 MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务正在更新!深入浅出助你打牢基础!

📊 大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈! 大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解

请添加图片描述

章节内容

上节我们完成了:

  • Redis分布式锁
  • Redis SETNX
  • Redis Redisson
  • 分布式锁对比
  • Java的部分实现

在这里插入图片描述

高可用介绍

概念定义

高可用(High Availability,简称HA)是指系统或服务经过专门设计后,能够长时间保持正常运行,将非计划性停机时间降至最低的技术特性。高可用性通常用"几个9"来衡量,例如99.9%(每年停机时间8.76小时)或99.99%(每年停机时间52.6分钟)。

实现原理

高可用系统通常通过以下机制实现:

  1. 冗余设计:部署多个相同功能的组件,当主组件失效时可以自动切换到备用组件
  2. 故障检测:实时监控系统健康状态,快速发现故障
  3. 自动恢复:在检测到故障后自动启动恢复流程
  4. 负载均衡:将请求合理分配到多个节点,避免单点过载

CAP理论与AP模型

在分布式系统的CAP理论(一致性Consistency、可用性Availability、分区容错性Partition tolerance)中,高可用系统通常采用AP模型:

  • AP模型:优先保证可用性和分区容错性,在出现网络分区时仍能提供服务,但可能牺牲强一致性
  • 典型应用场景:电商网站、社交网络等对服务连续性要求高的系统

典型应用场景

  1. 金融交易系统:需要7×24小时不间断运行
  2. 在线服务:如云存储、视频流媒体等
  3. 关键基础设施:电力系统、通信网络等

实现技术示例

  • 负载均衡:Nginx、HAProxy
  • 服务发现:Consul、Zookeeper
  • 容器编排:Kubernetes
  • 数据库集群:MySQL主从复制、Redis哨兵模式

挑战与权衡

实现高可用需要考虑:

  • 成本:冗余组件增加硬件投入
  • 复杂性:系统架构设计难度增加
  • 性能影响:如数据同步带来的延迟

现代云计算平台(如AWS、Azure)都提供了完善的高可用服务,大大降低了企业实现高可用的技术门槛。

Redis 主从复制详解

基本概念

Redis主从复制(Master-Slave Replication)是一种数据同步机制,允许将一台Redis服务器(主节点)的数据复制到其他Redis服务器(从节点)上,实现数据冗余备份和读写分离。

配置方式

1. 命令行配置

  • 在Redis 5.0及以后版本,使用REPLICAOF命令:
    REPLICAOF master_host master_port
    
  • 在Redis 5.0之前的版本,使用SLAVEOF命令:
    SLAVEOF master_host master_port
    

2. 配置文件设置

在redis.conf配置文件中可以永久设置主从关系:

replicaof 192.168.1.100 6379
# 或旧版本中使用:
# slaveof 192.168.1.100 6379

工作原理

  1. 初始化同步

    • 从节点连接主节点并发送SYNC命令
    • 主节点执行BGSAVE生成RDB文件,同时缓冲新写入的命令
    • 主节点将RDB文件发送给从节点
    • 从节点清空自身数据并加载RDB文件
    • 主节点将缓冲区的写命令发送给从节点执行
  2. 增量同步

    • 主节点将每个写命令发送到从节点
    • 从节点接收并执行这些命令,保持与主节点数据一致

应用场景

  1. 数据冗余:实现数据备份,提高数据安全性
  2. 读写分离:主节点负责写操作,从节点处理读请求
  3. 故障恢复:当主节点故障时,可以提升从节点为主节点
  4. 负载均衡:多个从节点分担读取压力

注意事项

  1. Redis主从复制默认是异步的,存在数据不一致的短暂窗口期
  2. 从节点默认是只读的,可以通过配置replica-read-only修改
  3. 复制过程中网络断开会自动重连并尝试部分重同步
  4. 主节点不需要任何配置即可接受从节点连接

一主一从

在这里插入图片描述

一主多从

在这里插入图片描述

传递复制

在这里插入图片描述

主从配置

主Redis

无需特殊的配置

从Redis

我们需要修改 redis.conf 文件,来实现。 比如我的主Redis是h121机器,当前我当前在h122上,计划变为h121的从服务器,那你需要如下的配置:

replicaof h121.wzk.icu 6379

主从作用

  • 读写分离:一主多从,主从同步,主写从读。
  • 数据容灾:从是主的备份。

同步模式

全量同步

全量同步是主从复制过程中最基础的同步方式,主要用于Slave节点初次连接Master或需要完全重建数据时。整个过程分为三个关键阶段:

  1. 同步快照阶段

    • Master节点执行BGSAVE命令,在后台生成当前数据的RDB快照文件
    • 快照生成期间,Master继续处理客户端请求,所有新的写命令会被记录到专用的复制缓冲区(replication buffer)
    • 当RDB文件生成完成后,Master将其传输给Slave节点
    • Slave接收到RDB文件后,会清空自身原有数据,然后完整加载这个快照
    • 示例:当新部署一个Slave节点时,首次连接Master就会触发此阶段
  2. 同步写缓冲阶段

    • Master将快照生成期间积压在复制缓冲区中的所有写命令发送给Slave
    • 这个阶段确保在生成RDB快照期间发生的数据变更不会丢失
    • Slave按顺序执行这些缓冲的命令,使其数据状态与Master保持一致
    • 应用场景:在高写入负载的系统,这个阶段可能包含大量命令,需要足够的网络带宽支持
  3. 同步增量阶段

    • 完成前两个阶段后,Master进入常规复制模式
    • Master将每个收到的写命令实时转发给Slave执行
    • Slave持续接收并执行这些命令,保持与Master的数据同步
    • 该阶段会一直持续,直到连接断开或发生新的全量同步
    • 步骤说明:Master为每个Slave维护一个复制偏移量(replication offset),用于跟踪同步进度

注意:全量同步是一个资源密集型操作,在网络带宽有限或数据量大的情况下,可能导致较长时间的同步延迟。生产环境中应合理配置自动故障转移和部分重同步机制来优化这个过程。

在这里插入图片描述

增量同步

  • Redis增量同步主要是Slave完成初始化正常工作后,Master的写操作同步到Slave
  • 通常情况下, Master每次执行一个写命令就会向Slave发送相同的写命令,然后Slave执行。

心跳监测

在命令阶段,从服务器默认会以每秒一次的频率向主服务器发送命令:

replconf ack <replication_offset>

主要有如下的作用:

  • 检测主从的连接状态
  • 辅助实现min-slaves
  • 检测命令丢失

哨兵模式

哨兵介绍

哨兵(Sentinel)是Redis官方提供的高可用性解决方案,由一个或多个Sentinel实例组成的分布式系统,用于监控Redis主从服务器的运行状态。当主服务器出现故障时,Sentinel能够自动执行故障检测和故障转移操作,确保Redis服务的持续可用性。

核心功能

  1. 监控

    • 持续检查主服务器和从服务器的运行状态
    • 定期向Redis实例发送PING命令检测响应情况
    • 记录实例的配置信息和复制关系
  2. 通知

    • 当监控的Redis实例出现问题时,可以通过API通知系统管理员或其他应用程序
    • 支持通过脚本、邮件等方式发送告警信息
  3. 自动故障转移

    • 当主服务器不可达时,自动启动故障转移流程
    • 从从服务器中选举出新的主服务器
    • 修改相关配置,使其他从服务器复制新的主服务器
    • 当旧的主服务器重新上线时,将其配置为新的主服务器的从服务器

工作原理

  1. 主观下线(SDOWN):

    • 单个Sentinel实例检测到主服务器无响应超过指定时间(可配置)
    • 该Sentinel会认为主服务器处于主观下线状态
  2. 客观下线(ODOWN):

    • 多个Sentinel实例(需达到quorum数量)都检测到主服务器无响应
    • Sentinel集群会通过Gossip协议交换信息并达成共识
    • 确认主服务器处于客观下线状态
  3. 选举领导者

    • Sentinel集群通过Raft算法选举出一个领导者Sentinel
    • 领导者负责执行故障转移操作
  4. 故障转移

    • 从可用的从服务器中选出最优候选作为新的主服务器
    • 向其他从服务器发送SLAVEOF命令,使其复制新的主服务器
    • 更新客户端配置,使其连接到新的主服务器

配置示例

# sentinel.conf 示例配置
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

应用场景

  1. 电商系统:确保购物车、秒杀等高并发场景下的Redis服务高可用
  2. 社交平台:保障用户关系、消息队列等核心数据的持久可靠
  3. 金融系统:需要7×24小时不间断服务的支付、交易系统
  4. 物联网平台:处理大量设备实时数据的存储和查询

最佳实践

  1. 部署至少3个Sentinel实例,分布在不同的物理机器上
  2. 合理配置down-after-milliseconds参数,平衡敏感性和误报率
  3. 定期测试故障转移功能,确保系统可靠性
  4. 监控Sentinel的运行状态和日志信息

部署方案

在这里插入图片描述

配置过程

由于需要启动很多,所以直接使用容器的方式部署。

version: '3'

services:
  redis-master:
    image: redis:6.2
    container_name: redis-master
    command: redis-server --appendonly yes
    ports:
      - 6379:6379
    volumes:
      - ./data/redis-master:/data

  redis-slave1:
    image: redis:6.2
    container_name: redis-slave1
    command: redis-server --slaveof redis-master 6379
    ports:
      - 6380:6379
    volumes:
      - ./data/redis-slave1:/data
    depends_on:
      - redis-master

  redis-slave2:
    image: redis:6.2
    container_name: redis-slave2
    command: redis-server --slaveof redis-master 6379
    ports:
      - 6381:6379
    volumes:
      - ./data/redis-slave2:/data
    depends_on:
      - redis-master

  sentinel1:
    image: redis:6.2
    container_name: sentinel1
    command: >
      sh -c "echo 'port 26379' > /data/sentinel.conf &&
             echo 'sentinel monitor mymaster redis-master 6379 2' >> /data/sentinel.conf &&
             echo 'sentinel down-after-milliseconds mymaster 5000' >> /data/sentinel.conf &&
             echo 'sentinel failover-timeout mymaster 10000' >> /data/sentinel.conf &&
             echo 'sentinel parallel-syncs mymaster 1' >> /data/sentinel.conf &&
             redis-sentinel /data/sentinel.conf"
    ports:
      - 26379:26379
    depends_on:
      - redis-master
      - redis-slave1
      - redis-slave2

  sentinel2:
    image: redis:6.2
    container_name: sentinel2
    command: >
      sh -c "echo 'port 26380' > /data/sentinel.conf &&
             echo 'sentinel monitor mymaster redis-master 6379 2' >> /data/sentinel.conf &&
             echo 'sentinel down-after-milliseconds mymaster 5000' >> /data/sentinel.conf &&
             echo 'sentinel failover-timeout mymaster 10000' >> /data/sentinel.conf &&
             echo 'sentinel parallel-syncs mymaster 1' >> /data/sentinel.conf &&
             redis-sentinel /data/sentinel.conf"
    ports:
      - 26380:26380
    depends_on:
      - redis-master
      - redis-slave1
      - redis-slave2

  sentinel3:
    image: redis:6.2
    container_name: sentinel3
    command: >
      sh -c "echo 'port 26381' > /data/sentinel.conf &&
             echo 'sentinel monitor mymaster redis-master 6379 2' >> /data/sentinel.conf &&
             echo 'sentinel down-after-milliseconds mymaster 5000' >> /data/sentinel.conf &&
             echo 'sentinel failover-timeout mymaster 10000' >> /data/sentinel.conf &&
             echo 'sentinel parallel-syncs mymaster 1' >> /data/sentinel.conf &&
             redis-sentinel /data/sentinel.conf"
    ports:
      - 26381:26381
    depends_on:
      - redis-master
      - redis-slave1
      - redis-slave2