Java Redis “Sentinel(哨兵)与集群”面试清单(含超通俗生活案例与深度理解)

一、Redis Sentinel基础

  1. 面试题:Redis Sentinel的核心作用是什么?为什么主从复制场景下必须用到它?

回答要点:核心作用是解决主从复制"无法自动故障转移"的痛点,实现Redis服务的高可用(即服务不中断、数据不丢失)。主从复制的本质是"主节点写数据、从节点复制数据",但一旦主节点宕机(比如服务器断电、网络中断),从节点只能被动等待,需要人工手动修改配置把某个从节点升级为主节点------这个过程少则几分钟、多则十几分钟,期间服务完全无法写入,会直接影响业务。而Sentinel相当于"自动运维员",能实时监控主从节点状态,主节点故障后10秒内完成故障检测、从节点筛选、新主节点切换,全程无需人工干预,业务几乎感受不到中断。

生活类比:就像家里的供水系统------主水管(主节点)负责给全家供水,2根备用水管(从节点)平时只备份主水管的水流(复制数据)。如果主水管突然爆裂,没有Sentinel的话,你得自己找维修师傅、关总阀、手动打开备用水管,期间1-2小时没水用,洗衣机停转、没法做饭;有了Sentinel,相当于装了"智能供水切换系统",主水管爆裂的瞬间,系统立刻检测到水压下降,自动关闭主水管、打开备用水管并把它设为新主供水管,你正在洗碗的水龙头都不会停,完全没感知到故障。

  1. 面试题:Redis Sentinel由哪两部分组成?各自的职责是什么?请用日常场景类比说明。

回答要点:Redis Sentinel由哨兵节点(Sentinel Node) 和数据节点(Data Node) 两部分组成,二者分工明确、协同工作。

◦ 哨兵节点:是特殊的Redis节点,不存储任何业务数据,核心职责有三个------"监控"(实时检查主从节点是否存活)、"判故障"(判断节点是暂时卡顿还是真宕机)、"调切换"(主节点故障后,选新主、让其他从节点连新主)。

◦ 数据节点:就是普通的Redis节点,分两类------主节点(Master)负责接收所有写请求(比如用户存数据、改数据),并把数据同步给从节点;从节点(Slave)只负责接收读请求(比如用户查数据),同时实时复制主节点的数据,相当于"数据备份机"。

生活类比:类似小区的"物业+住户"体系------哨兵节点是物业维修部(不住人、不存私人物品,只做三件事:每天检查电梯/水管/电路是否正常(监控)、判断电梯是偶尔故障还是彻底坏了(判故障)、电梯坏了立刻调备用电梯上线并贴通知(调切换));数据节点是住户家的"主卧室+次卧室"------主卧室(主节点)是家人主要活动区(存日常用品、做决策),次卧室(从节点)备份主卧室的物品(比如备用床品、衣服),平时也能住人(提供读服务),主卧室漏水时,次卧室就能临时当主活动区。

二、Redis Sentinel核心功能与原理

  1. 面试题:Redis Sentinel官方定义了四大核心功能,请分别解释每个功能的作用,并各举一个生活例子说明。

回答要点:四大功能分别是监控(Monitoring)、自动故障转移(Automatic Failover)、配置提供者(Configuration Provider)、通知(Notification),缺一不可:

◦ 监控:每个哨兵节点每隔1秒,会向主节点、从节点、其他哨兵节点发送"ping"命令,就像"心跳检测"------如果节点在"down-after-milliseconds"(默认30秒)内没回复,哨兵就暂时标记它"可能有问题"。

生活例子:外卖平台给骑手的"实时打卡"------平台(哨兵)每隔1秒给骑手(节点)发一次"是否在线"的请求,骑手正常接单时会立刻回复"在线";如果骑手手机没电关机,30秒内没回复,平台就会标记"这个骑手可能失联了"。

◦ 自动故障转移:当哨兵确认主节点"彻底宕机"后,会立刻执行三步操作------先从所有从节点里选一个"最合格"的当新主节点,再让其他从节点停止复制旧主、改复制新主,最后把旧主节点标记为"备用"(恢复后改当从节点)。

