首页 > 数据库 >Redis Cluster容错性实现详解

Redis Cluster容错性实现详解

来源:互联网 2026-07-07 09:07:20

Redis Cluster 的高容错性是怎么做到的?说白了,就是主从复制、自动故障转移和 Gossip 协议这三板斧。它们配合起来,确保集群里某个节点出问题也不会让整个服务挂掉。下面拆开来讲,顺便用 Ja va 代码演示一下实现逻辑。 1. 主从复制(Master-Sla ve Replicatio

Redis Cluster 的高容错性是怎么做到的?说白了,就是主从复制、自动故障转移和 Gossip 协议这三板斧。它们配合起来,确保集群里某个节点出问题也不会让整个服务挂掉。下面拆开来讲,顺便用 Ja va 代码演示一下实现逻辑。

Redis Cluster容错性实现详解

长期稳定更新的攒劲资源: >>>点此立即查看<<<

1. 主从复制(Master-Sla ve Replication)

这是最基础的高可用保障。每个主节点可以挂一到多个从节点,数据实时同步过去。一旦主节点挂了,从节点就能顶上,顶多丢一小部分还没来得及同步的数据。从代码角度看,就是定义节点角色和关联关系。

代码示例

import ja va.util.ArrayList;
import ja va.util.List;

class ClusterNode {
    String name;
    String ip;
    int port;
    boolean isMaster;
    ClusterNode master;

    ClusterNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
        this.name = name;
        this.ip = ip;
        this.port = port;
        this.isMaster = isMaster;
        this.master = master;
    }

    @Override
    public String toString() {
        return "Node " + name + ": " + ip + ":" + port + ", Role: " + (isMaster  "Master" : "Sla ve");
    }
}

class Cluster {
    List nodes = new ArrayList<>();

    void addNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
        nodes.add(new ClusterNode(name, ip, port, isMaster, master));
    }

    void printNodes() {
        for (ClusterNode node : nodes) {
            System.out.println(node);
        }
    }
}

public class RedisClusterDemo {
    public static void main(String[] args) {
        Cluster cluster = new Cluster();
        ClusterNode master1 = new ClusterNode("master1", "192.168.1.1", 6379, true, null);
        cluster.addNode(master1.name, master1.ip, master1.port, master1.isMaster, master1.master);
        cluster.addNode("sla ve1", "192.168.1.2", 6379, false, master1);
        cluster.printNodes();
    }
}

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

主节点挂了,从节点不能傻等着,得自动升主。这个过程中,其他节点需要协同工作,保证数据完整性不出乱子。下面的代码模拟了心跳检测和故障转移的简单逻辑:超过3秒没收到主节点心跳,就认定它挂了,然后找一个从节点转正。

代码示例

import ja va.util.ArrayList;
import ja va.util.List;
import ja va.util.Timer;
import ja va.util.TimerTask;

class ClusterNode {
    String name;
    String ip;
    int port;
    boolean isMaster;
    ClusterNode master;
    long lastHeartbeat;
    boolean isFailed;

    ClusterNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
        this.name = name;
        this.ip = ip;
        this.port = port;
        this.isMaster = isMaster;
        this.master = master;
        this.lastHeartbeat = System.currentTimeMillis();
        this.isFailed = false;
    }

    void sendHeartbeat() {
        System.out.println("Sending heartbeat to node " + name);
        lastHeartbeat = System.currentTimeMillis();
    }

    void checkHeartbeat() {
        long now = System.currentTimeMillis();
        if (now - lastHeartbeat > 3000) {
            System.out.println("Node " + name + " is not responding");
            isFailed = true;
        }
    }

    @Override
    public String toString() {
        return "Node " + name + ": " + ip + ":" + port + ", Role: " + (isMaster  "Master" : "Sla ve");
    }
}

class Cluster {
    List nodes = new ArrayList<>();

    void addNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
        nodes.add(new ClusterNode(name, ip, port, isMaster, master));
    }

    void handleFailover() {
        for (ClusterNode node : nodes) {
            if (node.isMaster && node.isFailed) {
                for (ClusterNode sla ve : nodes) {
                    if (sla ve.master == node) {
                        System.out.println("Failover: promoting sla ve node " + sla ve.name + " to master");
                        sla ve.isMaster = true;
                        sla ve.master = null;
                        node.isMaster = false;
                        return;
                    }
                }
            }
        }
    }

    void simulateCluster() {
        Timer timer = new Timer(true);
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                for (ClusterNode node : nodes) {
                    if (node.isMaster && !node.isFailed) {
                        node.sendHeartbeat();
                    } else {
                        node.checkHeartbeat();
                        if (node.isFailed && node.isMaster) {
                            handleFailover();
                        }
                    }
                }
            }
        };
        timer.scheduleAtFixedRate(task, 0, 1000);
    }

    void printNodes() {
        for (ClusterNode node : nodes) {
            System.out.println(node);
        }
    }
}

