Redis(三)

张开发
2026/5/5 2:26:38 15 分钟阅读
Redis(三)
在实际工程项目中单台 Redis 服务器根本无法满足生产需求 —— 不仅会面临单点故障一旦宕机整个缓存服务直接瘫痪同时单台机器内存容量有限、请求负载过高也撑不住高并发场景。就拿电商网站来说商品数据大多是 “一次上传、无数次浏览”属于典型的 “多读少写” 场景。想要解决单机 Redis 的痛点搭建 Redis 集群是必经之路。本篇博客全程干货从基础的主从复制、哨兵模式到分布式 Cluster 集群再到 SpringBoot 整合实操最后详解面试常考的缓存穿透、击穿、雪崩问题兼顾理论与实操适合 Redis 集群入门及巩固学习。一、Redis 集群基础为什么必须用集群单台 Redis 无法应用于生产核心原因有两点结构层面单点故障风险高一台服务器需承担所有请求负载压力巨大容量层面单台 Redis 内存有限即便机器内存有 256G也不建议将 Redis 存储内存超过 20G无法满足海量数据存储需求。而 Redis 集群能完美解决以上问题结合 “多读少写” 的业务场景通过合理的架构设计实现高可用、高并发、大容量的缓存服务。二、Redis 主从复制一主二从架构Redis 本身读写性能优异但在超高并发场景下单台服务器依旧会面临读写压力过大的问题。主从复制架构核心是 “读写分离”分担主节点压力是 Redis 高可用的基础。1. 核心概念主从复制即把一台 Redis 服务器主节点 Master的数据复制到其他 Redis 服务器从节点 Slave数据复制是单向的只能从主到从。主节点Master以写操作为主同时负责同步数据到从节点从节点Slave以读操作为主不允许写操作数据完全同步主节点常用架构一主二从1 个主节点 2 个从节点适配 80% 的读写分离场景大幅减轻主节点读压力。默认情况下每台 Redis 服务器都是主节点一个主节点可挂载多个从节点但每个从节点只能归属一个主节点。2. 主从复制原理三步同步从节点连接主节点后主动发送数据同步请求主节点接收请求后对自身数据进行 RDB 持久化生成 RDB 文件并发送给从节点从节点读取 RDB 文件完成数据初始化后续主节点每执行一次写操作都会实时同步给从节点保证主从数据一致。3. 主从复制的核心作用数据冗余实现数据热备份是 Redis 持久化之外的另一重数据保障故障恢复主节点宕机时从节点可临时顶替主节点提供读服务避免服务中断负载均衡读写分离主节点写、从节点读多个从节点分摊读压力提升并发量高可用基石是哨兵模式、Cluster 集群的基础没有主从复制就无法实现后续的自动故障转移。4. 一主二从环境搭建Docker 版实操可直接复用1前期准备阿里云服务器创建配置文件和数据存储目录规划 3 台 Redis 实例1 主 2 从# 配置文件目录3个配置文件对应3台实例 /tmp/redis/conf/redis1.conf /tmp/redis/conf/redis2.conf /tmp/redis/conf/redis3.conf # 数据目录3个数据目录隔离存储 /tmp/redis/data/data1 /tmp/redis/data/data2 /tmp/redis/data/data32创建 3 个 Redis 容器# 主节点redis11映射端口6381 docker run -itd -p 6381:6379 --name redis11 -v /tmp/redis/conf/redis1.conf:/etc/redis1.conf -v /tmp/redis/data/data1:/data redis redis-server /etc/redis1.conf # 从节点1redis12映射端口6382 docker run -itd -p 6382:6379 --name redis12 -v /tmp/redis/conf/redis2.conf:/etc/redis2.conf -v /tmp/redis/data/data2:/data redis redis-server /etc/redis2.conf # 从节点2redis13映射端口6383 docker run -itd -p 6383:6379 --name redis13 -v /tmp/redis/conf/redis3.conf:/etc/redis3.conf -v /tmp/redis/data/data3:/data redis redis-server /etc/redis3.conf3查看容器信息创建完成后通过以下命令查看容器 IP后续配置主从关系需用到docker inspect 容器名/容器ID记录 3 台容器的 IP 和端口示例redis11主172.18.0.2:6379redis12从172.18.0.3:6379redis13从172.18.0.4:6379此时进入 3 台 Redis 实例会发现默认都是主节点未建立主从关系。4配置主从关系两种方式方式 1临时配置重启容器失效适合测试进入从节点容器执行命令 “认领主节点”Redis 高版本用 replicaof低版本用 slaveof# 进入redis12从节点1指定主节点为redis11 replicaof 172.18.0.2 6379 # 进入redis13从节点2指定主节点为redis11 replicaof 172.18.0.2 6379方式 2永久配置推荐重启容器生效修改两个从节点的配置文件redis2.conf、redis3.conf添加以下配置################################# REPLICATION ################################# # 配置主节点IP和端口 replicaof 172.18.0.2 6379配置完成后重启从节点容器主从关系永久生效。5. 主从复制使用规则必记从节点只读不写从节点执行写操作会直接报错所有写操作必须在主节点执行主节点宕机默认从节点不会自动切换为主节点集群仅失去写能力主节点重启后恢复正常从节点宕机若为临时配置的从节点重启后会变回主节点且丢失之前同步的数据若为永久配置重启后会自动重新同步主节点数据主节点故障手动切换在任意从节点执行replicaof no one使其成为新主节点其他从节点再执行replicaof 新主节点IP 端口手动切换主从关系。三、哨兵模式Sentinel主从自动故障转移普通主从复制有一个致命缺陷主节点宕机后需要人工手动切换从节点为主节点不仅费时费力还会导致服务短暂不可用。Redis 从 2.8 版本开始推出哨兵模式完美解决这个问题。1. 哨兵模式核心概述哨兵Sentinel是一个独立运行的进程核心作用是 “监控 自动故障转移”基于主从复制架构实现 Redis 集群的高可用。监控实时监测主节点、从节点的运行状态通过发送命令判断节点是否正常自动故障转移当监测到主节点宕机自动投票选举一个从节点将其切换为新主节点并通知其他从节点更新主节点配置全程无需人工干预。为了避免单哨兵故障生产环境通常采用 “多哨兵模式”哨兵之间互相监控提升集群稳定性。2. 关键术语面试常考主观下线单个哨兵检测到主节点无响应单方面判定主节点不可用客观下线多个哨兵检测到主节点故障且达到指定数量配置中设置统一判定主节点下线开启故障转移流程。3. 哨兵模式搭建基于一主二从架构1配置哨兵配置文件sentinel.conf创建哨兵配置文件放入/tmp/redis/conf/目录核心配置如下# 哨兵运行端口默认26379 port 26379 # 关闭保护模式允许外部访问 protected-mode no # 监控主节点mymaster集群名可自定义、主节点IP、端口、判定下线的哨兵数量1代表1个及以上哨兵判定即可 sentinel monitor mymaster 172.18.0.2 6379 12重新创建容器挂载哨兵配置# 主节点redis11 docker run -itd -p 6381:6379 --name redis11 -v /tmp/redis/conf/redis1.conf:/etc/redis1.conf -v /tmp/redis/data/data1:/data -v /tmp/redis/conf/sentinel.conf:/etc/sentinel.conf redis redis-server /etc/redis1.conf # 从节点1redis12 docker run -itd -p 6382:6379 --name redis12 -v /tmp/redis/conf/redis2.conf:/etc/redis2.conf -v /tmp/redis/data/data2:/data -v /tmp/redis/conf/sentinel.conf:/etc/sentinel.conf redis redis-server /etc/redis2.conf # 从节点2redis13 docker run -itd -p 6383:6379 --name redis13 -v /tmp/redis/conf/redis3.conf:/etc/redis3.conf -v /tmp/redis/data/data3:/data -v /tmp/redis/conf/sentinel.conf:/etc/sentinel.conf redis redis-server /etc/redis3.conf3启动哨兵进入任意从节点容器启动哨兵进程redis-sentinel /etc/sentinel.conf启动后哨兵会自动监控主节点当主节点宕机会自动执行故障转移切换新主节点。4. 哨兵模式优缺点优点继承主从复制所有优势实现自动故障转移服务可用性大幅提升多哨兵监控稳定性强避免单哨兵故障导致集群失控无需人工干预减少运维成本比普通主从架构更健壮。缺点在线扩容困难集群容量达到上限后扩容流程复杂无法快速扩展配置复杂哨兵配置项繁多搭建和调优门槛较高单主节点瓶颈集群只有一个主节点所有写压力集中在主节点负载依旧较大。5. 哨兵模式完整配置备用完整的 sentinel.conf 配置文件包含密码、超时时间、脚本配置等可直接复用# 哨兵运行端口 port 26379 # 哨兵工作目录 dir /tmp # 监控主节点mymaster为集群名可自定义 sentinel monitor mymaster 127.0.0.1 6379 1 # 主节点密码若主从设置了密码必须配置 sentinel auth-pass mymaster MySUPER--secret-0123passw0rd # 主观下线超时时间默认30000毫秒30秒 sentinel down-after-milliseconds mymaster 30000 # 故障转移时同时同步数据的从节点数量设为1避免多个从节点同时不可用 sentinel parallel-syncs mymaster 1 # 故障转移超时时间默认180000毫秒3分钟 sentinel failover-timeout mymaster 180000 # 通知脚本故障时发送通知可选 sentinel notification-script mymaster /var/redis/notify.sh # 客户端重配置脚本主节点切换后通知客户端可选 sentinel client-reconfig-script mymaster /var/redis/reconfig.sh四、Redis Cluster 集群多主多从分布式存储哨兵模式解决了主从自动故障转移问题但依旧是单主节点架构写压力无法分散。Redis Cluster 集群采用 “三主三从” 架构实现数据分片存储彻底解决单机容量和并发瓶颈是生产环境中最常用的 Redis 集群方案。1. Cluster 集群核心概述Cluster 集群由多个节点Node组成采用 “多主多从” 架构核心特点是 “去中心化 数据分片”去中心化无中心节点连接任意一个主节点都能操作整个集群数据分片将数据分散存储在不同主节点每个主节点只存储一部分数据分担存储和读写压力高可用每个主节点对应一个从节点主节点宕机后从节点自动选举为新主节点。2. Cluster 集群环境搭建Docker host 模式三主三从1集群配置规划容器名称redis-node1~redis-node66 个容器3 主 3 从端口号6379、6380、6381主节点6382、6383、6384从节点挂载目录数据目录/tmp/redis/data/node1~node6配置文件自动生成注意阿里云服务器需开放端口6379~6384和集群总线端口16379~16384端口号 10000。2创建 6 个 Redis 容器开启集群模式# 节点1主端口6379 docker create --name redis-node1 --net host -v /tmp/redis/data/node1:/data redis --cluster-enabled yes --cluster-config-file nodes-node-1.conf --port 6379 # 节点2主端口6380 docker create --name redis-node2 --net host -v /tmp/redis/data/node2:/data redis --cluster-enabled yes --cluster-config-file nodes-node-2.conf --port 6380 # 节点3主端口6381 docker create --name redis-node3 --net host -v /tmp/redis/data/node3:/data redis --cluster-enabled yes --cluster-config-file nodes-node-3.conf --port 6381 # 节点4从端口6382 docker create --name redis-node4 --net host -v /tmp/redis/data/node4:/data redis --cluster-enabled yes --cluster-config-file nodes-node-4.conf --port 6382 # 节点5从端口6383 docker create --name redis-node5 --net host -v /tmp/redis/data/node5:/data redis --cluster-enabled yes --cluster-config-file nodes-node-5.conf --port 6383 # 节点6从端口6384 docker create --name redis-node6 --net host -v /tmp/redis/data/node6:/data redis --cluster-enabled yes --cluster-config-file nodes-node-6.conf --port 63843启动所有容器docker start redis-node1 redis-node2 redis-node3 redis-node4 redis-node5 redis-node64组建 Cluster 集群进入任意一个容器如 redis-node1执行集群组建命令# 进入容器 docker exec -it redis-node1 /bin/bash # 组建集群--cluster-replicas 1 表示每个主节点对应1个从节点 redis-cli --cluster create 宿主机IP:6379 宿主机IP:6380 宿主机IP:6381 宿主机IP:6382 宿主机IP:6383 宿主机IP:6384 --cluster-replicas 1执行后输入yes确认集群配置等待初始化完成即可。5集群验证连接集群节点必须加-c参数代表集群模式shellredis-cli -c -h 宿主机IP -p 6379执行cluster nodes命令可查看所有节点的主从关系和运行状态。3. 分片哈希槽Cluster 核心原理Redis Cluster 集群共有16384 个分片哈希槽这是数据分片的核心16384 个哈希槽会平均分配给所有主节点3 主节点时每个主节点分配 5461 个槽位节点 1主0~5460节点 2主5461~10922节点 3主10923~16383读写数据时Redis 会根据 key 通过 CRC16 算法计算出一个 0~16383 的哈希值根据哈希值定位到对应的哈希槽再找到该槽位归属的主节点执行读写操作。4. 集群搭建常见坑避坑指南坑 1报错[ERR] Node xxx:6379 is not empty原因搭建集群前节点中存在残留数据或集群配置解决清空节点数据目录/tmp/redis/data/node1~node6重新创建容器。坑 2集群无法连接节点之间无法通信原因未开放集群总线端口服务端口 10000解决阿里云服务器开放 6379~6384 和 16379~16384 端口。5. Cluster 集群核心特点去中心化无中心节点任意主节点均可接入集群操作全集群数据数据分片数据分散存储在不同主节点解决单机容量瓶颈自动故障转移主节点宕机后对应从节点通过过半选举机制自动成为新主节点水平扩容可按需增减节点扩展集群容量和并发能力读写分离主节点负责读写从节点负责同步备份和读操作分担压力。五、SpringBoot 整合 Redis Cluster 集群实操SpringBoot 整合 Redis Cluster 非常简单只需引入依赖、配置集群节点即可实现对集群的读写操作。1. 导入依赖SpringBoot 默认使用 Lettuce 连接 Redis替代 Jedis需引入核心依赖和连接池依赖!-- Redis核心依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency !-- Lettuce连接池依赖 -- dependency groupIdorg.apache.commons/groupId artifactIdcommons-pool2/artifactId /dependency2. 配置 application.properties# Redis Cluster集群节点配置替换为自己的宿主机IP spring.redis.cluster.nodes118.31.189.130:6379,118.31.189.130:6380,118.31.189.130:6381,118.31.189.130:6382,118.31.189.130:6383,118.31.189.130:6384 # Redis密码若未设置密码注释即可 # spring.redis.password123456 # Lettuce连接池配置 spring.redis.lettuce.pool.max-active8 # 最大活跃连接数 spring.redis.lettuce.pool.max-wait-1 # 最大等待时间-1表示无限制 spring.redis.lettuce.pool.max-idle8 # 最大空闲连接数 spring.redis.lettuce.pool.min-idle0 # 最小空闲连接数 spring.redis.lettuce.shutdown-timeout100 # 关闭超时时间3. 代码测试使用StringRedisTemplate操作 Redis 集群测试读写功能import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.StringRedisTemplate; SpringBootTest class SpringBootRedisClusterApplicationTests { Autowired private StringRedisTemplate redisTemplate; Test void contextLoads() { // 向集群中存入数据 redisTemplate.opsForValue().set(testKey, testValue); // 从集群中获取数据 Object result redisTemplate.opsForValue().get(testKey); System.out.println(从Redis集群获取的数据 result); } }运行测试用例若能正常输出数据说明 SpringBoot 与 Redis Cluster 整合成功。六、Redis 缓存三大问题穿透、击穿、雪崩Redis 作为缓存层核心作用是挡住大部分请求减轻数据库压力。但在高并发场景下容易出现缓存穿透、击穿、雪崩三大问题严重时会压垮数据库这也是面试高频考点。1. 缓存处理常规流程请求到来 → 查 Redis 缓存 → 缓存命中直接返回结果 → 缓存未命中查数据库 → 数据库命中写入缓存 返回结果 → 数据库未命中返回空结果。2. 缓存穿透查询不到数据概念查询一个缓存和数据库都不存在的数据因为数据库无数据无法写入缓存导致每次请求都直接打到数据库。黑客常利用此漏洞发起攻击大量请求访问不存在的数据压垮数据库。解决方案方案 1缓存空数据原理查询无结果时将空值如 {key: null}存入 Redis设置较短的过期时间如 5 分钟优点实现简单无需额外组件缺点会占用部分 Redis 内存若大量不存在的 key 被缓存会造成内存浪费且可能出现数据不一致数据库后续新增该数据缓存仍为空。方案 2布隆过滤器原理提前将所有合法的 key 存入布隆过滤器一个大型 bitmap请求先经过过滤器不存在的 key 直接被拒绝不进入缓存和数据库优点内存占用少无多余空 key缺点实现复杂存在一定误判率可能将不存在的 key 判定为存在。3. 缓存击穿热点 key 过期概念一个高并发访问的热点 key缓存过期失效此时大量请求同时涌入缓存无法命中全部请求直接访问数据库造成数据库瞬时压力暴增也叫 “热点 key 问题”。解决方案方案 1热点数据永不过期原理对核心热点数据如首页热门商品不设置过期时间避免过期失效优点彻底杜绝击穿问题缺点会占用 Redis 内存且需手动更新缓存数据保证与数据库一致。方案 2互斥锁原理同一时间只允许一个线程查询数据库并重建缓存其他线程等待如使用 Redis 的 setnx 命令实现锁优点保证数据强一致性缺点会降低系统吞吐量存在锁竞争开销。4. 缓存雪崩大量 key 同时过期概念大量缓存 key 在同一时间段集中过期或者 Redis 服务宕机导致所有请求都直接访问数据库数据库承受不住海量请求而崩溃。解决方案过期时间随机化给每个缓存 key 加上随机过期时间如 10~20 分钟避免大量 key 同时过期集群高可用搭建 Redis Cluster 集群避免单节点宕机导致整个缓存服务瘫痪热点数据永不过期核心热点数据不设过期时间保证缓存始终可用双缓存架构设置缓存 A设过期时间和缓存 B永不过期请求先查 AA 未命中查 B同时异步重建缓存 A限流降级缓存失效时通过限流组件控制访问数据库的请求数量避免数据库被压垮。5. 补充概念面试拓展Redis 高可用通过搭建集群主从、哨兵、Cluster实现多节点冗余避免单节点故障导致服务中断限流降级缓存失效后通过加锁、队列或限流组件控制访问数据库的线程数量保护数据库数据预热正式部署前手动触发加载热点数据到缓存避免大并发场景下缓存未命中导致数据库压力骤增。七、总结Redis 集群的演进本质是从 “解决单点故障” 到 “分担负载”再到 “分布式存储” 的过程主从复制实现读写分离解决单节点负载问题是高可用基础哨兵模式在主从复制基础上实现自动故障转移减少人工干预Cluster 集群多主多从 数据分片彻底解决单机容量和并发瓶颈是生产环境首选同时缓存三大问题穿透、击穿、雪崩是 Redis 使用的核心隐患需结合业务场景选择合适的解决方案才能保证缓存服务稳定运行。

更多文章