赞
踩
分布式唯一ID指在分布式系统中用于标识和区分各个实体、资源或事件的唯一标识符。由于分布式系统可能包含多个节点和多个并发操作,需要确保在整个系统中每个实体都具有唯一的标识,避免冲突和重复的情况。
分布式系统唯一ID的设计通常需要满足以下要求:
使用ZooKeeper实现生成分布式ID可以保证分布式系统中每个节点生成的ID是唯一且递增的。以下是使用ZooKeeper实现生成分布式ID的基本步骤:
问题来了,我们要明确创建一个什么样的ZooKeeper节点呢?首先,要知道ID是用来标识一个实体的,而不是作用于整个系统。比如一个系统中,实体有用户、商品、订单等,但是我们并不需要保证用户、商品和订单之间的ID是唯一的,而是要保证同一类实体比如用户这一个类,即任意两个用户A和B的ID不能重复。所以我们可以把系统中用于产生分布式ID的Znode的粒度控制在实体维度,例如/app/user
节点是用户实体的分布式ID节点,/app/product
节点是商品实体的分布式ID节点等。
/**
* 分布式ID节点缓存
*/
private Map<String,String> NodePathMap = new HashMap<>();
/**
* 生成分布式ID节点路径
* @param module 模块名称
* @return
*/
public String getIdNodePath(String module){
if (module == null || module.isBlank()){
throw new NullPointerException("请设置模块名称");
}
if (NodePathMap.get(module) == null){
if (appName == null || appName.isBlank()){
throw new NullPointerException("请设置系统名称");
}
synchronized (IdGenerator.class){
if (NodePathMap.get(module) == null){
NodePathMap.put(module,"/"+appName+"/"+module);
}
}
}
return NodePathMap.get(module);
}
先通过上一节中的临时顺序节点的路径,向ZooKeeper集群发起一个创建节点的请求并返回节点的名称,最后去除节点路径的前缀,获取最后的序列号。
/**
* 分布式ID节点的前缀
*/
public static final String ID_PREFIX = "id_";
/**
* 创建临时节点,并返回Id
* @param module
* @return
*/
public String createNodeId(String module){
String idNodePath = getIdNodePath(module);
try {
String idPrefix = idNodePath + "/" + ID_PREFIX;
String id = client.create() // 创建节点
.creatingParentsIfNeeded() // 如果需要,递归创建节点
.withMode(CreateMode.EPHEMERAL_SEQUENTIAL) // 指定创建节点类型,使用临时顺序节点
.forPath(idPrefix); // 设置节点路径
// 去除nodeId的前缀
return id.replace(idPrefix,"");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
在ZK生成的临时顺序节点ID的前附加时日期时间,以便直观显示此ID的生成日期。
/**
* 日期格式
*/
public static final String DATE_FORMAT = "yyyyMMdd";
/**
* 获取当天的日期
* 格式:yyyyMMdd
* @return
*/
public String datePrefix(){
DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern(DATE_FORMAT);
LocalDateTime now = LocalDateTime.now();
return now.format(yyyyMMdd);
}
/**
* 生成id
* @param module 模块
* @return
*/
public String nextId(String module){
// id前缀以日期开头
return datePrefix()+createNodeId(module);
}
一切从简,直接把测试方法写在启动类中
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。