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个虚拟机,在虚拟机里跑了下测试没有问题,没有经过正式环境的考验,有些需要在优化的,欢迎吐槽

你可能感兴趣的:(redis,zookeeper)