zookeeper生成全局唯一id
目录
依赖
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.12</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.8.0</version>
</dependency>
原理
实现方式有两种,一种通过节点,一种通过节点的版本号
- 节点的特性
持久顺序节点(PERSISTENT_SEQUENTIAL)
他的基本特性和持久节点是一致的,额外的特性表现在顺序性上。在ZooKeeper中,每个父节点都会为他的第一级子节点维护一份顺序,用于记录下每个子节点创建的先后顺序。基于这个顺序特性,在创建子节点的时候,可以设置这个标记,那么在创建节点过程中,ZooKeeper会自动为给定节点加上一个数字后缀,作为一个新的、完整的节点名。另外需要注意的是,这个数字后缀的上限是整型的最大值。 - 版本-保证分布式数据原子性操作
ZooKeeper中为数据节点引入了版本的概念,每个数据节点都具有三种类型的版本信息,对数据节点的任何更新操作都会引起版本号的变化。
代码实现
第一种根据节点方式:
创建持久顺序节点,只要不把节点删除,那么就不会重复;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 类描述:Curator实现的分布式锁
* 创建人:simonsfan
*/
public class DistributedLock {
private static CuratorFramework curatorFramework;
private static InterProcessMutex interProcessMutex;
private static final String connectString = "localhost:2181";
private static final String root = "/root";
private static ExecutorService executorService;
private String lockName;
public String getLockName() {
return lockName;
}
public void setLockName(String lockName) {
this.lockName = lockName;
}
static {
curatorFramework = CuratorFrameworkFactory.builder().connectString(connectString).connectionTimeoutMs(5000).sessionTimeoutMs(5000).retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
executorService = Executors.newCachedThreadPool();
curatorFramework.start();
}
public DistributedLock(String lockName) {
this.lockName = lockName;
interProcessMutex = new InterProcessMutex(curatorFramework, root.concat(lockName));
}
/*上锁*/
public boolean tryLock() {
int count = 0;
try {
while (!interProcessMutex.acquire(100, TimeUnit.SECONDS)) {
count++;
if (count > 3) {
TimeUnit.SECONDS.sleep(1);
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
/*释放*/
public void releaseLock() {
try {
if (interProcessMutex != null) {
interProcessMutex.release();
}
curatorFramework.delete().inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
}
}, executorService).forPath(root.concat(lockName));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
DistributedIdGeneraterService distributedIdGeneraterService = new DistributedIdGeneraterService();
String s = distributedIdGeneraterService.generateId();
System.out.println(s);
}
// ZkIdGenerator zkIdGenerator = new ZkIdGenerator("localhost:2181", "/id-gen");
// System.out.println( zkIdGenerator.next());
// for (int i = 0; i < 1000; i++) {
// }
}
}
生成的节点:
第一种根据节点版本方式:
只要修改了节点,版本号就会加一.
代码:
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
/**
* 使用zk生成分布式唯一id,自增有序
*
* @author CC11001100
*/
public class ZkIdGenerator {
private ZooKeeper zk;
private String path;
public ZkIdGenerator(String serverAddress, String path) {
try {
this.path = path;
zk = new ZooKeeper(serverAddress, 3000, event -> {
System.out.println(event.toString());
});
if (zk.exists(path, false) == null) {
zk.create(path, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
} catch (IOException | InterruptedException | KeeperException e) {
e.printStackTrace();
}
}
public long next() {
try {
Stat stat = zk.setData(path, new byte[0], -1);
return stat.getVersion();
} catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
return -1;
}
public static void main(String[] args) {
// for (int i = 0; i < 1000; i++) {
// DistributedIdGeneraterService distributedIdGeneraterService = new DistributedIdGeneraterService();
// String s = distributedIdGeneraterService.generateId();
// System.out.println(s);
// }
ZkIdGenerator zkIdGenerator = new ZkIdGenerator("localhost:2181", "/id-gen");
for (int i = 0; i < 1000; i++) {
System.out.println(zkIdGenerator.next());
}
}
}
版本生成的:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。