第六章:Redis分布式缓存

Redis分布式缓存架构核心解决方案

摘要:针对单机Redis的四大核心问题,分布式架构提供了完整解决方案:1)通过RDB和AOF持久化机制解决数据丢失问题,RDB适合快速恢复,AOF保障数据安全;2)采用主从复制实现读写分离,提升并发能力,支持全量/增量同步;3)基于哨兵机制实现自动故障转移,确保高可用性,包含监控、选举、切换全流程;4)通过分片集群扩展存储容量,采用哈希槽机制实现数据分布。生产环境建议综合运用多种技术,主从+哨兵适合中小规模,分片集群应对海量数据,同时需优化持久化策略、网络配置和内存管理。

概述

单机Redis存在四大核心问题,通过分布式缓存架构可有效解决:

  1. 数据丢失问题 - 持久化机制保障

  2. 并发能力有限 - 主从读写分离提升

  3. 故障恢复困难 - 哨兵自动故障转移

  4. 存储容量限制 - 分片集群扩展

一、Redis持久化机制

1.1 RDB持久化(Redis Database Backup)

1.1.1 执行触发时机

主动触发:

复制代码
# 控制台

# 同步执行(阻塞主进程,生产环境慎用)
save

# 异步执行(后台fork子进程)
bgsave

自动触发配置:

复制代码
# properties配置文件

# redis.conf配置
save 900 1      # 900秒内至少1次修改
save 300 10     # 300秒内至少10次修改
save 60 10000   # 60秒内至少10000次修改

其他触发:

  • Redis正常关闭时自动执行save

  • 主从复制时,主节点自动触发bgsave

1.1.2 RDB配置参数
复制代码
# properties配置文件

# RDB文件名称
dbfilename dump.rdb

# 文件保存目录
dir ./

# 是否压缩(建议关闭,CPU换磁盘不划算)
rdbcompression no

# 保存时错误是否继续工作
stop-writes-on-bgsave-error yes
1.1.3 RDB执行原理

基于写时复制(Copy-on-Write)技术:

text

复制代码
1. 主进程fork()创建子进程
2. 子进程共享父进程内存空间
3. 父进程继续处理客户端请求
4. 子进程遍历内存数据写入RDB文件
5. 父进程修改数据时复制内存页副本
6. 子进程完成写入后替换旧RDB文件
1.1.4 RDB优缺点分析

优点:

  • 二进制紧凑格式,恢复速度快

  • 适合备份和灾难恢复

  • 最大化Redis性能(fork进程开销相对固定)

缺点:

  • 数据安全性较低(可能丢失最后一次保存后的数据)

  • fork过程内存占用翻倍(大数据量时影响性能)

  • 保存间隔期间故障会丢失数据

1.2 AOF持久化(Append Only File)

1.2.1 AOF配置详解
java 复制代码
# properties配置文件

# 开启AOF
appendonly yes

# AOF文件名
appendfilename "appendonly.aof"

# 同步策略(三选一)
appendfsync always      # 每个写命令立即同步(最安全,性能差)
appendfsync everysec    # 每秒同步一次(推荐,平衡方案)
appendfsync no          # 由操作系统决定(最快,最不安全)
1.2.2 AOF重写机制

触发条件:

java 复制代码
# properties配置文件

# 当前AOF文件大小超过上次重写大小的100%时触发
auto-aof-rewrite-percentage 100

# AOF文件最小达到64MB才触发重写
auto-aof-rewrite-min-size 64mb

手动触发:

java 复制代码
# 控制台

bgrewriteaof  # 后台重写AOF文件

重写原理:

text

复制代码
原始命令:set name jack → set name tom → set name alice
重写后:set name alice(只保留最终状态)
1.2.3 AOF优缺点

优点:

  • 数据安全性高(最多丢失1秒数据)

  • 可读性好,便于分析

  • 支持误操作恢复(删除错误命令)

缺点:

  • 文件体积大,恢复速度慢

  • 写入性能比RDB略差

  • 重写期间可能阻塞服务

1.3 RDB与AOF对比决策

特性 RDB AOF
数据安全性 可能丢失几分钟数据 最多丢失1秒数据
恢复速度 慢(需重新执行命令)
文件大小 小(二进制压缩) 大(文本格式)
对性能影响 保存时影响大 持续写入影响小
适用场景 备份、灾难恢复 数据安全性要求高

生产建议:同时开启两种持久化

properties配置文件

复制代码
# Redis重启时优先加载AOF文件
# 定期用RDB做冷备份

二、Redis主从复制架构

2.1 主从复制原理详解

2.1.1 全量同步流程
java 复制代码
1. slave发送psync ? -1 请求同步
2. master判断slave为首次连接,执行bgsave
3. master发送RDB文件给slave
4. slave清空旧数据,加载RDB
5. master将RDB期间的命令存入repl_backlog
6. master持续发送repl_backlog中的命令
7. slave执行命令,与master保持同步

