概述
在电商等高并发系统中,我们经常遇到在短时间内产生大量数据,比如抢购时,短时间下单数据激增;直播场景中,短时间产生大量聊天数据;以及伴随着这些请求的日志数据、操作的日志数据都是非常大...
在单体服务环境下,可以利用数据库的主键自增功能可以为数据提供唯一标识ID,但在分布式或者微服务环境下,在短时间内多个节点如何为数据生成唯一的ID?就需要分布式的ID生成系统。
分布式ID生成系统的特征
- 全局唯一:不能出现重复ID
- 高可用:ID生成系统是基础系统,被许多关键系统调用,一旦宕机,就会造成严重影响
所以要满足以上的特征,需要对分布式ID生成的机制有所要求
- 实现机制的可靠性
- 实现复杂度
有些算法可以实现ID的唯一性和可读性,但是实现起来十分复杂,后续也难以改造 - 可扩展性
- ID的可读性
有些ID只是为了唯一性,如UUID机制,它是不可读的,没有业务含义。不过,生成一个可读的带有业务含义的ID,将有助于业务人员和开发人员定位业务和问题所在 - 性能
分布式系统往往也需要面对高并发的情况,所以对实现的算法性能要求高
常见的分布式ID生成方案
- Java的UUID
这种方式比较简单,本地生成速度快,代码如下
String id = UUID.randomUUID().toString();
但是,使用UUID作为主键,存储会占据较大的空间,网络传输内容也多,不利于优化;存入数据库后,这么长的字符串作为主键,影响查询性能。
- 独立的数据库,通过数据库自增长专门来生成ID
- 数据库集群,设定好步长来生成ID
- Redis生成ID
- Twitter的SnowFlake算法
- 美团 Leaf
- 滴滴 Tinyid
- MongoDb的ObjectId
- ZooKeeper生成ID
本文介绍的是ZooKeeper生成ID,以上的其他方式可以另开一篇详细介绍。
ZooKeeper分布式ID生成,原理是利用ZooKeeper的顺序节点,生成全局唯一的ID
ZooKeeper分布式ID生成实现
接上一篇SpringBoot整合zookeeper、curator,实现分布式锁功能,把项目源码进行扩展
- ZookeeperClient类中增加makeId方法,用来生成ID
/**
* 分布式ID生成
* */
public String makeId(String nodeName) {
String str = createSeqNode(nodeName);
if (null == str) {
return null;
}
int index = str.lastIndexOf(nodeName);
if (index >= 0) {
index += nodeName.length();
return index <= str.length() ? str.substring(index) : "";
}
return str;
}
/**
* 创建顺序节点
* */
private String createSeqNode(String pathPrefix) {
try {
// 创建一个 ZNode 顺序节点
String s = client.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
//避免zookeeper的顺序节点暴增,需要删除创建的持久化顺序节点
// .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
.forPath(pathPrefix);
return s;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
- 在测试目录org.zhangsan.zookeeper包中,创建ZkIdMakerTest.java
package org.zhangsan.zookeeper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.zhangsan.beans.ZookeeperClient;
/**
* @ClassName ZkIdMakerTest
* @Description //分布式ID生成测试
* @Author singleZhang
* @Email 405780096@qq.com
* @Date 2020/12/8 0008 下午 5:18
**/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ZkIdMakerTest {
@Autowired
private ZookeeperClient zookeeperClient;
@Test
public void zookeeperIdMakerTest(){
String nodeName = "/test/zkIdMaker/ID-";
for (int i = 0; i < 10; i++) {
String id = zookeeperClient.makeId(nodeName);
System.out.println("第" + i + "个创建的id为:" + id);
}
}
}
3.运行zookeeper服务,运行程序,测试分布式ID生成,结果如下:
分布式ID
网友评论