public class RedisClusterDemo {
    public static void main(String[] args) throws InterruptedException {
        Cluster cluster = new Cluster();
        ClusterNode master1 = new ClusterNode("master1", "192.168.1.1", 6379, true, null);
        cluster.addNode(master1.name, master1.ip, master1.port, master1.isMaster, master1.master);
        cluster.addNode("sla ve1", "192.168.1.2", 6379, false, master1);
        cluster.addNode("sla ve2", "192.168.1.3", 6379, false, master1);
        cluster.printNodes();
        cluster.simulateCluster();

        Thread.sleep(10000);
        master1.isFailed = true;

        Thread.sleep(20000);
    }
}

3. Gossip 协议

光有主从和自动切换还不够——整个集群必须对节点状态达成共识。Gossip 协议就是干这个的:每个节点定期给其他节点广播心跳信息,互相知道谁还活着。如果某个节点被多数节点报告不可达,那它就会被标记为失败,触发故障转移。下面的代码模拟了 gossip 交互:节点之间互相发送和接收心跳,同时检测超时,一旦发现主节点挂了就自动切换。

代码示例

import ja va.util.ArrayList;
import ja va.util.List;
import ja va.util.Timer;
import ja va.util.TimerTask;

class ClusterNode {
    String name;
    String ip;
    int port;
    boolean isMaster;
    ClusterNode master;
    long lastHeartbeat;
    boolean isFailed;

    ClusterNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
        this.name = name;
        this.ip = ip;
        this.port = port;
        this.isMaster = isMaster;
        this.master = master;
        this.lastHeartbeat = System.currentTimeMillis();
        this.isFailed = false;
    }

    void sendHeartbeat() {
        System.out.println("Sending heartbeat from node " + name);
        lastHeartbeat = System.currentTimeMillis();
    }

    void receiveHeartbeat() {
        System.out.println("Received heartbeat at node " + name);
        lastHeartbeat = System.currentTimeMillis();
        isFailed = false;
    }

    void checkHeartbeat() {
        long now = System.currentTimeMillis();
        if (now - lastHeartbeat > 3000) {
            System.out.println("Node " + name + " is not responding");
            isFailed = true;
        }
    }

    @Override
    public String toString() {
        return "Node " + name + ": " + ip + ":" + port + ", Role: " + (isMaster  "Master" : "Sla ve");
    }
}

class Cluster {
    List nodes = new ArrayList<>();

    void addNode(String name, String ip, int port, boolean isMaster, ClusterNode master) {
        nodes.add(new ClusterNode(name, ip, port, isMaster, master));
    }

    void handleFailover(ClusterNode failedNode) {
        for (ClusterNode node : nodes) {
            if (node.master == failedNode && !node.isFailed) {
                System.out.println("Failover: promoting sla ve node " + node.name + " to master");
                node.isMaster = true;
                node.master = null;
                failedNode.isMaster = false;
                return;
            }
        }
    }

    void gossip() {
        for (ClusterNode node : nodes) {
            if (!node.isFailed) {
                for (ClusterNode peer : nodes) {
                    if (peer != node) {
                        peer.receiveHeartbeat();
                    }
                }
            } else {
                handleFailover(node);
            }
        }
    }

    void simulateCluster() {
        Timer timer = new Timer(true);
        TimerTask heartbeatTask = new TimerTask() {
            @Override
            public void run() {
                for (ClusterNode node : nodes) {
                    if (!node.isFailed) {
                        node.sendHeartbeat();
                    }
                }
            }
        };
        TimerTask gossipTask = new TimerTask() {
            @Override
            public void run() {
                gossip();
            }
        };
        timer.scheduleAtFixedRate(heartbeatTask, 0, 1000);
        timer.scheduleAtFixedRate(gossipTask, 0, 1000);
    }

    void printNodes() {
        for (ClusterNode node : nodes) {
            System.out.println(node);
        }
    }
}

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备2026025700号-3 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。