关键概念:

  • Replication ID:数据集唯一标识,主从相同表示同一数据集

  • offset:复制偏移量,记录命令位置

2.1.2 增量同步机制

repl_backlog工作原理:

java 复制代码
# properties配置文件

# 环形缓冲区配置
repl-backlog-size 1mb    # 缓冲区大小
repl-backlog-ttl 3600    # 缓冲区保留时间(秒)

同步判断逻辑:

python 复制代码
# python环境
if slave.replid != master.replid:
    # 首次连接,执行全量同步
    do_full_sync()
elif slave.offset in master.backlog:
    # offset在缓冲区,执行增量同步
    do_partial_sync(slave.offset)
else:
    # offset已丢失,执行全量同步
    do_full_sync()
2.1.3 主从同步优化策略
  1. 无磁盘复制(避免全量同步IO)

    python 复制代码
    # properties配置文件
    
    repl-diskless-sync yes
    repl-diskless-sync-delay 5
  2. 合理配置缓冲区

    python 复制代码
    # properties配置文件
    
    # 根据写入量和网络情况调整
    repl-backlog-size 512mb
  3. 级联复制减少主节点压力

    python 复制代码
    主节点 → 从节点1 → 从节点2

2.2 主从配置实践

2.2.1 命令行配置
python 复制代码
# 控制台

# 在从节点执行
redis-cli -p 6380
SLAVEOF 127.0.0.1 6379

# 查看复制信息
INFO replication
2.2.2 配置文件设置
python 复制代码
# properties配置文件

# 从节点配置
slaveof 127.0.0.1 6379
slave-read-only yes
masterauth <password>  # 如果主节点有密码

三、Redis哨兵高可用方案

3.1 哨兵核心功能

3.1.1 监控机制

心跳检测:

  • 每隔1秒向所有节点发送PING命令

  • 主观下线:单个哨兵认为节点不可用

  • 客观下线:超过quorum数量的哨兵认为节点不可用

配置示例:

python 复制代码
# properties配置文件

# sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
3.1.2 故障转移流程
python 复制代码
1. 发现master客观下线
2. 选举领头哨兵(Raft算法)
3. 选择新master(按优先级、offset、runid)
4. 执行slaveof no one提升新master
5. 其他slave切换至新master
6. 旧master恢复后作为slave加入

选举规则优先级:

  1. 断开时间小于阈值(down-after-milliseconds * 10)

  2. slave-priority值越小优先级越高(0表示不参与选举)

  3. offset值越大优先级越高(数据越新)

  4. runid越小优先级越高

3.2 Spring Boot集成哨兵

3.2.1 依赖配置
XML 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3.2.2 配置文件
python 复制代码
# yaml配置文件

spring:
  redis:
    sentinel:
      master: mymaster
      nodes:
        - 192.168.1.101:26379
        - 192.168.1.102:26379
        - 192.168.1.103:26379
3.2.3 读写分离配置
java 复制代码
@Configuration
public class RedisConfig {
    
    @Bean
    public LettuceClientConfigurationBuilderCustomizer customizer() {
        return builder -> builder.readFrom(ReadFrom.REPLICA_PREFERRED);
    }
}

读取策略选项:

  • MASTER:只从主节点读

  • MASTER_PREFERRED:优先主节点,不可用则从节点

  • REPLICA:只从从节点读

  • REPLICA_PREFERRED:优先从节点,不可用则主节点

四、Redis分片集群

4.1 集群架构设计

4.1.1 集群特点
  • 多个master节点,每个存储不同数据

  • 每个master可有多个slave节点

  • 数据分片存储,解决海量数据问题

  • 支持水平扩展和高并发写

4.1.2 散列插槽机制

插槽分配:

java 复制代码
# 控制台
# 查看集群节点和插槽分配
redis-cli -p 7001 cluster nodes

key路由规则:

python 复制代码
# python环境

def slot_calculation(key):
    # 如果key包含{},则只计算{}内的部分
    if '{' in key and '}' in key:
        hash_key = key[key.find('{')+1:key.find('}')]
    else:
        hash_key = key
    
    # CRC16计算哈希值后对16384取模
    return crc16(hash_key) % 16384

应用技巧:

python 复制代码
# 控制台
# 同一类数据固定存储(使用相同hash tag)
set {user:1000}:name "张三"
set {user:1000}:age 25
set {user:1000}:email "zhangsan@example.com"

4.2 集群管理操作

4.2.1 集群伸缩操作

添加新节点:

python 复制代码
# 控制台
# 启动新实例
redis-server 7004/redis.conf

# 添加节点到集群
redis-cli --cluster add-node 192.168.1.104:7004 192.168.1.101:7001

# 查看节点状态(新增节点无插槽)
redis-cli -p 7001 cluster nodes

重新分配插槽:

python 复制代码
# 控制台
# 重新分配插槽
redis-cli --cluster reshard 192.168.1.101:7001