生活例子:学校的"上课老师备用机制"------主老师(主节点)突然发烧请假,教务处(哨兵)5分钟内完成安排:选平时备课最充分的副老师(合格从节点)当主讲课老师,让其他辅助老师(其他从节点)配合新主老师发课件、改作业,等主老师病好回来,就当辅助老师(从节点)帮忙。

◦ 配置提供者:客户端(比如Java程序)启动时,不知道哪个是主节点、哪个是从节点,这时会先连接哨兵节点,哨兵会直接返回"当前正在工作的主节点地址",客户端再去连主节点写数据。

生活例子:你去陌生城市找连锁奶茶店------你不知道哪家店是"主店"(能点所有新品)、哪家是"分店"(只卖常规款),打开奶茶APP(客户端),APP先连接品牌总部系统(哨兵),总部告诉你"当前营业的主店在XX路123号",你直接导航过去点新品,不用自己查所有门店信息。

◦ 通知:故障转移完成后,哨兵会把"新主节点地址、旧主节点状态、从节点调整情况"等信息,通过短信、邮件或API通知给客户端、运维人员。

生活例子:快递柜的"取件通知"------快递员(哨兵)把快递从旧柜子(旧主节点)转到新柜子(新主节点)后,系统会立刻给你发短信(通知):"您的快递已转移到2号柜,取件码123456",你不用反复去旧柜子查,直接去新柜子取就行。

  1. 面试题:Redis Sentinel靠三个"定时任务"实现节点监控和拓扑感知,这三个任务分别是什么?各自的周期和作用是什么?

回答要点:三个定时任务是Sentinel的"核心手脚",周期和作用完全不同,共同支撑起监控和故障检测:

◦ 任务1:每隔10秒,每个哨兵向主节点、从节点发送"info"命令。作用是获取最新的"拓扑结构"------比如主节点有多少个从节点、每个从节点的IP/端口、从节点复制主节点的数据进度(偏移量),确保哨兵始终知道"整个集群的成员和状态"。

生活例子:公司部门经理(哨兵)每周一(10秒周期)给部门所有员工(主/从节点)发"工作周报收集表"(info命令),通过表格知道"部门有多少人、谁是新入职的(新从节点)、每个人上周做了多少工作(复制进度)",避免有人离职了经理还不知道。

◦ 任务2:每隔2秒,每个哨兵向"sentinel:hello"频道(Redis的内置频道)发送一条消息,内容包括"自己的IP/端口、对主节点的判断(比如主节点是否正常)、当前哨兵的状态"。作用是让所有哨兵互相感知------你知道我在、我知道你在,同时交换对主节点的看法,避免单个哨兵"孤陋寡闻"。

生活例子:小区业主群(sentinel:hello频道)里,每个业主(哨兵)每隔2分钟发一条"我家水电正常"(自身状态)+"我看楼下超市还开着(对主节点的判断)"的消息,大家通过群消息知道"有多少业主在线、大家对小区设施的看法是否一致",比如有人说"超市关了",其他人看到后会一起确认,避免单个业主误判。

◦ 任务3:每隔1秒,每个哨兵向主节点、从节点、其他哨兵节点发送"ping"命令。作用是做"实时心跳检测"------这是最频繁的任务,确保能最快发现节点宕机,比如主节点突然断网,1秒内哨兵就会收到"ping没回复"的信号,开始后续判断。

生活例子:家长(哨兵)每隔1分钟给独自在家的孩子(节点)发一条"在吗"(ping命令),孩子正常时会立刻回复"在",如果孩子没回复,家长1分钟内就会察觉"可能有问题",赶紧打电话确认,不会等半小时才发现。

  1. 面试题:什么是Redis Sentinel的"主观下线(SDOWN)"和"客观下线(ODOWN)"?两者的区别是什么?为什么主节点需要"客观下线",从节点不需要?

回答要点:主观下线和客观下线是哨兵判断节点故障的"两步法",避免误判和漏判:

◦ 主观下线(Subjective Down):单个哨兵节点通过"1秒ping任务"发现,某个节点(主或从)超过"down-after-milliseconds"时间没回复,就独自认为"这个节点宕机了"------这是单个哨兵的"个人判断",可能存在误判(比如节点只是网络卡顿,不是真宕机)。

