元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
Redis核心
▶
数据结构
字符串实现
哈希表实现
列表实现
集合实现
有序集合实现
▶
内存管理
内存分配策略
淘汰算法
▶
持久化
▶
RDB机制
快照生成原理
文件格式解析
▶
AOF机制
命令追加策略
重写过程分析
▶
高可用
▶
主从复制
SYNC原理
增量复制
▶
哨兵机制
故障检测
领导选举
▶
高级特性
▶
事务系统
ACID实现
WATCH原理
▶
Lua脚本
沙盒环境
执行管道
▶
实战问题
▶
缓存问题
缓存雪崩
缓存穿透
缓存击穿
缓存预热
▶
数据一致性
读写一致性
双写一致性
▶
性能优化
大key处理
热点key优化
发布时间:
2025-03-22 10:47
↑
☰
# Redis Sentinel故障检测机制 ## 引言 Redis Sentinel是Redis的高可用解决方案,通过故障检测机制实现主节点的自动发现和故障转移。本文将深入分析Sentinel的故障检测原理、实现机制以及最佳实践。 ## 基本概念 ### 1. Sentinel架构 ```conf # Sentinel配置示例 port 26379 sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel failover-timeout mymaster 180000 sentinel parallel-syncs mymaster 1 ``` ### 2. 主观下线和客观下线 ```c // 主观下线判断 typedef struct sentinelRedisInstance { int flags; // 实例标志 mstime_t s_down_since_time; // 主观下线时间 mstime_t o_down_since_time; // 客观下线时间 } sentinelRedisInstance; #define SRI_S_DOWN (1<<0) // 主观下线标志 #define SRI_O_DOWN (1<<1) // 客观下线标志 ``` ## 故障检测原理 ### 1. PING机制 ```c // PING命令实现 void sentinelPingInstance(sentinelRedisInstance *ri) { mstime_t now = mstime(); mstime_t ping_time; /* 发送PING命令 */ if (ri->link->act_ping_time == 0) { ri->link->act_ping_time = now; ri->link->last_ping_time = now; if (redisAsyncCommand(ri->link->cc,sentinelPingReplyCallback,NULL, "PING") == C_OK) { ri->link->pending_commands++; } } /* 检查超时 */ ping_time = now - ri->link->act_ping_time; if (ping_time > ri->down_after_period) { /* 标记为主观下线 */ instanceLinkDisconnectFromMaster(ri); ri->flags |= SRI_S_DOWN; ri->s_down_since_time = now; } } ``` ### 2. 信息交换 ```c // 信息发布订阅 void sentinelPublishEvent(char *channel, char *event, char *type, char *data) { robj *channel_obj = createStringObject(channel,strlen(channel)); robj *message = createStringObject(event,strlen(event)); /* 发布事件 */ pubsubPublishMessage(channel_obj,message); decrRefCount(channel_obj); decrRefCount(message); } // 处理订阅消息 void sentinelReceiveHelloMessages(redisAsyncContext *c, void *reply, void *privdata) { sentinelRedisInstance *ri = privdata; redisReply *r = reply; /* 解析消息 */ if (r->type == REDIS_REPLY_ARRAY && r->elements == 3 && r->element[0]->type == REDIS_REPLY_STRING && r->element[1]->type == REDIS_REPLY_STRING && r->element[2]->type == REDIS_REPLY_STRING) { sentinelProcessHelloMessage(r->element[0]->str, r->element[1]->str, r->element[2]->str); } } ``` ### 3. 故障确认 ```c // 客观下线判断 void sentinelCheckObjectivelyDown(sentinelRedisInstance *master) { dictIterator *di; dictEntry *de; unsigned int quorum = 0, odown = 0; /* 统计主观下线数量 */ di = dictGetIterator(master->sentinels); while((de = dictNext(di)) != NULL) { sentinelRedisInstance *ri = dictGetVal(de); if (ri->flags & SRI_MASTER_DOWN) quorum++; } dictReleaseIterator(di); /* 判断是否达到客观下线条件 */ if (quorum >= master->quorum) odown = 1; /* 设置客观下线标志 */ if (odown) { if ((master->flags & SRI_O_DOWN) == 0) { master->flags |= SRI_O_DOWN; master->o_down_since_time = mstime(); } } else { master->flags &= ~SRI_O_DOWN; } } ``` ## 性能优化 ### 1. 网络优化 ```conf # 心跳检测间隔 sentinel monitor mymaster 127.0.0.1 6379 2 # 主观下线时间 sentinel down-after-milliseconds mymaster 5000 ``` ### 2. 超时优化 ```conf # 故障转移超时 sentinel failover-timeout mymaster 180000 # 并行同步数量 sentinel parallel-syncs mymaster 1 ``` ### 3. 带宽优化 ```c // 消息压缩 int sentinelSendPing(sentinelRedisInstance *ri) { char *cmd = "*1\r\n$4\r\nPING\r\n"; size_t cmdlen = 14; /* 发送PING命令 */ if (ri->link->cc && redisAsyncWrite(ri->link->cc,cmd,cmdlen) == REDIS_OK) { return 1; } return 0; } ``` ## 监控和维护 ### 1. 状态监控 ```redis # 查看Sentinel状态 SENTINEL MASTER mymaster # 查看从节点状态 SENTINEL SLAVES mymaster ``` ### 2. 故障处理 ```c // 故障恢复 void sentinelFailoverStateMachine(sentinelRedisInstance *ri) { mstime_t now = mstime(); if (!(ri->flags & SRI_FAILOVER_IN_PROGRESS)) return; switch(ri->failover_state) { case SENTINEL_FAILOVER_STATE_WAIT_START: sentinelFailoverWaitStart(ri); break; case SENTINEL_FAILOVER_STATE_SELECT_SLAVE: sentinelFailoverSelectSlave(ri); break; case SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE: sentinelFailoverSendSlaveOfNoOne(ri); break; case SENTINEL_FAILOVER_STATE_WAIT_PROMOTION: sentinelFailoverWaitPromotion(ri); break; case SENTINEL_FAILOVER_STATE_RECONF_SLAVES: sentinelFailoverReconfNextSlave(ri); break; } } ``` ### 3. 性能监控 ```redis # 监控故障转移次数 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster # 监控主观下线次数 SENTINEL PENDING-SCRIPTS ``` ## 最佳实践 ### 1. 部署建议 - 至少部署3个Sentinel节点 - 分布在不同的物理机器上 - 配置合适的网络超时参数 ### 2. 配置建议 - 合理设置主观下线时间 - 配置适当的故障转移超时 - 控制并行同步数量 ### 3. 监控建议 - 实时监控Sentinel状态 - 记录故障转移日志 - 设置告警阈值 ### 4. 运维建议 - 定期检查节点状态 - 及时处理故障告警 - 做好配置备份 ## 常见问题 ### 1. 网络问题 - 网络分区处理 - 超时参数调优 - 心跳机制优化 ### 2. 一致性问题 - 脑裂问题处理 - 数据同步延迟 - 配置不一致 ### 3. 性能问题 - 故障检测延迟 - 资源占用过高 - 带宽消耗大 ## 总结 Redis Sentinel的故障检测机制是实现高可用的核心,通过主观下线和客观下线的双重判断,以及完善的故障转移流程,保证了Redis服务的可靠性。在实际应用中,需要根据业务场景合理配置Sentinel参数,并建立完善的监控和运维机制,确保Redis集群的稳定运行。