Redis(147)Redis的Cluster的容错性如何?

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

Redis Cluster 通过多种机制来实现高容错性,包括主从复制、自动故障转移和Gossip协议。这些机制确保即使在节点发生故障时,集群仍然能继续运行并提供服务。以下是详细的解释,并结合Java代码示例来说明其实现。

1. 主从复制(Master-Slave Replication)

主从复制是Redis Cluster最基础的高容错机制。每个主节点可以有一个或多个从节点,这些从节点复制主节点的数据。当主节点发生故障时,从节点可以接管其角色。

代码示例

1import java.util.ArrayList;
2import java.util.List;
3
4class ClusterNode {
5    String name;
6    String ip;
7    int port;
8    boolean isMaster;
9    ClusterNode master;
10
11    ClusterNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
12        this.name = name;
13        this.ip = ip;
14        this.port = port;
15        this.isMaster = isMaster;
16        this.master = master;
17    }
18
19    @Override
20    public String toString() {
21        return "Node " + name + ": " + ip + ":" + port + ", Role: " + (isMaster ? "Master" : "Slave");
22    }
23}
24
25class Cluster {
26    List<ClusterNode> nodes = new ArrayList<>();
27
28    void addNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
29        nodes.add(new ClusterNode(name, ip, port, isMaster, master));
30    }
31
32    void printNodes() {
33        for (ClusterNode node : nodes) {
34            System.out.println(node);
35        }
36    }
37}
38
39public class RedisClusterDemo {
40    public static void main(String[] args) {
41        Cluster cluster = new Cluster();
42
43        ClusterNode master1 = new ClusterNode("master1", "192.168.1.1", 6379, true, null);
44        cluster.addNode(master1.name, master1.ip, master1.port, master1.isMaster, master1.master);
45        cluster.addNode("slave1", "192.168.1.2", 6379, false, master1);
46
47        cluster.printNodes();
48    }
49}
50

2. 自动故障转移(Automatic Failover)

当主节点发生故障时,从节点会被提升为主节点。这个机制需要其他节点的协作,以保证集群的一致性和数据的完整性。

代码示例

1import java.util.ArrayList;
2import java.util.List;
3import java.util.Timer;
4import java.util.TimerTask;
5
6class ClusterNode {
7    String name;
8    String ip;
9    int port;
10    boolean isMaster;
11    ClusterNode master;
12    long lastHeartbeat;
13    boolean isFailed;
14
15    ClusterNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
16        this.name = name;
17        this.ip = ip;
18        this.port = port;
19        this.isMaster = isMaster;
20        this.master = master;
21        this.lastHeartbeat = System.currentTimeMillis();
22        this.isFailed = false;
23    }
24
25    void sendHeartbeat() {
26        System.out.println("Sending heartbeat to node " + name);
27        lastHeartbeat = System.currentTimeMillis();
28    }
29
30    void checkHeartbeat() {
31        long now = System.currentTimeMillis();
32        if (now - lastHeartbeat > 3000) { // 3 seconds timeout
33            System.out.println("Node " + name + " is not responding");
34            isFailed = true;
35        }
36    }
37
38    @Override
39    public String toString() {
40        return "Node " + name + ": " + ip + ":" + port + ", Role: " + (isMaster ? "Master" : "Slave");
41    }
42}
43
44class Cluster {
45    List<ClusterNode> nodes = new ArrayList<>();
46
47    void addNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
48        nodes.add(new ClusterNode(name, ip, port, isMaster, master));
49    }
50
51    void handleFailover() {
52        for (ClusterNode node : nodes) {
53            if (node.isMaster && node.isFailed) {
54                for (ClusterNode slave : nodes) {
55                    if (slave.master == node) {
56                        System.out.println("Failover: promoting slave node " + slave.name + " to master");
57                        slave.isMaster = true;
58                        slave.master = null;
59                        node.isMaster = false;
60                        return;
61                    }
62                }
63            }
64        }
65    }
66
67    void simulateCluster() {
68        Timer timer = new Timer(true);
69        TimerTask task = new TimerTask() {
70            @Override
71            public void run() {
72                for (ClusterNode node : nodes) {
73                    if (node.isMaster && !node.isFailed) {
74                        node.sendHeartbeat();
75                    } else {
76                        node.checkHeartbeat();
77                        if (node.isFailed && node.isMaster) {
78                            handleFailover();
79                        }
80                    }
81                }
82            }
83        };
84        timer.scheduleAtFixedRate(task, 0, 1000);
85    }
86
87    void printNodes() {
88        for (ClusterNode node : nodes) {
89            System.out.println(node);
90        }
91    }
92}
93
94public class RedisClusterDemo {
95    public static void main(String[] args) throws InterruptedException {
96        Cluster cluster = new Cluster();
97
98        ClusterNode master1 = new ClusterNode("master1", "192.168.1.1", 6379, true, null);
99        cluster.addNode(master1.name, master1.ip, master1.port, master1.isMaster, master1.master);
100        cluster.addNode("slave1", "192.168.1.2", 6379, false, master1);
101        cluster.addNode("slave2", "192.168.1.3", 6379, false, master1);
102
103        cluster.printNodes();
104
105        cluster.simulateCluster();
106
107        // Simulate a failure of the master after 10 seconds
108        Thread.sleep(10000);
109        master1.isFailed = true;
110
111        // Keep the main thread alive to see the failover in action
112        Thread.sleep(20000);
113    }
114}
115