◦ 客观下线(Objective Down):只有当"被主观下线的节点是主节点"时,哨兵才会发起"客观下线判断"------它会向其他哨兵发送"sentinel is-master-down-by-addr"命令,问"你觉得主节点宕机了吗?",如果超过"quorum"(预设的最小同意数,比如3个哨兵里至少2个同意)的哨兵都回复"我也觉得主节点宕机了",这时才会确认"主节点真的宕机了",触发故障转移。

两者的核心区别:主观下线是"个人意见",可能不准;客观下线是"多数共识",更可靠。从节点不需要客观下线,因为从节点故障只影响读服务,主节点故障影响写服务------读服务断了可以用其他从节点补,写服务断了必须100%确认主节点真宕机,才敢切换,避免"主节点只是卡了,哨兵却误把从节点升为主,导致数据不一致"。

生活例子:判断班级同学是否"真的没来上课"------① 主观下线:你进教室看到小明座位空着(单个哨兵ping没回复),就觉得"小明没来"(主观下线),但其实小明只是去厕所了(网络卡顿);② 客观下线:你问了周围5个同学(其他哨兵),有4个(超过quorum=3)说"一整节课都没看到小明"(也主观下线),这时大家一起判断"小明真的没来"(客观下线),才会告诉老师。如果只是判断"小红没在座位上"(从节点),你一个人看到就够了(不用问别人),因为小红不在不影响上课,其他同学还在。

  1. 面试题:Redis Sentinel如何选举"领导者节点"来负责故障转移?为什么必须选领导者,不能所有哨兵一起处理?

回答要点:Sentinel用"Raft算法"选举领导者,流程分四步,核心是"少数服从多数、避免多头指挥":

  1. 发起请求:某个哨兵确认主节点"主观下线"后,会向其他所有哨兵发送"sentinel is-master-down-by-addr"命令,同时附带"让我当领导者"的请求------相当于"我觉得主节点坏了,我来负责修,大家同意吗?"。

  2. 投票同意:其他哨兵收到请求后,如果"还没同意过其他哨兵的请求"(每个哨兵在一次选举中只能投1票),就会回复"同意",否则回复"拒绝"。

  3. 确认当选:如果发起请求的哨兵收到的"同意票数"超过"max(quorum, 哨兵总数/2 + 1)"(比如3个哨兵,quorum=2,max(2, 3/2+1)=2,超过2票即当选),就会成为领导者;如果没超过,就等下一轮重新发起。

  4. 执行转移:领导者当选后,独自负责故障转移的所有操作(选新主、调从节点、通知客户端),其他哨兵只负责监控,不插手。

必须选领导者的原因:避免"多头指挥"------如果所有哨兵一起处理故障转移,可能出现"两个哨兵同时选不同的从节点当新主",导致集群出现两个主节点(脑裂),数据彻底混乱。就像一个团队只能有一个队长,大家都指挥的话,没人知道该听谁的。

生活例子:班级选"临时组长"处理教室卫生问题(故障转移)------① 小明发现教室地面脏了(主节点主观下线),举手说"我来当组长安排打扫,大家同意吗?"(发起请求);② 小红和小刚没投过别人,举手同意(投票同意),小明得到2票(3个同学,超过2票),当选组长(确认当选);③ 小明安排小红擦黑板、小刚扫地(执行转移),自己不插手具体工作,避免小红和小刚都安排任务导致混乱。

  1. 面试题:Sentinel选举领导者时,"max(quorum, 哨兵总数/2 + 1)"这个票数规则怎么理解?举个例子说明为什么需要这个规则。

回答要点:这个规则的核心是"确保领导者得到'足够多'的支持,既符合quorum的预设要求,又满足'超过半数'的多数原则,避免少数哨兵选出来的领导者不被认可"。

◦ "quorum"是哨兵配置文件里预设的"判断主节点客观下线的最小同意数"(比如配置quorum=2),确保至少有quorum个哨兵认为主节点故障,才会触发选举;

◦ "哨兵总数/2 + 1"是"超过半数"的票数(比如3个哨兵需2票,4个需3票),确保领导者得到多数支持,避免"3个哨兵里2个选A,1个选B,A以2票当选,符合多数"。

