Generate Distributed IDs with Zookeeper and Spring Boot
This guide shows how to use Zookeeper 3.6.2 with Spring Boot 2.2.10 to create sequential nodes, implement a distributed ID service in Java, and test concurrent ID generation across 100 threads.
Zookeeper version: 3.6.2
Since Zookeeper 3.6, watches can be recursive, unlike earlier versions where a watch was removed after a change.
Create a sequential node via command line:
create /distributed/key/ids # create a persistent node
Created /distributed/key/ids
create -s /distributed/key/ids/ # create sequential node under ids
Created /distributed/key/ids/0000000000
# Repeating the command continues the sequence even after deletion.Next, implement with Java.
Environment: Spring Boot 2.2.10.RELEASE, JDK 1.8, Zookeeper 3.6.2
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.2</version>
</dependency>
</dependencies>application.yml configuration
server:
port: 9881
---
zk:
connectString: localhost:2181,localhost:2182,localhost:2183
timeout: 3000Zookeeper connection configuration
@Configuration
public class ZKConfig {
private static Logger logger = LoggerFactory.getLogger(ZKConfig.class);
@Value("${zk.connectString}")
private String connectString;
@Value("${zk.timeout}")
private Integer timeout;
@Bean
public ZooKeeper zookeeper() {
ZooKeeper zookeeper = null;
try {
CountDownLatch cdl = new CountDownLatch(1);
logger.info("zk准备连接: {}", connectString);
zookeeper = new ZooKeeper(connectString, timeout, event -> {
if (event.getState() == Event.KeeperState.SyncConnected) {
logger.info("zk服务器连接成功");
cdl.countDown();
}
});
cdl.await();
} catch (Exception e) {
e.printStackTrace();
}
return zookeeper;
}
}Implementation
public interface DistributedIdModel {
Long getId(String key);
}
@Service
public class DistributedIdZK implements DistributedIdModel {
private static final String PATH = "/distributed/key/ids/";
@Resource
private ZooKeeper zk;
@Override
public Long getId(String key) {
try {
String res = zk.create(PATH, null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
zk.delete(res, 0);
if (res != null && res.length() > PATH.length()) {
return Long.valueOf(res.substring(PATH.length()));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}zk.create returns the full path; the node is then deleted to avoid accumulation.
Test
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringDistributedIdApplicationTests {
@Resource
private DistributedIdModel distId;
private final int COUNT = 100;
private CountDownLatch cdl = new CountDownLatch(COUNT);
private CountDownLatch state = new CountDownLatch(COUNT);
private Thread[] threads = new Thread[COUNT];
@Before
public void before() {
for (int i = 0; i < COUNT; i++) {
threads[i] = new Thread(() -> {
cdl.countDown();
System.out.println(Thread.currentThread().getName() + ", 到达");
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
Long id = distId.getId(null);
System.out.println(Thread.currentThread().getName() + ", 获取到ID = " + id);
state.countDown();
}, "线程-" + i);
}
}
@Test
public void testGetRedisId() {
for (int i = 0; i < COUNT; i++) {
threads[i].start();
}
try {
state.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}This simulates 100 concurrent threads obtaining IDs.
Done!
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
