Redis(140)Redis的Cluster的故障转移是如何实现的?

作者:Victor356日期:2025/11/23

Redis Cluster 的故障转移机制确保在主节点(Master)出现故障时,集群中的从节点(Slave)能够自动接管主节点的角色,从而保证高可用性。故障转移的实现涉及节点状态监控、故障检测、选举新主节点及更新集群状态等步骤。下面我们详细解析这些步骤,并结合代码示例进行深入探讨。

1. 节点状态监控和故障检测

每个 Redis 集群节点都会定期向其他节点发送 PING 消息,并期望收到 PONG 回复。如果在一定时间内未收到回复,该节点将认为目标节点可能失效。

代码示例

1/* Cluster node structure */
2typedef struct clusterNode {
3    char name[40];      /* Node ID */
4    int flags;          /* Node flags: master, slave, fail, etc. */
5    mstime_t ping_sent; /* Last time a ping was sent */
6    mstime_t pong_received; /* Last time a pong was received */
7    // other fields...
8} clusterNode;
9
10/* Function to check for node failures */
11void clusterCron(void) {
12    mstime_t now = mstime();
13    dictIterator *di;
14    dictEntry *de;
15
16    di = dictGetSafeIterator(server.cluster->nodes);
17    while((de = dictNext(di)) != NULL) {
18        clusterNode *node = dictGetVal(de);
19
20        if (node->flags & CLUSTER_NODE_MYSELF) continue;
21
22        if (now - node->pong_received > server.cluster_node_timeout) {
23            // Mark the node as failing
24            node->flags |= CLUSTER_NODE_PFAIL;
25            printf("Node %s is in PFAIL state\n", node->name);
26        }
27    }
28    dictReleaseIterator(di);
29}
30

2. 故障确认和投票

当一个节点被标记为 PFAIL(疑似失败)状态后,如果多数主节点(Master)也标记该节点为 FAIL(确定失败)状态,那么该节点将被认为真的失效。

代码示例

1/* Function to confirm node failure */
2void clusterSendFail(clusterNode *node) {
3    dictIterator *di;
4    dictEntry *de;
5
6    di = dictGetSafeIterator(server.cluster->nodes);
7    while ((de = dictNext(di)) != NULL) {
8        clusterNode *peer = dictGetVal(de);
9
10        if (peer->flags & CLUSTER_NODE_MYSELF) continue;
11
12        // Send FAIL message to other nodes
13        clusterSendMessage(peer, node, CLUSTERMSG_TYPE_FAIL);
14    }
15    dictReleaseIterator(di);
16}
17
18/* Function to process FAIL messages */
19void clusterProcessFail(clusterMsg *msg) {
20    clusterNode *node = clusterLookupNode(msg->data.fail.nodeid);
21
22    if (node == NULL) return;
23
24    // Mark the node as FAIL
25    node->flags |= CLUSTER_NODE_FAIL;
26    printf("Node %s marked as FAIL\n", node->name);
27}
28

3. 选举新的主节点

当主节点被确定为失效后,其从节点将参与选举。参与选举的从节点会向其他主节点发送投票请求,并根据收到的投票数量决定是否成为新的主节点。

代码示例