例子1:3个哨兵,quorum=2。max(2, 3/2+1)=max(2, 2.5)=2,此时只要得到2票(超过2)就可当选。比如哨兵A发起请求,哨兵B和C都同意,A得到2票,满足quorum=2且超过半数,顺利当选;如果A只得到1票,既不满足quorum=2,也没超过半数,无法当选。

例子2:5个哨兵,quorum=3。max(3, 5/2+1)=max(3, 3.5)=3.5,此时需要得到4票(超过3.5)才能当选。如果哨兵A得到3票,虽然满足quorum=3,但没超过3.5,不能当选;得到4票时,既符合quorum要求,又超过半数(5个哨兵的半数是2.5),才能当选,确保后续故障转移时,大多数哨兵认可A的操作,不会出现分歧。

生活例子:公司选项目负责人(领导者),5个部门(哨兵),规定"至少3个部门同意(quorum=3),且同意数超过半数(5/2+1=3.5)"------如果A得到3票,虽然满足3个部门同意,但没超过3.5,其他2个部门可能不认可,后续推动项目会受阻;A得到4票时,4个部门都支持,既够quorum要求,又超过半数,项目推进时没人反对,效率更高。

三、Redis Sentinel新主节点挑选

  1. 面试题:Redis Sentinel故障转移时,如何从多个从节点中挑选"最合格"的新主节点?挑选流程分几步?每一步的判断标准是什么?

回答要点:挑选新主节点是故障转移的核心,分"四步筛选法",确保选出来的从节点"最健康、数据最完整、最稳定":

第一步:过滤"不健康"的从节点。排除三类从节点:① 处于"主观下线"状态的(比如从节点自己也宕机了);② 5秒内没回复过哨兵ping命令的(比如从节点网络卡顿,没法正常工作);③ 与旧主节点失联时间超过"down-after-milliseconds * 10"的(比如旧主节点down了30秒,从节点失联超过300秒,数据肯定很旧)。这一步先把"明显不能用"的从节点淘汰。

第二步:选"slave-priority(从节点优先级)"最高的。Redis的从节点配置里有"slave-priority"参数(默认100,数值越大优先级越高),优先级最高的从节点直接当选------这是人工预设的"优先顺序",比如把配置更好、性能更强的从节点设为高优先级,确保新主节点性能足够。

第三步:优先级相同,选"复制偏移量"最大的。复制偏移量是从节点复制旧主节点数据的"进度条"------偏移量越大,说明从节点复制的旧主数据越完整(比如旧主节点有1000条数据,偏移量999的从节点比偏移量500的多复制了499条),选它当新主,能最大程度减少数据丢失。

第四步:偏移量也相同,选"runid最小"的。runid是Redis节点启动时生成的唯一ID(类似身份证号),runid越小,说明节点启动时间越早------选启动早的节点,因为它运行更稳定(比如运行了1年的节点比运行1天的节点更不容易出问题)。

生活例子:学校选"临时班长"(新主节点),从5个副班长(从节点)里挑:

第一步:先排除------① 请假没来的(主观下线);② 老师喊了5次都没回应的(没回复ping);③ 一周没来上学的(与旧班长失联太久),剩下3个副班长(小明、小红、小刚)。

第二步:看"老师指定的优先级"------老师之前说"成绩前3名的优先",小明是年级第1(slave-priority=150),小红第2(slave-priority=120),小刚第3(slave-priority=100),小明优先级最高,先选小明;如果小明当天请假被排除,就选小红。

第三步:如果小明和小红都是年级前10(优先级相同,都设为120),看"作业完成度"(复制偏移量)------小明完成了98%的作业,小红完成了90%,选小明;如果两人都完成98%,进入第四步。

第四步:看"入学时间"(runid)------小明是一年级入学的(runid=1001,启动早),小红是三年级转来的(runid=3001),选小明,因为小明更熟悉班级纪律和同学情况,当班长更稳定。

四、Redis集群基础与数据分区

  1. 面试题:Redis集群相比"主从复制+Sentinel",核心优势是什么?解决了前者的哪些痛点?

回答要点:"主从复制+Sentinel"能解决高可用,但有两个致命痛点:① 单机内存上限------所有数据都存在主节点,主节点内存满了就没法扩容(比如主节点是8G内存,存满后不能再存新数据);② 单机性能瓶颈------所有写请求都压在主节点,主节点CPU/IO满了,写服务就会卡顿。而Redis集群的核心优势是"分布式存储+分布式高可用",同时解决这两个痛点:

