掌握Redis基础后,进阶学习的核心围绕两个核心目标:高可用 和数据一致性。高可用确保Redis服务不中断、承载高并发;数据一致性解决缓存与数据库协同的痛点,避免业务异常。本文将深入拆解Redis高可用体系(主从复制、哨兵模式、集群),以及缓存与数据库不一致的核心原因和落地解决方案,适合后端开发、运维同学进阶学习,也可作为面试重点复习资料。
一、Redis高可用基础:主从复制(Master-Replica Replication)
Redis单节点部署存在明显短板:一旦节点宕机,服务直接不可用;单节点处理能力有限,无法承载高并发读写。主从复制是Redis高可用的基础,核心是"一主多从"架构,主节点负责写操作,从节点负责读操作,实现读写分离、故障备份。
1. 主从复制核心原理
主从复制的核心是"数据同步",即从节点复制主节点的数据集,保持与主节点数据一致,整个过程分为三个阶段,且默认采用异步复制模式(低延迟、高性能,适配绝大多数Redis用例):
-
初始化同步(全量同步):当从节点首次连接主节点时,会发送PSYNC命令,请求全量同步。主节点会fork一个子进程,生成RDB快照文件,同时缓冲这段时间内的所有写命令;子进程将RDB文件发送给从节点,从节点接收后加载RDB文件,完成初始数据同步;最后主节点将缓冲的写命令发送给从节点,从节点执行这些命令,确保与主节点数据完全一致。
-
增量同步:全量同步完成后,主节点会将后续所有写命令(set、hset等)实时发送给从节点,从节点接收并执行命令,保持数据实时同步。主节点会维护一个复制偏移量,每发送一个字节的复制流,偏移量就递增;从节点也会维护自身的偏移量,用于向主节点确认已接收的数据量,实现精准增量同步。
-
断连重连:若主从节点因网络问题断开连接,从节点会自动重新连接主节点。连接成功后,从节点会发送自身的复制ID和偏移量,主节点会判断是否能进行增量同步(若主节点缓冲区有足够的积压数据);若无法增量同步,则触发全量同步,确保数据一致。
2. 主从复制核心特性与注意事项
主从复制的设计兼顾性能和可用性,有几个关键特性需要重点关注:
-
主节点非阻塞:主节点在执行全量同步(fork子进程)和增量同步时,不会阻塞自身的写操作,可正常处理客户端请求。
-
从节点大多非阻塞:从节点执行全量同步时,可配置使用旧数据集处理读请求;加载新RDB文件时会短暂阻塞,Redis 4.0后可配置在独立线程中删除旧数据集,减少阻塞时间。
-
级联复制:从节点可连接其他从节点,形成级联架构,所有子从节点都会从主节点接收相同的复制流,减轻主节点的同步压力。
-
数据安全注意:强烈建议主从节点都开启持久化;若主节点关闭持久化,需禁用自动重启,否则主节点宕机重启后会以空数据集启动,导致所有从节点数据被清空。
3. 主从复制的使用场景
-
读写分离:主节点承担写操作,从节点承担读操作(如查询、统计),分担主节点压力,提升系统并发处理能力。
-
故障备份:当主节点宕机时,从节点可作为备用节点,后续通过手动或哨兵模式提升为主节点,避免服务中断。
-
数据备份:从节点可单独开启AOF或RDB持久化,避免主节点持久化的IO开销,同时实现数据备份。
二、Redis高可用升级:哨兵模式(Sentinel)原理与实现
主从复制解决了"数据备份"和"读写分离",但存在一个致命问题:主节点宕机后,需要手动将从节点提升为主节点,无法实现自动故障转移,期间服务会中断。哨兵模式正是为解决这个问题而生,它是Redis的高可用解决方案,能够实现"监控、通知、自动故障转移",无需人工干预。
1. 哨兵模式核心功能
Redis Sentinel是一个分布式系统,通常由3个及以上哨兵节点组成(避免单点故障),核心功能有4个:
-
监控(Monitoring):哨兵节点会持续监控主节点和从节点的运行状态,检查节点是否正常工作(通过发送PING命令检测)。
-
通知(Notification):当某个节点出现故障时,哨兵会通过API通知系统管理员或其他应用程序,及时反馈故障信息。
-
自动故障转移(Automatic Failover):当主节点宕机且无法恢复时,哨兵会自动挑选一个健康的从节点,将其提升为主节点;同时更新其他从节点的配置,让它们同步新主节点的数据;最后通知客户端,更新主节点地址。
-
配置提供者(Configuration Provider):客户端连接Redis时,会先连接哨兵,获取当前主节点的地址,再连接主节点进行操作;故障转移后,哨兵会向客户端返回新主节点地址,确保客户端正常访问。
2. 哨兵模式核心原理(故障转移流程)
哨兵模式的核心是"故障检测"和"自动故障转移",整个流程清晰且可落地,具体步骤如下:
-
故障检测:每个哨兵节点会定期向主节点、从节点发送PING命令,若某个节点在指定时间(down-after-milliseconds配置,默认60秒)内未响应,哨兵会将该节点标记为"主观下线"(仅当前哨兵认为节点故障)。
-
故障确认:当一个哨兵标记主节点为"主观下线"后,会向其他哨兵节点发起投票,询问是否认为该主节点已故障;若超过半数(quorum配置,通常为哨兵节点数的一半+1)哨兵标记主节点为"客观下线",则确认主节点确实故障,触发故障转移。
-
挑选新主节点:哨兵会从所有健康的从节点中,挑选一个最优的从节点作为新主节点,挑选标准优先考虑:复制偏移量最大(数据最完整)、响应速度快、配置优先级高的从节点。
-
故障转移执行:将挑选出的从节点提升为主节点(执行slaveof no one命令);让其他从节点同步新主节点的数据(执行slaveof 新主节点IP:端口命令);更新哨兵配置,将旧主节点标记为从节点,待其恢复后,让其同步新主节点的数据。
3. 哨兵模式的实现(简单部署步骤)
哨兵模式的部署基于主从复制,需先搭建主从架构,再部署哨兵节点,核心步骤如下(以3个哨兵节点为例):
- 搭建主从复制:部署1个主节点(master)和2个从节点(slave1、slave2),配置从节点的slaveof 主节点IP:端口,完成主从同步。
2.配置哨兵节点:每个哨兵节点创建sentinel.conf配置文件,核心配置如下(最小配置):
# 监控主节点,mymaster为主节点名称,127.0.0.1:6379为主节点地址,2为投票quorum值 ``sentinel monitor mymaster 127.0.0.1 6379 2
# 主节点无响应60秒后,标记为主观下线
sentinel down-after-milliseconds mymaster 60000
# 故障转移超时时间,默认180秒
sentinel failover-timeout mymaster 180000
# 故障转移时,同时同步的从节点数量,默认1(避免同步压力过大)
sentinel parallel-syncs mymaster 1
3.启动哨兵节点:通过命令redis-sentinel /path/to/sentinel.conf启动3个哨兵节点,哨兵会自动发现主节点和从节点,开始监控。
注意:哨兵节点默认运行在26379端口,需确保该端口开放,允许哨兵节点之间、哨兵与主从节点之间通信;建议将哨兵节点部署在不同的服务器或可用区,提升稳定性。
三、Redis分布式解决方案:集群(Redis Cluster)
主从复制+哨兵模式解决了"高可用",但仍存在局限:单主节点的内存有限,无法存储海量数据;单主节点的写操作压力无法分散。Redis Cluster(Redis集群)通过"分片存储"和"分布式高可用",解决了海量数据存储和高并发写的问题,是生产环境中大规模Redis部署的首选方案。
1. 集群核心原理
Redis集群的核心是"分片(Sharding)"和"主从备份",集群由多个节点组成(至少6个节点,3主3从),每个主节点负责一部分数据,从节点作为主节点的备份,实现高可用,核心设计如下:
-
哈希槽(Hash Slot):Redis集群将所有数据划分为16384个哈希槽,每个键通过CRC16算法计算哈希值,再对16384取模,确定该键属于哪个哈希槽;每个主节点负责一部分哈希槽(例如3主节点,分别负责0-5500、5501-11000、11001-16383的哈希槽)。
-
分片存储:数据按哈希槽分布到不同的主节点,实现数据分片,解决单节点内存限制问题;同时,写操作分散到多个主节点,提升并发写能力。
-
主从备份:每个主节点对应至少一个从节点,当主节点宕机时,其从节点会被自动提升为主节点,接管对应的哈希槽,确保集群正常运行;若主节点和其所有从节点都宕机,且该主节点负责的哈希槽无其他备份,则集群无法提供该部分数据的服务。
-
集群总线:每个集群节点需要开放两个端口,一个是客户端通信端口(默认6379),另一个是集群总线端口(默认16379,客户端端口+10000);集群总线用于节点之间的通信,实现故障检测、配置更新、故障转移授权等功能。
2. 集群的核心特性
-
自动分片:数据自动分布到不同主节点,无需人工干预;新增或删除节点时,可通过哈希槽迁移,实现扩缩容,且不影响集群正常运行。
-
高可用:每个主节点有从节点备份,支持自动故障转移,与哨兵模式类似,但无需额外部署哨兵节点,集群自身实现故障转移。
-
多键操作限制:多键操作(如mget、mset)要求所有键属于同一个哈希槽,可通过哈希标签(如user:{123}:profile、user:{123}:account)强制多个键属于同一个哈希槽,实现多键操作。
-
一致性说明:Redis集群采用异步复制,不保证强一致性,可能会丢失少量已确认的写入;可通过WAIT命令实现同步复制,降低数据丢失风险,但会牺牲部分性能。
3. 集群的使用场景
-
海量数据存储:单节点内存不足时,通过集群分片,将数据分散到多个节点,支持TB级数据存储。
-
高并发读写:写操作分散到多个主节点,读操作可由主节点和从节点共同承担,提升系统并发处理能力(支持10万+ QPS)。
-
分布式部署:节点可部署在不同的服务器、机房,提升系统的容灾能力。
四、核心痛点:缓存与数据库不一致(原因+解决方案)
Redis作为缓存使用时,最常见的进阶痛点就是"缓存与数据库不一致"------即缓存中的数据与数据库中的数据不匹配,导致业务查询错误、数据错乱。造成不一致的核心原因是"缓存操作"与"数据库操作"无法保证原子性,下面逐一拆解原因和可落地的解决方案。
1. 造成缓存与数据库不一致的核心原因
不一致的本质是"缓存更新"与"数据库更新"的顺序、时机出现问题,常见原因有4种:
-
更新顺序错误(最常见):
-
错误顺序:先更新缓存,再更新数据库。若更新数据库失败,缓存中是新数据,数据库中是旧数据,导致不一致。
-
半正确顺序:先更新数据库,再更新缓存。若更新缓存失败,数据库中是新数据,缓存中是旧数据,同样导致不一致。
-
-
缓存过期/淘汰:缓存设置了过期时间,过期后自动失效,若此时数据库数据已更新,缓存未及时重建,会导致缓存中无数据或数据陈旧。
-
并发读写冲突:高并发场景下,多个线程同时读写数据,例如:线程1读取缓存(旧数据)→ 线程2更新数据库(新数据)→ 线程1更新缓存(旧数据覆盖新数据),导致缓存与数据库不一致。
-
缓存穿透/击穿/雪崩(间接导致):缓存穿透、击穿、雪崩会导致缓存失效,大量请求直接打向数据库,若数据库更新后,缓存未及时同步,会出现短期不一致。
2. 缓存与数据库不一致的解决方案(落地性优先)
解决方案的核心原则:保证"数据库更新"与"缓存更新"的原子性,优先选择简单、可落地的方案,避免过度复杂。
方案1:正确的更新顺序(推荐)------ 先更数据库,再删缓存(Cache Aside Pattern)
这是最常用、最落地的方案,核心逻辑:不更新缓存,而是删除缓存,让后续的读请求自动重建缓存,避免更新缓存失败导致的不一致,步骤如下:
-
先执行数据库更新操作(如update、delete),确保数据库数据正确。
-
再执行缓存删除操作(如del key),删除旧缓存。
-
后续有读请求时,发现缓存不存在,从数据库读取新数据,再写入缓存,完成同步。
补充说明:该方案仍存在极小概率的不一致(如数据库更新成功,缓存删除失败),可通过"重试机制"解决------若缓存删除失败,记录日志,通过定时任务重试删除,或在下次读请求时校验数据一致性。
方案2:解决并发读写冲突------ 分布式锁
针对高并发场景,通过分布式锁(Redis的setnx命令、Redisson框架)保证同一时间只有一个线程能执行"读-写"操作,避免冲突,步骤如下:
-
线程请求数据时,先获取分布式锁。
-
获取锁成功后,查询缓存:若缓存存在,直接返回;若缓存不存在,查询数据库,写入缓存,再返回。
-
更新数据时,同样先获取分布式锁,再执行"更新数据库→删除缓存",最后释放锁。
-
获取锁失败的线程,等待一段时间后重试,避免并发冲突。
方案3:缓存过期优化------ 合理设置过期时间+缓存预热
-
合理设置过期时间:根据业务场景设置过期时间,避免缓存长期不更新;同时给同一类key设置随机过期时间(如基础过期时间+1-5分钟),避免大量缓存同时过期。
-
缓存预热:系统启动时,主动将热点数据从数据库加载到缓存中,避免缓存失效后大量请求打向数据库,同时确保缓存数据与数据库一致。
方案4:最终一致性方案------ binlog同步(进阶)
针对数据一致性要求较高的场景,可通过"数据库binlog同步"实现缓存与数据库的最终一致性,核心逻辑:
-
数据库开启binlog,记录所有数据更新操作(insert、update、delete)。
-
部署一个binlog监听服务(如Canal),监听数据库的binlog变化。
-
当数据库数据更新时,binlog监听服务捕捉到更新事件,自动同步更新或删除对应的缓存。
优点:无需在业务代码中处理缓存更新,降低开发成本;实现最终一致性,适合核心业务场景;缺点:增加系统复杂度,需要部署额外服务。
方案5:兜底校验------ 缓存数据校验
在业务代码中增加校验逻辑:读取缓存数据后,与数据库数据进行简单校验(如校验版本号、时间戳),若不一致,直接从数据库读取数据,并更新缓存,确保业务数据正确。
五、总结:Redis进阶知识核心梳理
Redis进阶学习的核心的是"高可用"和"数据一致性",两者相辅相成,支撑生产环境的稳定运行,核心要点梳理如下:
-
主从复制:高可用基础,实现读写分离、数据备份,核心是异步同步,需注意主从持久化配置,避免数据丢失。
-
哨兵模式:基于主从复制,实现自动故障转移,无需人工干预,核心是"监控-投票-故障转移",建议部署3个及以上哨兵节点。
-
集群:分布式解决方案,通过哈希槽分片存储,实现海量数据和高并发读写,核心是"分片+主从备份",适合大规模部署。
-
缓存一致性:核心是保证"数据库更新"与"缓存更新"的原子性,优先使用"先更数据库,再删缓存",高并发场景加分布式锁,核心场景用binlog同步兜底。