public class FindLeader implements Watcher { ZooKeeper zk; static String ip = "";// 本機ip ,參數傳過來的 RedisClient client; String localName = "";// 本地建立zookeeper 遞增節點後的名字 boolean isDead = false;// 用於監控redis鏈接的,若是鏈接斷掉了則退出應用 public FindLeader() throws KeeperException, IOException, InterruptedException { zk = new ZooKeeper( "192.168.93.128:2181,192.168.93.129:2181,192.168.93.130:2181", 3000, this); client = RedisClient.getInstance(ip.split(":")[0], 6379); } /** * @param args */ public static void main(String[] args) { try { ip = args[0].toString(); FindLeader find = new FindLeader(); find.run(); } catch (KeeperException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } public void process(WatchedEvent event) { System.out.println("已經觸發了" + event.getType() + "事件!" + " " + ip); findLeader(); } private void following(String leader) { try { List<String> list = zk.getChildren("/group", false); String[] nodes = list.toArray(new String[list.size()]); Arrays.sort(nodes); String first = nodes[0]; String masterIp = new String(zk.getData("/group/" + nodes[0], false, null)); String watchIp = ""; // 查找比本身小的follower // 而且監控他是否存在,由於選舉master是根據最小的選舉,這樣,若是比本身小的掛掉了,那就是本身當master了 if (nodes.length == 1) { watchIp = first; } else { for (int i = 0; i < nodes.length; i++) { if (("/group/" + nodes[i]).equals(localName) && i != 0) { watchIp = nodes[i - 1]; } } } if (!watchIp.equals("")) { zk.exists("/group/" + watchIp, true); } if (masterIp.equals(ip)) { client.slaveOfNo(); } for (int i = 1; i < nodes.length; i++) { RedisClient c = RedisClient.getInstance(new String(zk.getData("/group/" + nodes[i], false, null)).split(":")[0], 6379); c.setSlaveOf(masterIp.split(":")[0], 6379); } System.err.println("leader is :" + first); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (RedisOperationException e) { e.printStackTrace(); } } private void findLeader() { try { System.err.println("執行查找master任務"); byte[] localhost = ip.getBytes(); if (localName.equals("")) { localName = zk.create("/group/member_", localhost,ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL); } following(localName); } catch (Exception e) { e.printStackTrace(); } } private void run() { while (!isDead) { try { if (!client.ping().equals("PONG")) { isDead = true; System.exit(2); } Thread.sleep(5000); } catch (RedisOperationException e) { e.printStackTrace(); isDead = true; System.exit(2); } catch (InterruptedException e) { e.printStackTrace(); } } } }
這兩天學習了下zookeeper,順便練習了下,用zookeeper實現了一個redis的主從,只是建了3個虛擬機,在虛擬機裏跑了下測試沒有問題,沒有通過正式環境的考驗,有些須要在優化的,歡迎吐槽java