redis用zookeeper實現自動主從同步,切換

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

相關文章
相關標籤/搜索