1/* Function to initiate failover */
2void clusterHandleSlaveFailover(clusterNode *slave) {
3    if (!(slave->flags & CLUSTER_NODE_SLAVE)) return;
4
5    // Promote the slave to master
6    slave->flags &= ~CLUSTER_NODE_SLAVE;
7    slave->flags |= CLUSTER_NODE_MASTER;
8
9    // Send update to the cluster
10    clusterBroadcastSlaveOf(slave, NULL);
11    printf("Slave %s promoted to master\n", slave->name);
12}
13
14/* Function to broadcast SLAVEOF message */
15void clusterBroadcastSlaveOf(clusterNode *node, clusterNode *master) {
16    dictIterator *di;
17    dictEntry *de;
18
19    di = dictGetSafeIterator(server.cluster->nodes);
20    while ((de = dictNext(di)) != NULL) {
21        clusterNode *peer = dictGetVal(de);
22
23        if (peer->flags & CLUSTER_NODE_MYSELF) continue;
24
25        clusterSendMessage(peer, node, CLUSTERMSG_TYPE_SLAVEOF, master);
26    }
27    dictReleaseIterator(di);
28}
29
30/* Function to process SLAVEOF messages */
31void clusterProcessSlaveOf(clusterMsg *msg) {
32    clusterNode *node = clusterLookupNode(msg->data.slaveof.nodeid);
33
34    if (node == NULL) return;
35
36    // Update the node's master
37    node->slaveof = clusterLookupNode(msg->data.slaveof.masterid);
38    printf("Node %s updated to follow master %s\n", node->name, node->slaveof->name);
39}
40

4. 更新集群状态

一旦新的主节点被选定,集群中所有节点需要更新自己的状态信息,以便正确地处理客户端请求。

代码示例

1/* Function to update cluster state */
2void clusterUpdateState(void) {
3    dictIterator *di;
4    dictEntry *de;
5
6    di = dictGetSafeIterator(server.cluster->nodes);
7    while((de = dictNext(di)) != NULL) {
8        clusterNode *node = dictGetVal(de);
9
10        if (node->flags & CLUSTER_NODE_MASTER) {
11            // Update master's state
12        } else if (node->flags & CLUSTER_NODE_SLAVE) {
13            // Update slave's state
14        }
15    }
16    dictReleaseIterator(di);
17}
18

综合示例

以下是一个综合性的代码示例,展示了 Redis Cluster 故障转移的完整流程。