◦ 分布式存储:把数据分成16384个"槽(slot)",每个主节点负责一部分槽(比如3个主节点,每个负责5461个槽),数据按"hash(key) mod 16384"分配到对应槽------相当于把"大蛋糕(所有数据)切成16384块,3个主节点各拿一块",每个主节点只存自己负责的槽数据,突破了单机内存上限(3个8G主节点,总内存24G)。

◦ 分布式高可用:每个主节点都有1个或多个从节点,主节点故障后,从节点自动升为主(类似Sentinel),且多个主节点同时提供写服务------比如3个主节点,写请求可以分散到3个节点,每个节点的CPU压力只有原来的1/3,解决了单机性能瓶颈。

生活类比:"主从复制+Sentinel"是"单家大超市"------1个主超市(主节点)存1000种商品,2个分店(从节点)备份这些商品,主超市仓库满了就没法进新货(内存上限),顾客结账只能去主超市(写请求集中),高峰时排队1小时;Redis集群是"连锁超市"------3个主超市各负责一片区域的商品(A超市卖食品、B超市卖日用品、C超市卖家电),总商品量3000种(内存扩容3倍),顾客可以去3个超市分别结账(写请求分散),高峰时排队不超过10分钟,某家超市装修(主节点故障),备用超市(从节点)立刻开门,不影响顾客购物。

  1. 面试题:分布式存储中常见的"数据分区方案"有三种,分别是"节点取余""一致性哈希""虚拟槽",请对比三者的优缺点,以及Redis集群为什么选"虚拟槽"?

回答要点:三种方案的核心区别是"数据如何映射到节点",优缺点对比清晰:

◦ 方案一:节点取余分区(hash(key) mod N,N是节点数)

优点:实现最简单,不用额外维护映射关系------比如3个节点,直接算key的hash值除以3的余数,余数0去节点1,余数1去节点2,余数2去节点3,开发时几行代码就能实现。

缺点:"节点增减时数据迁移量大"------比如N从3变成4,原来余数0的key(去节点1),现在可能变成余数1(去节点2),80%以上的key都要迁移,迁移期间服务卡顿,甚至因网络中断导致数据丢失。

生活例子:学校按"学号 mod 5"分5个班级,学号1→1班,学号2→2班...学号5→5班。如果新增1个班(N=6),原来学号6 mod5=1→1班,现在mod6=0→6班(要换班);学号10 mod5=0→5班,现在mod6=4→4班(要换班),一半以上的学生要搬桌子换班级,课堂秩序混乱,还可能丢课本(数据丢失)。

◦ 方案二:一致性哈希分区(将节点和key哈希到"虚拟圆环",key顺时针找第一个节点)

优点:节点增减只影响"相邻节点"------比如圆环上有节点A(hash=100)、B(hash=200)、C(hash=300),新增节点D(hash=150)在A和B之间,只有原来去A(hash100-150)的key会改去D,其他key不变,迁移量比节点取余少50%以上。

缺点:"节点分布不均,易出现热点"------如果节点IP/端口的hash值集中在圆环某一段,比如节点A(hash=100)和B(hash=110)离得很近,大部分key的hash值都在100-110之间,全去A节点,导致A压力大(热点),B很空闲;而且节点故障后,所有去该节点的key会全转移到下一个节点,比如A故障,100-200的key全去B,B瞬间压力翻倍(雪崩)。

生活例子:社区的自提柜分布------把自提柜的编号哈希到圆环上,柜A(hash=100)、柜B(hash=200)、柜C(hash=300),住户门牌号哈希后找最近的自提柜,门牌号1-150的去柜A,151-250的去柜B,251-300的去柜C。新增柜D(hash=150)后,只有100-150的住户改去柜D,其他不变(迁移量少);但如果柜A坏了,100-200的住户包裹全堆到柜B,柜B原本放50个包裹,现在要放150个,直接爆满(压力骤增),住户取件要等半小时。

◦ 方案三:虚拟槽分区(Redis集群用此方案)------先把数据映射到16384个"虚拟槽",再把槽分配给节点,key按"hash(key) mod 16384"确定槽,再找槽对应的节点。