3. Gossip 协议

Gossip 协议用于节点之间交换状态信息,确保整个集群对节点状态的一致性认识。每个节点会定期向其他节点发送和接收状态信息。

代码示例

1import java.util.ArrayList;
2import java.util.List;
3import java.util.Timer;
4import java.util.TimerTask;
5
6class ClusterNode {
7    String name;
8    String ip;
9    int port;
10    boolean isMaster;
11    ClusterNode master;
12    long lastHeartbeat;
13    boolean isFailed;
14
15    ClusterNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
16        this.name = name;
17        this.ip = ip;
18        this.port = port;
19        this.isMaster = isMaster;
20        this.master = master;
21        this.lastHeartbeat = System.currentTimeMillis();
22        this.isFailed = false;
23    }
24
25    void sendHeartbeat() {
26        System.out.println("Sending heartbeat from node " + name);
27        lastHeartbeat = System.currentTimeMillis();
28    }
29
30    void receiveHeartbeat() {
31        System.out.println("Received heartbeat at node " + name);
32        lastHeartbeat = System.currentTimeMillis();
33        isFailed = false;
34    }
35
36    void checkHeartbeat() {
37        long now = System.currentTimeMillis();
38        if (now - lastHeartbeat > 3000) { // 3 seconds timeout
39            System.out.println("Node " + name + " is not responding");
40            isFailed = true;
41        }
42    }
43
44    @Override
45    public String toString() {
46        return "Node " + name + ": " + ip + ":" + port + ", Role: " + (isMaster ? "Master" : "Slave");
47    }
48}
49
50class Cluster {
51    List<ClusterNode> nodes = new ArrayList<>();
52
53    void addNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
54        nodes.add(new ClusterNode(name, ip, port, isMaster, master));
55    }
56
57    void handleFailover(ClusterNode failedNode) {
58        for (ClusterNode node : nodes) {
59            if (node.master == failedNode && !node.isFailed) {
60                System.out.println("Failover: promoting slave node " + node.name + " to master");
61                node.isMaster = true;
62                node.master = null;
63                failedNode.isMaster = false;
64                return;
65            }
66        }
67    }
68
69    void gossip() {
70        for (ClusterNode node : nodes) {
71            if (!node.isFailed) {
72                for (ClusterNode peer : nodes) {
73                    if (peer != node) {
74                        peer.receiveHeartbeat();
75                    }
76                }
77            } else {
78                handleFailover(node);
79            }
80        }
81    }
82
83    void simulateCluster() {
84        Timer timer = new Timer(true);
85        TimerTask heartbeatTask = new TimerTask() {
86            @Override
87            public void run() {
88                for (ClusterNode node : nodes) {
89                    if (!node.isFailed) {
90                        node.sendHeartbeat();
91                    }
92                }
93            }
94        };
95
96        TimerTask gossipTask = new TimerTask() {
97            @Override
98            public void run() {
99                gossip();
100            }
101        };
102
103        timer.scheduleAtFixedRate(heartbeatTask, 0, 1000);
104        timer.scheduleAtFixedRate(gossipTask, 0, 1000);
105    }
106
107    void printNodes() {
108        for (ClusterNode node : nodes) {
109            System.out.println(node);
110        }
111    }
112}
113
114

Redis(147)Redis的Cluster的容错性如何?》 是转载文章,点击查看原文


相关推荐


网站被谷歌标记“不安全”(Not Secure)怎么处理?
光算科技2025/11/24

当你的网站突然被谷歌打上“不安全”红标,访客看到登录、支付环节跳出警告弹窗时,超过63%的用户会直接关闭页面——这意味着流量流失、品牌信任度暴跌! 本文提供可直接落地的修复方案,无需专业开发也能操作,2小时内让网站回归“安全”状态! 为什么你的网站会被标记"不安全" 谷歌从2018年开始强制要求所有含用户输入(如登录、支付、表单)的页面必须部署SSL证书,否则直接标记为不安全。 更棘手的是,即便你已经安装了SSL证书,​证书过期​(比如免费证书3个月未续期)、域名不匹配


Altium Designer 6.0 初学教程-在Altium Designer 中对PCB 进行板层设置及内电层进行分割
贝塔实验室2025/11/22

更多入门教程:Altium Designer 6.0 初学教程(一)-CSDN博客 Altium Designer 6.0 初学教程-原理图和PCB 的设计-CSDN博客 Altium Designer 6.0 初学教程-在Altium Designer 中进行PCB 的CAM 输出_ad导出cam-CSDN博客 Altium Designer 6.0 初学教程-在Altium Designer 中进行混合信号功能仿真_altiumdesigner如何做信号仿真-CSDN博客 Altiu