# 交互式操作流程:
# 1. 输入要移动的插槽数量(如3000)
# 2. 输入接收节点ID
# 3. 输入源节点ID(或all从所有节点平均移动)
# 4. 输入yes确认
4.2.2 故障转移处理

自动故障转移:

python 复制代码
# 控制台

# 停止一个master节点
redis-cli -p 7002 shutdown

# 观察自动切换过程
redis-cli -p 7001 cluster nodes

手动故障转移(维护时使用):

python 复制代码
# 控制台

# 连接到要从节点
redis-cli -p 8001

# 执行手动故障转移
CLUSTER FAILOVER [FORCE|TAKEOVER]

故障转移模式:

  • 默认模式:完整流程,保证数据一致性

  • FORCE模式:跳过一致性检查,快速切换

  • TAKEOVER模式:强制切换,无视其他节点意见

4.3 Spring Boot集成集群

python 复制代码
# yaml配置文件

spring:
  redis:
    cluster:
      nodes:
        - 192.168.1.101:7001
        - 192.168.1.101:7002
        - 192.168.1.101:7003
        - 192.168.1.101:8001
        - 192.168.1.101:8002
        - 192.168.1.101:8003
      max-redirects: 3  # 最大重定向次数

五、生产环境最佳实践

5.1 持久化策略建议

python 复制代码
# properties配置文件

# 综合配置示例
# 1. 同时开启RDB和AOF
appendonly yes
appendfsync everysec

# 2. RDB配置为低频高量
save 3600 1000
save 300 100
save 60 10000

# 3. AOF自动重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 256mb

# 4. 禁用AOF重写期间追加
no-appendfsync-on-rewrite yes

5.2 主从复制优化

python 复制代码
# properties配置文件

# 主节点配置
repl-backlog-size 512mb
repl-backlog-ttl 3600
min-slaves-to-write 1
min-slaves-max-lag 10

# 从节点配置
slave-serve-stale-data yes
slave-read-only yes

5.3 哨兵配置要点

python 复制代码
# properties配置文件

# 哨兵基础配置
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

# 生产环境建议
sentinel auth-pass mymaster <password>
sentinel notification-script mymaster /path/to/script.sh

5.4 集群运维建议

  1. 容量规划:预留30%内存用于bgsave和集群管理

  2. 监控告警:监控节点状态、内存使用、网络延迟

  3. 备份策略:定期RDB备份到异地

  4. 升级方案:先升级从节点,再手动故障转移升级主节点

六、故障排查与性能调优

6.1 常见问题排查

主从同步失败:

python 复制代码
# 控制台
# 检查主从状态
INFO replication

# 查看复制错误
redis-cli -p 6380 DEBUG REPLICATION

# 检查网络连通性
redis-cli -p 6379 PING

哨兵无法故障转移:

python 复制代码
# 控制台

# 查看哨兵日志
tail -f /var/log/redis/sentinel.log

# 检查仲裁数量配置
redis-cli -p 26379 SENTINEL GET-master-addr-by-name mymaster

集群节点故障:

python 复制代码
# 控制台

# 检查集群健康状态
redis-cli --cluster check 192.168.1.101:7001

# 修复故障节点
redis-cli --cluster fix 192.168.1.101:7001

6.2 性能优化参数

python 复制代码
# properties配置文件

# 网络优化
tcp-keepalive 300
timeout 0

# 内存优化
maxmemory-policy volatile-lru
maxmemory-samples 5

# 持久化优化
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes

总结对比表

方案 数据安全 可用性 扩展性 适用场景
单机+持久化 开发测试、小数据量
主从复制 读扩展 读多写少,允许短暂不可用
哨兵模式 读扩展 高可用要求,自动故障转移
分片集群 读写扩展 海量数据,高并发读写

架构选择建议:

  1. 中小规模:主从+哨兵,满足大部分生产需求

  2. 大数据量:分片集群,支持水平扩展

  3. 混合架构:集群内部分片,分片内部主从+哨兵

相关推荐
IT大白鼠2 天前
Redis 系列 · 第 01 篇——认知入门:Redis 是什么
redis·nosql
彧azz2 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
lbb 小魔仙2 天前
OpenClaw + cpolar 实战:远程 NAS、分享小游戏、RDP,再配置公网 AI 入口
数据库·人工智能·redis·oracle·prometheus
夕除2 天前
redis--018
redis
两锭子2 天前
Redis基础
redis
烟沙九洲2 天前
Redis 缓存穿透、缓存击穿、缓存雪崩
数据库·redis
字节探索2 天前
Redis 只会当缓存用?这 10 大实战场景,让你的系统快到飞起
redis·后端
于樱花森上飞舞2 天前
【Redis】哨兵详解
java·开发语言·数据库·redis
Rain的Java大神之路3 天前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
Wang's Blog3 天前
Java 接入Redis: 通用命令与键管理
java·服务器·redis