1. 程式人生 > >zookeeper使用curator進行選主(Leader)

zookeeper使用curator進行選主(Leader)

delet ram href try eat 處理方式 連接 監聽 prev

在分布式系統設計中,選主是一個常見的場景。選主是一個這樣的過程,通過選主,主節點被選擇出來控制其他節點或者是分配任務。

選主算法要滿足的幾個特征:

1)各個節點均衡的獲得成為主節點的權利,一旦主節點被選出,其他的節點可以感知到誰是主節點,被服從分配。

2)主節點是唯一存在的

3)一旦主節點失效,宕機或者斷開連接,其他的節點能夠感知,並且重新進行選主算法。

zookeeper實現了安全可靠的選主機制。

作為zookeeper的高級api封裝庫curator選主算法主要有以下兩個:Leader Latch和Leader Election

1、Leader Latch

實例被選為leader後,執行isLeader中的邏輯。當領導權易主之後才會再次執行isLeader。

直接看代碼吧,註釋裏面已經有說明了。

/*
    *  Leader Latch(群首閂)
    *  isLeader 中的方法會在實例被選為主節點後被執行, 而notLeader中的不會被執行
    *  如果主節點被失效, 會進行重新選主
    * */
    public void setLeaderLatch(String path) {
        try {
            String id = "client#" + InetAddress.getLocalHost().getHostAddress();
            leaderLatch 
= new LeaderLatch(client, path, id); LeaderLatchListener leaderLatchListener = new LeaderLatchListener() { @Override public void isLeader() { logger.info("[LeaderLatch]我是主節點, id={}", leaderLatch.getId()); } @Override
public void notLeader() { logger.info("[LeaderLatch]我不是主節點, id={}", leaderLatch.getId()); } }; leaderLatch.addListener(leaderLatchListener); leaderLatch.start(); } catch (Exception e) { logger.error("c創建LeaderLatch失敗, path={}", path); } } /* * 判斷實例是否是主節點 * */ public boolean hasLeadershipByLeaderLatch() { return leaderLatch.hasLeadership(); } /* * 阻塞直到獲得領導權 * */ public void awaitByLeaderLatch() { try { leaderLatch.await(); } catch (InterruptedException | EOFException e) { e.printStackTrace(); } } /* * 嘗試獲得領導權並超時 * */ public boolean awaitByLeaderLatch(long timeout, TimeUnit unit) { boolean hasLeadership = false; try { hasLeadership = leaderLatch.await(timeout, unit); } catch (InterruptedException e) { e.printStackTrace(); } return hasLeadership; }

2、Leader Election

當實例被選為leader之後,調用takeLeadership方法進行業務邏輯處理,處理完成即釋放領導權。

其中autoRequeue()方法的調用確保此實例在釋放領導權後還可能獲得領導權。

/*
    *   Leader Election模式
    *   實例被選主後執行takeLeadership, 執行完之後立刻釋放領導權, 再次選主, 所以這裏sleep 10秒
    * */
    public void setLeaderSelector(String path) {
        try {
            final String id = "client#" + InetAddress.getLocalHost().getHostAddress();
            LeaderSelectorListener leaderSelectorListener = new LeaderSelectorListener() {
                @Override
                public void takeLeadership(CuratorFramework client) throws Exception {
                    logger.info("[LeaderSelector]我是主節點, id={}", id);
                    Thread.sleep(10000);
                }

                @Override
                public void stateChanged(CuratorFramework client, ConnectionState newState) {

                }
            };
            leaderSelector = new LeaderSelector(client, path, leaderSelectorListener);
            leaderSelector.autoRequeue();
            leaderSelector.start();
        } catch (Exception e) {
            logger.error("c創建LeaderLatch失敗, path={}", path);
        }
    }

LeaderLatch instances add a ConnectionStateListener to watch for connection problems. If SUSPENDED or LOST is reported, the LeaderLatch that is the leader will report that it is no longer the leader (i.e. there will not be a leader until the connection is re-established). If a LOST connection is RECONNECTED, the LeaderLatch will delete its previous ZNode and create a new one.

Users of LeaderLatch must take account that connection issues can cause leadership to be lost. i.e. hasLeadership() returns true but some time later the connection is SUSPENDED or LOST. At that point hasLeadership() will return false. It is highly recommended that LeaderLatch users register a ConnectionStateListener.

LeaderSelectorListener類繼承了ConnectionStateListener。一旦LeaderSelector啟動,它會向curator客戶端添加監聽器。 使用LeaderSelector必須時刻註意連接的變化。一旦出現連接問題如SUSPENDED,curator實例必須確保它可能不再是leader,直至它重新收到RECONNECTED。如果LOST出現,curator實例不再是leader並且其takeLeadership()應該直接退出。

推薦的做法是,如果發生SUSPENDED或者LOST連接問題,最好直接拋CancelLeadershipException,此時,leaderSelector實例會嘗試中斷並且取消正在執行takeLeadership()方法的線程。 建議擴展LeaderSelectorListenerAdapter, LeaderSelectorListenerAdapter中已經提供了推薦的處理方式 。

zookeeper使用curator進行選主(Leader)