1#include <stdio.h>
2#include <string.h>
3#include <stdint.h>
4#include <time.h>
5#include "crc16.h"  // Assume crc16.h provides crc16 function
6#include "dict.h"   // Assume dict.h provides a dictionary implementation
7#include "mstime.h" // Assume mstime.h provides mstime function
8
9#define CLUSTER_NODE_TIMEOUT 15000  // 15 seconds
10#define CLUSTER_NODE_MYSELF 0x01
11#define CLUSTER_NODE_MASTER 0x02
12#define CLUSTER_NODE_SLAVE 0x04
13#define CLUSTER_NODE_PFAIL 0x08
14#define CLUSTER_NODE_FAIL  0x10
15
16typedef struct clusterNode {
17    char name[40];      /* Node ID */
18    int flags;          /* Node flags: master, slave, fail, etc. */
19    mstime_t ping_sent; /* Last time a ping was sent */
20    mstime_t pong_received; /* Last time a pong was received */
21    struct clusterNode *slaveof; /* Master of this node if it's a slave */
22    // other fields...
23} clusterNode;
24
25typedef struct clusterState {
26    dict *nodes;        /* All known nodes in the cluster */
27} clusterState;
28
29clusterState *server.cluster;
30
31/* Function to hash a key to a slot */
32unsigned int keyHashSlot(char *key, int keylen) {
33    return crc16(key, keylen) & 16383;
34}
35
36/* Function to send a message to a node */
37void clusterSendMessage(clusterNode *node, const char *msg) {
38    // In a real implementation, this would send the message over a network
39    printf("Sending message to node %s: %s\n", node->name, msg);
40}
41
42/* Function to check for node failures */
43void clusterCron(void) {
44    mstime_t now = mstime();
45    dictIterator *di;
46    dictEntry *de;
47
48    di = dictGetSafeIterator(server.cluster->nodes);
49    while((de = dictNext(di)) != NULL) {
50        clusterNode *node = dictGetVal(de);
51
52        if (node->flags & CLUSTER_NODE_MYSELF) continue;
53
54        if (now - node->pong_received > CLUSTER_NODE_TIMEOUT) {
55            // Mark the node as failing
56            node->flags |= CLUSTER_NODE_PFAIL;
57            printf("Node %s is in PFAIL state\n", node->name);
58        }
59    }
60    dictReleaseIterator(di);
61}
62
63/* Function to confirm node failure */
64void clusterSendFail(clusterNode *node) {
65    dictIterator *di;
66    dictEntry *de;
67
68    di = dictGetSafeIterator(server.cluster->nodes);
69    while ((de = dictNext(di)) != NULL) {
70        clusterNode *peer = dictGetVal(de);
71
72        if (peer->flags & CLUSTER_NODE_MYSELF) continue;
73
74        // Send FAIL message to other nodes
75        clusterSendMessage(peer, "FAIL");
76    }
77    dictReleaseIterator(di);
78}
79
80/* Function to process FAIL messages */
81void clusterProcessFail(clusterMsg *msg) {
82    clusterNode *node = clusterLookupNode(msg->data.fail.nodeid);
83
84    if (node == NULL) return;
85
86    // Mark the node as FAIL
87    node->flags |= CLUSTER_NODE_FAIL;
88    printf("Node %s marked as FAIL\n", node->name);
89}
90
91/* Function to initiate failover */
92void clusterHandleSlaveFailover(clusterNode *slave) {
93    if (!(slave->flags & CLUSTER_NODE_SLAVE)) return;
94
95    // Promote the slave to master
96    slave->flags &= ~CLUSTER_NODE_SLAVE;
97    slave->flags |= CLUSTER_NODE_MASTER;
98
99    // Send update to the cluster
100    clusterBroadcastSlaveOf(slave, NULL);
101    printf("Slave %s promoted to master\n", slave->name);
102}
103
104/* Function to broadcast SLAVEOF message */
105void clusterBroadcastSlaveOf(clusterNode *node, clusterNode *master) {
106    dictIterator *di;
107    dictEntry *de;
108
109    di = dictGetSafeIterator(server.cluster->nodes);
110

Redis(140)Redis的Cluster的故障转移是如何实现的?》 是转载文章,点击查看原文


相关推荐


基于51单片机的PD协议移动电源控制程序
t198751282025/11/21

含PD协议通信、电池管理、充电控制和状态显示等功能。 #include <reg52.h> #include <intrins.h> // 硬件引脚定义 sbit USB_CC1 = P1^0; // Type-C CC1检测引脚 sbit USB_CC2 = P1^1; // Type-C CC2检测引脚 sbit USB_DM = P1^2; // USB D- 引脚 sbit USB_DP = P1^3; // USB D+ 引脚 sbit L


嵌入式C++安全编码
普通网友2025/11/19

1、非修改序列算法 这些算法不会改变它们所操作的容器中的元素。 1.1 find 和 find_if find(begin, end, value):查找第一个等于 value 的元素,返回迭代器(未找到返回 end)。find_if(begin, end, predicate):查找第一个满足谓词的元素。find_end(begin, end, sub_begin, sub_end):查找子序列最后一次出现的位置。 vector<int> nums = {1, 3, 5, 7, 9};


苹果应用商店上架全流程 从证书体系到 IPA 上传的跨平台方法
aiopencode2025/11/18

将应用成功发布到苹果应用商店(App Store)往往是移动开发流程中最具挑战的一环。 相比 Android 的自由生态,苹果 App Store 在审核机制、签名系统、隐私要求等方面都有严格规范。 很多团队第一次上架都会遇到证书混乱、IPA 上传失败、审核被拒等问题。 好消息是——如今的工具生态已经成熟,无论你使用的是 macOS、Windows 或 Linux,都可以完成 App Store 上架。 本文将从实战开发者角度,完整梳理 “苹果应用商店上架” 的必要步骤、工具选择与跨平台处理方式


下载安装pycharm 并通过pycahrm来驱动Anaconda来运行Python程序
BugMaker01142025/11/17

目录 下载安装创建新项目 下载 点击跳转官方下载地址 点击下载 建议下载最新版再往前几个版本 选择需要的版本 安装 双击安装包 选择目标安装路径 选择需要的选项 然后选择下一步并安装 如果需要破解 完成安装后先关掉pycharm 再点击 然后再打开pycharm 创建新项目 选择创建新项目 选择现有环境 因为已经安装过了Anaconda 然后选择create


Python 的内置函数 object
IMPYLH2025/11/16

Python 内建函数列表 > Python 的内置函数 object Python 的内置函数 object 是 Python 中最基础的类,它是所有类的基类。在 Python 中,所有的类都直接或间接地继承自 object 类。object 类提供了一些默认的方法和属性,这些方法和属性可以被所有 Python 对象使用。 基本特性 继承关系:所有 Python 类默认都继承自 object。例如,定义一个空类时,实际上它已经隐式地继承了 object 类。 class MyClass


vue2中实现天气预报
王阔阔2025/11/14

vue2中实现天气预报功能 实现效果图静态页完整代码echarts组件代码最终实现页面渲染使用到的函数年-月-日字符串转为 昨天、今天、明天、周几 实现效果图 静态页完整代码 <template> <div class="weather-container"> <div class="weather-top"> <!-- 市区选择和更新时间 --> <p class="city-select padding-l-r-10">


企业项目级医院随访系统源码,患者随访管理系统,技术框架:Java+Spring boot,Vue,Ant-Design+MySQL5
源码宝2025/11/13

项目级医院随访系统源码,患者随访管理系统源码,三级随访系统源码,java版随访系统全套源码。 在医患关系日益紧张的当下,提升医院服务质量和效率成为了医疗机构亟待解决的问题。在此背景下,医院随访系统作为一种信息化管理工具应运而生,它不仅优化了医患关系,更是在医疗服务的多个环节中起到了至关重要的作用。  医院随访系统的核心功能是患者资料管理、医患沟通和随访平台。该系统通过集成先进的信息技术,为医院提供了全面的患者信息支持,包括患者的个人基本信息、住院详情、治疗过程以及后续的随访记录。这样的信息管


【微服务 - easy视频 | day04】Seata解决分布式事务
serendipity_hky2025/11/12

文章目录 前言Seata解决分布式事务 前言 本项目非原创,我只是个小小白,跟随 b 站脚步,找到老罗的这个项目,视频来源于: https://www.bilibili.com/video/BV1oEUkY6EFy/?spm_id_from=333.1387.homepage.video_card.click 本人不分享项目源码,支持项目付费!!! Seata解决分布式事务 (可以好好看看seata官网中的讲述) seata官网:https://seata.apac


Unity UGC IDE实现深度解析(五):事件系统与消息传递
NocturnalSky2025/11/10

Unity UGC IDE实现深度解析(五):事件系统与消息传递 引言 在上一篇中,我们构建了数据的"存储与流动"机制。但仅有数据流还不够——真实的游戏逻辑充满了事件驱动的场景:角色受击、任务完成、UI按钮点击……这些都需要一个强大的事件系统来协调。 本篇将实现一个解耦、可扩展、支持异步的事件系统,让节点图能够响应Unity引擎事件,并支持跨图表通信。 一、事件系统整体架构 1.1 设计思路 事件系统需要解决四个核心问题: 如何封装Unity事件(MonoBehaviour生


TrueNas Scale配置immich集成GPU硬件加速,用于智能模型,人脸识别,OCR文本识别加速
小黑小黑白2025/11/8

本文主要描述在TrueNas Scale中,为Immich应用配置GPU硬件加速的踩坑记录,旨在加速immich的人脸识别,ocr识别等智能模型推理,欢迎沟通讨论~ 前言 自从TrueNas Scale从Electric Eel 24.10.1版本由k3s转docker之后,对于容器镜像的操作更加方便,immich的快速迭代与truenas scale的兼容适配也更好,之前immich导入本地模型,pod重启消失的问题也优化了。随着最近immich的OCR文本识别的功能集成,针对历史图片的机器

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读