返回

Elasticsearch集群建立源码剖析:揭秘分布式搜索引擎的底层奥秘

后端

Elasticsearch 集群建立:揭秘源码背后的智慧

Gossip 协议:集群邻居发现

想象一下一个 Elasticsearch 集群,就像一个分布式社区。为了让每个节点都知道其他邻居,它们使用 Gossip 协议。它就像一场接力的信息游戏,每个节点随机地向另一个节点发送信息。这些信息包含有关每个节点本身以及它所知道的其他节点的信息。通过这种方式,信息像涟漪一样在网络中传播,最终,每个节点都会了解集群中的所有邻居。

// Gossip 协议实现示例
private void sendGossip() {
    if (!discovery.nodeExists(transportService.getLocalNode())) {
        transportService.getLocalNode().version();  // 准备版本信息
    }
    // 随机选择一个节点并发送 Gossip 消息
    transportService.randomNodes().stream()
        .filter(node -> !node.equals(transportService.getLocalNode()))
        .findFirst()
        .ifPresent(targetNode -> {
            PlainNode localNode = transportService.getLocalNode();
            transportService.sendRequest(targetNode, NODE_INFO_REQUEST_ACTION_NAME,
                new NodeInfoRequest(localNode.getId(), localNode.getVersion()),
                transportOptions(),
                new AsyncListenableActionNotifier<NodeInfoResponse>() {
                    @Override
                    protected void onResponse(NodeInfoResponse response) {
                        processGossipResponse(response);
                    }
                });
        });
}

选举算法:Bully 的领导

当邻居们熟悉了,是时候选举一位领导了。Elasticsearch 使用 Bully 算法来决定谁将成为集群的 Master 节点。它就像一场竞赛,每个节点都会宣布自己的“实力”——一个数字,通常是其节点 ID。最高“实力”的节点将成为 Master。如果有多个节点具有相同的“实力”,它们将重复这一过程,直到产生赢家。

// Bully 算法实现示例
private void electMaster() {
    try {
        final LocalNode masterNode = discoveryService.getClusterManagerNode();
        // 如果当前节点的节点 ID 大于 Master 节点的节点 ID
        if (localNode.getId().compareTo(masterNode.getId()) > 0) {
            logger.info("Node {} challenges current master node {}.", localNode.getId(),
                masterNode.getId());
            // 向 Master 节点发送强制新选的通知
            transportService.sendRequest(masterNode, FORCE_NEW_CLUSTER_HEAD_ACTION_NAME,
                new ForceNewClusterHeadRequest(),
                transportOptions(),
                new AsyncListenableActionNotifier<NewClusterHeadResponse>() {
                    @Override
                    protected void onResponse(NewClusterHeadResponse response) {
                        if (!response.isAcknowledged()) {
                            logger.info("Failed to force cluster head. Response {}.", response);
                        } else {
                            logger.info("Cluster head forced successfully");
                            masterNode.stop();
                            startMaster();
                        }
                    }
                });
        }
    } catch (NodeDoesNotExistException e) {
        // 如果 Master 节点不存在,当前节点成为新 Master
        logger.info("Master {} does not exist, electing self as master",
            discoveryService.getClusterManagerNode());
        startMaster();
    }
}

节点加入:欢迎新成员

随着集群的成长,新的节点需要加入。当一个新节点出现时,它会向 Master 节点发送一个加入请求。Master 节点将检查新节点的信息,并向其发送有关集群的其他节点的信息。新节点将使用这些信息连接到集群,并成为其中一员。

// 节点加入实现示例
private void addJoiningNode(JoiningNode joiningNode) {
    // 处理加入请求并发送集群状态
    logger.info("Received joining node request from node: [{}]", joiningNode.getNode());
    transportService.sendRequest(joiningNode.getNode(), JOIN_ACTION_NAME,
        new JoinRequest(joiningNode.discoveryNode(), joiningNode.getFinalClusterState()),
        transportOptions(),
        new AsyncListenableActionNotifier<JoinResponse>() {
            @Override
            protected void onResponse(JoinResponse response) {
                // 处理加入响应并更新集群状态
                logger.info("Received joining node response from node: [{}]", joiningNode.getNode());
                discoveryService.handleJoinResponse(joiningNode, response);
            }
        });
}

健康监测:集群的脉搏

Elasticsearch 不断监测集群中的节点健康状况。如果一个节点出现故障,Master 节点会从集群中将其删除。Master 节点会定期发送心跳信号,以确保所有节点都是健康的。如果 Master 节点检测到一个节点没有发送心跳信号,它会标记该节点为不可用,并从集群中将其删除。

// 健康监测实现示例
private void pingNode() {
    if (localNode.isClusterManagerEligible()) {
        try {
            // 发送心跳信号
            discoveryService.pingNodes();
        } catch (Exception e) {
            logger.warn("Failed to ping cluster manager nodes.", e);
        }
    }
}

结论

Elasticsearch 集群建立是一个复杂的过程,涉及多个组件的协作。通过 Gossip 协议、选举算法、节点加入和健康监测,Elasticsearch 能够建立一个高度可用、可扩展且弹性的集群,为企业提供强大的搜索和分析解决方案。

常见问题解答

1. 为什么 Elasticsearch 使用 Gossip 协议?
Gossip 协议允许节点在不依赖中心权威的情况下发现彼此,提高了系统的可靠性和可用性。

2. Bully 算法如何处理选举冲突?
如果有多个节点具有相同的“实力”,Bully 算法将重复选举过程,直到产生一个赢家。

3. 新节点如何加入 Elasticsearch 集群?
新节点向 Master 节点发送加入请求,Master 节点检查新节点的信息并提供有关集群其他节点的信息。

4. Elasticsearch 如何确保集群的健康?
Master 节点不断发送心跳信号,如果一个节点没有发送心跳信号,Master 节点会将其标记为不可用并将其从集群中删除。

5. Elasticsearch 集群建立过程中最关键的步骤是什么?
选举一个 Master 节点是集群建立过程中最关键的步骤,因为它协调集群中的活动和管理数据分片。