面试题答案
一键面试故障检测
- 心跳机制:Redis集群节点之间通过定期发送心跳包(PING消息)来检测彼此的存活状态。若在一定时间内未收到某个节点的心跳响应(PONG消息),则判定该节点疑似故障。
- 主观下线(PFail):当某个节点对另一个节点的心跳检测超时而未收到响应,会将其标记为主观下线(PFail),表明自身认为该节点可能出现故障,但此时整个集群还未正式认定该节点故障。
- 客观下线(Fail):当集群中超过半数的主节点都将某个节点标记为主观下线时,这个节点会被标记为客观下线(Fail),此时集群会认为该节点已不可用,触发故障转移流程。
数据迁移
- 故障转移:当某个主节点被标记为客观下线后,集群会从该主节点的从节点中选举出一个新的主节点。选举过程基于Raft算法的变种,从节点会向其他主节点请求投票,得票最多且超过半数的从节点会成为新的主节点,接管故障主节点的所有数据槽。
- 重新分片:如果故障节点是主节点且没有足够的从节点来进行故障转移,或者集群出于负载均衡等原因,可能需要进行手动或自动的重新分片操作。Redis提供了
redis-trib.rb
工具(在Redis 6.0之前)或CLUSTER ADDSLOTS
、CLUSTER DELSLOTS
等命令来手动调整数据槽的分布。在自动重新分片场景下,集群管理系统(如Redis Cluster Manager等)会自动计算并执行数据槽的迁移,将原本分配给故障节点的数据槽重新分配到其他正常节点上。数据迁移过程中,会通过MIGRATE
命令将数据从源节点传输到目标节点。
读写策略调整
- 读策略
- 故障前:读请求通常优先从Redis集群读取数据。客户端会根据数据的键计算出对应的CRC16值,再对16384取模,得到数据所在的数据槽编号,进而定位到存储该数据的Redis节点。
- 故障后:当部分Redis节点故障时,若客户端发现从Redis读取数据失败(如返回
MOVED
错误表示数据已迁移,或直接连接失败等情况),则立即切换到从MySQL读取数据。为了减少对MySQL的压力,可以在应用层增加缓存层,将从MySQL读取的数据暂时缓存起来。例如,可以使用Guava Cache等本地缓存,当再次请求相同数据时,优先从本地缓存读取,若本地缓存不存在则从MySQL读取并更新本地缓存。
- 写策略
- 故障前:写请求会同时写入MySQL和Redis集群。写入Redis时,同样通过键计算数据槽编号找到对应的节点进行写入。
- 故障后:若Redis节点故障导致写操作失败,应用程序可以选择重试一定次数(如3次),如果仍然失败,则先确保数据成功写入MySQL,同时记录失败日志。对于Redis写入失败的数据,可以在故障恢复后,通过日志记录将这些数据重新同步到Redis集群中。为了确保数据一致性,在从MySQL读取数据时,可以对比数据的版本号(如在MySQL表中增加一个版本字段,每次写入操作版本号递增),若发现Redis中的数据版本号落后于MySQL,则从MySQL重新读取数据并更新到Redis。