zookeeper实现IdGenerator(原理版本)

608 阅读1分钟

zookeeper系列之【IdGenerator,简单原理】

zookeeper系列之【IdGenerator,多线程测试】

zookeeper系列之【分布式锁】

zookeeper系列之【master选举】


单进程,多线程下实现IdGenerator可以AtomicLong对象。内部使用了CAS无锁算法。宕机了,内存就没了,last Id就找不到了。

多进程或者集群环境下实现IdGenerator,要借助一个第三方进程,无论它是独立部署的还是跟应用程序搞在一块。可以用redis,数据库,Zookeeper,或者自己搞个application实现(自己实现的,数据得落地哦,要不然宕机了也就玩完)

这边介绍下Zookeeper实现方式。

原理

在ZK中找个目录(Persistent永久性的),分布式的各个客户端向这个目录下创建永久顺序节点(EphemeralSequential)

创建永久顺序节点后,把节点名字转换成Long类型即可。

/mygen
├── /0000000000
└── /0000000002
└── /0000000003
└── /0000000004

代码实现

public interface IGenerator {

	/**
	 * 生成器抽象方法
	 */
	long gen();
}
public class IdGenerator implements IGenerator {

	private ZkClient client; // 客户端持有
	private String nodePath; // 生成的顺序节点要放在哪个目录下

	public IdGenerator(ZkClient client, String basePath) {
		this.client = client;
		this.nodePath = basePath.concat("/");

		// 初始化的时候,看看基础目录有没有,没有就来一个
		if (!client.exists(basePath)) {
			client.createPersistent(basePath, true);
		}
	}

	@Override
	public long gen() {
		String fullPath = client.createPersistentSequential(nodePath, null);
		return Long.parseLong(fullPath.substring(fullPath.lastIndexOf("/") + 1));// 数字转换下
	}
}
public class TestClient {

	private static final int TOTAL_NUM = 5;

	public static void main(String[] args) throws InterruptedException {
		// 创建zookeeper会话
		ZkClient client = new ZkClient("localhost:2181,localhost:2182,localhost:2183", 5000, 5000, new SerializableSerializer());

		IGenerator generator = new IdGenerator(client, "/mygen");
		for (int i = 0; i < TOTAL_NUM; i++) {
			System.out.println(generator.gen());
		}
		client.close();// 结束会话
	}
}