zookeeper系列之【IdGenerator,简单原理】
zookeeper系列之【IdGenerator,多线程测试】
单进程,多线程下实现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();// 结束会话
}
}