优点:① 节点增减只迁移"部分槽"------比如3个节点各负责5461个槽,新增1个节点,只需从每个旧节点迁移1365个槽给新节点,迁移量仅25%(1/4),且迁移时按槽分批进行,不影响其他槽的服务;② 槽分布均匀------人工或自动分配槽,确保每个节点负责的槽数差不多(16384能被2-100个节点整除),避免热点;③ 槽是"数据迁移的最小单位"------迁移时只动槽,不用逐个迁移key,操作简单,且Redis自带槽迁移工具,不用手动写脚本。

缺点:需要维护"槽-节点"的映射关系------每个节点都要知道"哪个槽属于哪个节点",但Redis集群会通过Gossip协议自动同步这个映射,不用人工维护,只有新增/删除节点时才需要手动触发槽分配。

Redis集群选"虚拟槽"的核心原因:兼顾"低迁移量、均匀分布、易维护",完美解决了节点取余的"高迁移量"和一致性哈希的"分布不均"问题,且16384个槽的数量设计合理------既不会因槽太少导致单个槽数据量过大(迁移慢),也不会因槽太多导致节点维护成本高(每个槽占用内存少),最适合Redis的分布式场景。

生活例子:外卖平台按"16384个片区(槽)"分配骑手(节点),3个骑手各负责5461个片区,顾客下单时,按"地址hash mod 16384"确定片区,再找片区对应的骑手。新增1个骑手后,从每个旧骑手手里分1365个片区给新骑手(每次分1个片区,分完1个再分下一个),旧骑手继续送其他片区的订单,顾客下单不受影响;每个骑手负责4096个片区,订单量差不多(不忙不闲),不会出现某个骑手一天送200单、另一个只送50单的情况。

五、Redis集群创建与故障转移

  1. 面试题:创建一个"完整高可用"的Redis集群,至少需要多少个节点?为什么?部署时主节点为什么不能放在同一台物理机上?

回答要点:至少需要6个节点(3主3从),缺一不可,原因和"故障转移的投票规则"直接相关:

◦ 故障转移的投票要求:主节点故障后,从节点要当选新主,必须得到"超过半数的主节点投票"(比如3个主节点,至少2个投票同意)。如果节点数少于6个(比如2主2从),1个主节点故障后,只剩1个主节点,从节点最多只能得到1票,没超过半数(2主需2票),故障转移失败,集群无法提供写服务;如果是1主1从,主节点故障后,没有其他主节点投票,从节点永远无法当选新主,集群直接瘫痪。

◦ 3主3从的合理性:3个主节点,1个故障后还剩2个,从节点能得到2票(超过半数),故障转移成功;每个主节点配1个从节点,确保主节点故障后有备用,且3个从节点刚好够3个主节点的备份需求,不多不少------如果配2个从节点,会有1个主节点没备用,故障后无法转移;配4个从节点,会有1个从节点闲置,浪费资源,3主3从是性价比最高的组合。

主节点不能放同一台物理机的原因:避免"物理机单点故障"------如果3个主节点都放在1台物理机上,这台机器断电或宕机(比如硬盘损坏、主板故障),3个主节点会同时故障,从节点虽然在其他机器,但没有主节点能投票(全故障了),故障转移无法进行,整个集群彻底瘫痪,业务无法读写。只有把3个主节点分别放在3台物理机上,才能确保"一台物理机故障,只影响1个主节点,其他2个主节点正常工作,投票能正常进行",故障转移顺利完成,业务不受影响。

生活例子:小区的"应急供电系统"------需要3个主配电箱(主节点)+3个备用配电箱(从节点),共6个。如果3个主配电箱装在同一栋楼(同一物理机),这栋楼因线路老化停电,3个主配电箱全坏,备用配电箱要投票选新主,却没有主配电箱能投票(全故障),整个小区没电,居民只能点蜡烛;如果3个主配电箱分别装在3栋楼(3台物理机),1栋楼停电只影响1个主配电箱,另外2个主配电箱正常,备用配电箱能得到2票,顺利切换供电,小区其他2栋楼不停电,居民正常用电。

  1. 面试题:Redis集群的故障转移和Sentinel的故障转移,核心区别是什么?为什么会有这些区别?