Qt 优雅实现线程安全单例模式(模板化 + 自动清理)
喵个咪2025/11/20

Qt 优雅实现线程安全单例模式(模板化 + 自动清理) 在 Qt 开发中,单例模式是高频使用的设计模式,用于全局共享一个实例(如配置管理、网络服务、日志系统等)。一个健壮的 Qt 单例需要满足 线程安全、自动清理、通用性强、支持任意构造参数 等核心需求。本文将基于模板封装 + 管理器的设计思路,实现一套可直接复用的单例框架,并详细讲解其设计原理与最佳实践。 一、单例模式的核心诉求 在 Qt 环境中,单例的设计需要解决以下关键问题: 线程安全: 多线程并发调用时避免创建多个实例; 自动清理: 程


基于UniappX开发电销APP,实现CRM后台控制APP自动拨号
爱心发电丶2025/11/19

原文:nicen.cn/8532.html 在上一篇文章中(juejin.cn/post/757352…),已经实现了电销APP的基础功能:通时通次记录、通话录音上传。 已经能在工作中进行应用了,但是离成熟的电销APP还是差了不少,还得继续开发。 电销APP大都还有一个与之对应的CRM系统,所以另一个常见的需求,就是通过CRM后台直接控制APP拨号。 相关代码和电销APP已经开源:github.com/friend-nice… 开发思路 常规需求用常规的办法:在保证消息收发高效实时的前提下,后端


Swift 6 迁移常见 crash: _dispatch_assert_queue_fail
RickeyBoy2025/11/17

我的 Github:github.com/RickeyBoy/R… 大量 iOS 内容欢迎大家关注~ 最近在将公司项目迁移到 Swift 6 的过程中,解决了好几个相似的 crash。关键字如下 _dispatch_assert_queue_fail "%sBlock was %sexpected to execute on queue [%s (%p)] Task 208: EXC_BREAKPOINT (code=1, subcode=0x103


VSCode debugger 调试指南
清沫2025/11/16

在以前的文章 深入前端调试原理,我们主要从原理的角度来看了如何调试。本篇文章则是从实践角度出发,看看如何在 vscode 中配置和使用各种调试功能。 本文涉及到代码均在仓库 vscode-debugger-dojo,全面的 VSCode Debugger 调试示例项目,涵盖了各种常见场景的调试配置。 VSCode Debugger 原理 在 VSCode 的项目中 .vscode/launch.json 中加入如下的配置即可调试: SCode 并不是 JS 语言的专属编辑器,它可以用于多


Bash 的 base64 命令
hubenchang05152025/11/15

#Bash 的 base64 命令 base64 [OPTION]... [FILE]... 功能 进行 BASE64 编码或解码。 类型 可执行文件(/usr/bin/base64),属于 coreutils。 参数 OPTION 选项: -d, --decode - 解码;不带此选项则为编码 -i, --ignore-garbage - 解码时忽略无效字符 -w, --wrap=COLS - 编码输出时一行的字符数;默认为 76,设为 0 则不换行 --help - 显示帮助 --ve


Vue3实现拖拽排序
用户9714171814272025/11/14

Vue3 + Element Plus + SortableJS 实现表格拖拽排序功能 📋 目录 功能概述 技术栈 实现思路 代码实现 核心要点 常见问题 总结 功能概述 在管理后台系统中,表格数据的排序功能是一个常见的需求。本文介绍如何使用 Vue3、Element Plus 和 SortableJS 实现一个完整的表格拖拽排序功能,支持: ✅ 通过拖拽图标对表格行进行排序 ✅ 实时更新数据顺序 ✅ 支持数据过滤后的排序 ✅ 切换标签页时自动初始化 ✅ 优雅的动画效果 先看实现效果:


Python 的内置函数 id
IMPYLH2025/11/13

Python 内建函数列表 > Python 的内置函数 id Python 的内置函数 id() 是一个非常有用的工具函数,它返回一个对象的"身份标识",这个标识实际上是该对象在内存中的地址(以整数形式表示)。以下是关于 id() 函数的详细说明: 基本用法 x = 42 print(id(x)) # 输出一个整数,代表变量x所引用的对象的内存地址 特性说明 每个对象在内存中都有唯一的id这个id在对象的生命周期内保持不变不同对象可能有相同的id(如果前一个对象已被销毁)


FastAPI × SQLAlchemy 2.0 Async:从“能跑”到“可压测”的完整工程实践
Java私教2025/11/11

一句话总结 用 SQLAlchemy 2.0 AsyncIO 模式,把 FastAPI 的并发优势兑现成 真正的数据库吞吐;再叠上连接池、事务、迁移、测试四件套,直接上线不踩坑。 1. 为什么要“异步 ORM”? 场景同步 SQLAlchemy异步 SQLAlchemy100 个并发上传开 100 线程 → 100 个连接 → DB 被打爆单线程 20 连接即可跑满 CPU请求等待 I/O线程上下文切换 8 ms协程切换 0.3 ms代码风格

首页编辑器站点地图

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

Copyright © 2025 聚合阅读