java id 生成器_[Java]IdWorker ID生成器

package cn.studyjava.util;

/**

* @author zsljava@163.com

* JavaScript整数最大支持53位

* 时间41位 机器号1位 毫秒ID自增6位 一共48位

*/

public class IdWorker {

/**

* 2016-01-01 00:00:00

*/

private final static long twepoch = 1451577600000L;

/**

* 机器标识位数

*/

private final static long workerIdBits = 1L;

/**

* 机器ID支持机器节点数0~1

*/

public final static long maxWorkerId = ~(-1L << workerIdBits);

/**

* 毫秒内自增位

*/

private final static long sequenceBits = 6L;

/**

* 毫秒内sequence范围0~63

*/

public final static long sequenceMask = ~(-1L << sequenceBits);

/**

* 机器ID偏左移6位

*/

private final static long workerIdShift = sequenceBits;

/**

* 时间毫秒左移7位

*/

private final static long timestampLeftShift = sequenceBits + workerIdBits;

private final long workerId;

private long sequence = 0L;

private long lastTimestamp = -1L;

public IdWorker(final long workerId) {

if (workerId > maxWorkerId || workerId < 0) {

throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));

}

this.workerId = workerId;

}

public synchronized long nextId() {

long timestamp = this.timeGen();

if (timestamp < this.lastTimestamp) {

throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", this.lastTimestamp - timestamp));

}

if (this.lastTimestamp == timestamp) {

this.sequence = (this.sequence + 1) & sequenceMask;

if (this.sequence == 0) {

timestamp = this.tilNextMillis(this.lastTimestamp);

}

}

else {

this.sequence = 0;

}

this.lastTimestamp = timestamp;

return ((timestamp - twepoch << timestampLeftShift)) | (this.workerId << workerIdShift) | (this.sequence);

}

private long tilNextMillis(final long lastTimestamp) {

long timestamp = this.timeGen();

while (timestamp <= lastTimestamp) {

timestamp = this.timeGen();

}

return timestamp;

}

private long timeGen() {

return System.currentTimeMillis();

}

}

注意:本文归作者所有,未经作者允许,不得转载

### Java 中生成唯一交易编号的方法 在Java应用程序中,为了确保事务ID的唯一性和高效性,可以采用多种方法来实现序列号生成器。以下是几种常见的方案: #### 使用UUID作为唯一标识符 UUID (Universally Unique Identifier) 是一种标准格式,用于生成几乎不可能重复的大数值字符串。 ```java import java.util.UUID; public class TransactionIdGenerator { public static String generateTransactionId() { return UUID.randomUUID().toString(); } } ``` 这种方法简单易用,但在某些情况下可能不适合业务需求,因为它产生的是一串随机字符而不是连续整数[^1]。 #### 基于时间戳和计数器组合的方式 通过结合当前的时间戳与一个自增计数器,可以在一定程度上保证全局唯一性的同时保持较好的可读性。 ```java class TimeBasedSequenceNumberGenerator { private final AtomicLong counter = new AtomicLong(0L); public synchronized String getNextId() { long timestamp = System.currentTimeMillis(); int countValue = Math.toIntExact(counter.getAndIncrement()); // Reset counter every day to avoid overflow. if ((System.currentTimeMillis() / 86400000) != (timestamp / 86400000)) { counter.set(0L); } return String.format("%d-%06d", timestamp, countValue); } } ``` 这种方式能够提供较为紧凑且有序的结果,适用于大多数分布式环境下的应用系统[^2]。 #### 利用数据库中的SEQUENCE对象 对于那些已经依赖关系型数据库的应用程序来说,利用内置的支持也是不错的选择之一。例如,在MySQL中可以通过`AUTO_INCREMENT`字段来自动生成唯一的主键值;而在PostgreSQL或其他支持SQL:2003 SEQUENCE定义的语言里,则可以直接调用相应的函数获取下一个可用序号。 需要注意的是,虽然这种方法易于实施并能很好地与其他持久化层组件集成在一起工作,但它通常不具备跨多个实例部署的能力,并且在网络分区的情况下可能会遇到同步方面的问题[^3]。 #### 分布式ID生成算法-Snowflake Algorithm Twitter开源了一个叫做SnowFlake的服务端库,它可以用来快速有效地生产全球唯一的long类型的id。其设计原理是将机器位、数据中心位、毫秒级时间戳以及序列号编码到一起形成最终返回给客户端的一个64bit长度的数据结构。 ```java // Snowflake ID Generator implementation example using Twitter's snowflake algorithm. final class IdWorker { private final long workerId; private final long datacenterId; private final long sequence = 0L; /** * Constructor for IdWorker which takes both Worker ID and Data Center ID as parameters. */ public IdWorker(long workerId, long dataCenterId){ this.workerId=workerId; this.datacenterId=dataCenterId; } protected synchronized long nextId(){ // Implementation details omitted... return id; } } // Usage Example: IdWorker idWorker=new IdWorker(1,1); for(int i=0;i<10;i++){ System.out.println(idWorker.nextId()); } ``` 这种解决方案非常适合大规模微服务架构下需要频繁创建大量记录的情形,既不会造成冲突又具备良好的扩展特性[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值