回答要点:两者都是"主节点故障后自动切换",但核心区别在"监控主体、状态维护、适用场景"三个维度,这些区别源于两者的设计目标不同:

首先是监控主体不同:Redis集群的监控是"分布式监控",所有节点互相监控------每个节点每隔1秒向其他所有节点发送"ping"消息,接收节点回复"pong"消息,若超过"cluster-node-timeout"(默认15秒)没收到回复,发送节点就标记接收节点为"主观下线";而Sentinel的监控是"中心化监控",由单独的哨兵节点负责监控------哨兵节点专门发送ping命令监控主从节点,数据节点不参与监控,只负责存储数据。

其次是状态维护主体不同:Redis集群的状态由所有节点共同维护------"槽-节点"映射关系、节点健康状态等信息,通过Gossip协议在所有节点间同步,每个节点都有完整的集群状态;而Sentinel的状态由哨兵节点单独维护------主从节点的地址、健康状态等信息,只存在于哨兵节点中,数据节点不知道其他节点的状态。

最后是适用场景不同:Redis集群适用于"分布式存储场景"------需要多主节点分片存储数据,突破单机内存和性能瓶颈,比如电商平台的用户购物车数据(数据量大,需要分布式存储);而Sentinel适用于"单主多从场景"------数据量不大,只需高可用,不需要分布式存储,比如小型网站的用户会话存储(数据量小,单主节点足够)。

这些区别的核心原因:两者的设计目标不同。Sentinel的目标是"给单主多从架构加自动故障转移",不需要分布式存储,所以用"中心化监控"更简单------专门的哨兵节点干活,数据节点专注存数据,减少节点间的通信开销;Redis集群的目标是"分布式存储+高可用",需要多主节点协同工作,所以用"分布式监控"更可靠------所有节点都参与监控,避免哨兵节点的单点风险(比如所有哨兵节点宕机,Sentinel就失效了,但Redis集群的节点不会全宕机)。

生活例子:Sentinel故障转移像"小区有专门的安保队(哨兵节点)"------安保队有3个保安,每天巡逻监控大门(主节点)和侧门(从节点),大门坏了,保安们一起商量安排侧门当主门,住户(数据节点)不用管监控,只负责住家;Redis集群故障转移像"小区每个住户都是安全员(所有节点)"------住户既自己住家(存数据),又每天敲邻居家门确认安全(节点ping/pong),大门坏了,住户们一起投票选侧门当主门,不用依赖安保队,就算有1个住户不在家(节点故障),其他住户还能正常投票,更抗风险。

六、Redis集群伸缩

  1. 面试题:Redis集群如何实现"扩容"(加节点)和"缩容"(删节点)?核心原理是什么?操作时需要注意什么,才能不影响业务?

回答要点:Redis集群伸缩的核心原理是"槽和数据的迁移"------扩容时把旧节点的槽移给新节点,缩容时把待删节点的槽移给其他节点,全程"在线操作",不影响业务读写,这也是Redis集群相比其他分布式缓存的优势之一。

先看扩容流程(以"3主3从→4主4从"为例):

  1. 启动新节点:新增1个主节点和1个从节点,在配置文件中开启"cluster-enabled yes",让节点运行在集群模式,同时设置"cluster-config-file"指定集群配置文件路径(用于存储集群状态)。

  2. 加入集群:用"cluster meet 新节点IP 新节点端口"命令,在原有集群的任意一个节点上执行,把新主节点和新从节点加入集群------这一步相当于"介绍新成员给大家认识",原有节点会通过Gossip协议把新节点的信息同步给所有其他节点,几分钟后所有节点都知道新节点存在。

  3. 迁移槽和数据:这是扩容的核心步骤,需要手动触发或用工具自动执行。先确定要迁移的槽:16384个槽分给4个主节点,每个主节点负责4096个槽,所以要从原有3个主节点中各选1365个槽(3×1365=4095,加上新节点自带的1个槽,共4096个)。然后用"cluster setslot 槽号 importing 新主节点ID"命令,让旧节点把指定槽的 data 导出;再用"cluster setslot 槽号 migrating 旧节点ID"命令,让新节点接收这个槽的 data;最后用"cluster getkeysinslot 槽号 100"命令,把槽里的key分批迁移到新节点(每次迁100个key,避免一次性迁移太多导致卡顿)。

  4. 配置从节点:在新从节点上执行"cluster replicate 新主节点ID"命令,让新从节点复制新主节点的数据,成为新主节点的备用节点------这一步完成后,扩容就结束了,新主节点开始接收自己负责的槽的读写请求。

再看缩容流程(以"4主4从→3主3从"为例):

  1. 迁移槽和数据:这是缩容的核心,必须先迁槽再删节点。先确定待删主节点负责的4096个槽,把这些槽平均分给其他3个主节点(每个主节点接收1365或1366个槽)。用和扩容类似的命令,先让待删节点把槽导出,再让其他节点接收槽,分批迁移key,直到待删节点的槽数为0(用"cluster slots"命令可查看槽分布)。

  2. 下线从节点:先在待删从节点的所有邻居节点上执行"cluster forget 待删从节点ID"命令,让集群忘记这个从节点(不再同步它的信息),然后停止从节点的Redis服务------这一步要确保从节点没有数据要同步,避免数据丢失。

  3. 下线主节点:确认待删主节点的槽已全部迁移(槽数为0),且没有任何key后,在所有邻居节点上执行"cluster forget 待删主节点ID"命令,让集群忘记这个主节点,最后停止主节点的Redis服务------缩容完成,集群恢复3主3从的结构,业务读写不受影响。

操作时的注意事项有三点:

一是迁移槽时要"分批迁移":每次只迁移1个槽或少量key(比如100个),迁移完1个再迁移下一个,避免一次性迁移大量槽或key导致节点CPU/IO过高,影响业务请求的响应时间(比如电商平台高峰时,迁移太快会导致用户下单卡顿)。

二是迁移前要"检查数据一致性":用"cluster getkeysinslot 槽号 数量"命令,查看迁移前后槽里的key数量是否一致,比如迁移前槽100有500个key,迁移后新节点的槽100也应有500个key,确保没有数据丢失(数据丢失会导致业务报错,比如用户购物车数据不见了)。

三是缩容时要"先迁槽再下线":必须先把待删节点的槽全部迁移到其他节点,确保待删节点不再负责任何槽的读写请求后,再停止节点服务------如果先下线节点再迁槽,槽对应的key会无法访问,用户请求会返回"MOVED"错误(业务无法正常使用)。

生活例子:连锁奶茶店的"扩店"和"关店"就像Redis集群的伸缩:

扩容(开新店):先租一个新店(启动新节点),告诉其他3家老店"新店开了,大家认识一下"(加入集群);然后从每家老店分10个片区的客户(迁移1365个槽),每家老店每次转1个片区的客户信息(分批迁移key),转完1个再转下一个,老店继续服务其他片区的客户;最后招一个店员(新从节点)帮新店做奶茶,扩容完成,新店开始接待自己片区的客户。

缩容(关老店):先把老店负责的40个片区客户,分给其他3家店(迁移4096个槽),每次转1个片区的客户信息,确保客户都能找到新的奶茶店;然后让老店的辅助店员(从节点)离职(下线从节点);最后确认老店没有客户了,再关店(下线主节点),缩容完成,客户买奶茶不受影响。

相关推荐
222you3 小时前
Mybatis(1)
java·tomcat·mybatis
渣哥3 小时前
三级缓存揭秘:Spring 如何优雅地处理循环依赖问题
javascript·后端·面试
靠近彗星3 小时前
1.5操作系统引导
java·linux·服务器·操作系统
渣哥3 小时前
为什么几乎所有 Java 项目都离不开 IoC?Spring 控制反转的优势惊人!
javascript·后端·面试
前端赵哈哈3 小时前
Vue I18n 完整安装与使用指南
前端·vue.js·面试
瑶山4 小时前
社区版Idea怎么创建Spring Boot项目?Selected Java version 17 is not supported. 问题解决
java·spring boot·intellij-idea·创建项目
学习编程的Kitty4 小时前
JavaEE初阶——多线程(1)初识线程与创建线程
java·开发语言·java-ee
长安城没有风4 小时前
从入门到精通【Redis】初识Redis哨兵机制(Sentinel)
java·数据库·redis·后端
蒂法就是我4 小时前
java集合类的底层类是哪个
java·开发语言