当前位置: 首页 > news >正文

分布式ID生成SnowflakeId雪花算法和百度UidGenerator工具类

1:SnowflakeId雪花算法

public class SnowflakeIdUtils {@Getterprivate static final SnowflakeIdUtils instance = new SnowflakeIdUtils(0, 0);/*** 机器id所占的位数*/private final long workerIdBits = 5L;/*** 数据标识id所占的位数*/private final long datacenterIdBits = 5L;/*** 工作机器ID(0~31)*/private final long workerId;/*** 数据中心ID(0~31)*/private final long datacenterId;/*** 毫秒内序列(0~4095)*/private long sequence = 0L;/*** 上次生成ID的时间截*/private long lastTimestamp = -1L;/*** 构造函数** @param workerId     工作ID (0~31)* @param datacenterId 数据中心ID (0~31)*/private SnowflakeIdUtils(long workerId, long datacenterId) {long maxWorkerId = ~(-1L << workerIdBits);if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}long maxDatacenterId = ~(-1L << datacenterIdBits);if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}/*** 测试*/public static void main(String[] args) {long st = System.currentTimeMillis();for (int i = 0; i < 4096000; i++) {SnowflakeIdUtils.getInstance().nextId();}long ent = System.currentTimeMillis();System.out.println("耗时=>{}" + (ent - st) + " 毫秒");}/*** 获得下一个ID (该方法是线程安全的)** @return SnowflakeId*/private synchronized long getSnowflakeId() {long timestamp = timeGen();//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}//如果是同一时间生成的,则进行毫秒内序列long sequenceBits = 12L;if (lastTimestamp == timestamp) {//生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)long sequenceMask = ~(-1L << sequenceBits);sequence = (sequence + 1) & sequenceMask;//毫秒内序列溢出if (sequence == 0) {//阻塞到下一个毫秒,获得新的时间戳timestamp = tilNextMillis(lastTimestamp);}}//时间戳改变,毫秒内序列重置else {sequence = 0L;}//上次生成ID的时间截lastTimestamp = timestamp;//移位并通过或运算拼到一起组成64位的IDlong timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;long datacenterIdShift = sequenceBits + workerIdBits;long epoch = 1420041600000L;return ((timestamp - epoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << sequenceBits) | sequence;}public String nextId() {return LocalDate.now().toString().replace("-", "") + getSnowflakeId();}/*** 阻塞到下一个毫秒,直到获得新的时间戳** @param lastTimestamp 上次生成ID的时间截* @return 当前时间戳*/protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}/*** 返回以毫秒为单位的当前时间** @return 当前时间(毫秒)*/protected long timeGen() {return System.currentTimeMillis();}
}

2:百度UidGenerator
 

public class UidGeneratorUtils {@Getterprivate static final UidGeneratorUtils instance = new UidGeneratorUtils(0);// 起始时间戳(2016-05-05 00:00:00)private final static long START_STAMP = 1462272000000L;// 序列号位数private final static long SEQUENCE_BIT = 12;// 工作节点位数private final static long WORKER_BIT = 10;// 掩码(用于取低 n 位)private final static long SEQUENCE_MASK = ~(-1L << SEQUENCE_BIT);// 最大值private final static long MAX_WORKER_ID = ~(-1L << WORKER_BIT);// 工作节点 ID(需确保分布式环境中唯一)private final long workerId;// 毫秒内序列号(从 0 开始)private long sequence = 0L;// 上一次时间戳private long lastTimestamp = -1L;/*** 构造函数** @param workerId 工作节点 ID(0~1023)*/public UidGeneratorUtils(long workerId) {if (workerId < 0 || workerId > MAX_WORKER_ID) {throw new IllegalArgumentException("Worker ID 必须在 0~" + MAX_WORKER_ID + " 之间");}this.workerId = workerId;}/*** 测试*/public static void main(String[] args) {long st = System.currentTimeMillis();for (int i = 0; i < 4096000; i++) {System.out.println(getInstance().nextId());}long ent = System.currentTimeMillis();System.out.println("耗时=>{}" + (ent - st) + " 毫秒");}/*** 生成 ID** @return 64 位 long 型 ID*/public synchronized long nextId() {long timestamp = timeGen();// 时间回拨处理if (timestamp < lastTimestamp) {long offset = lastTimestamp - timestamp;if (offset > 5) {  // 允许最多 5ms 的回拨throw new RuntimeException("时钟回拨,拒绝生成 ID。回拨时间:" + offset + "ms");}timestamp = lastTimestamp;  // 等待时间前进}// 同一毫秒内生成 IDif (timestamp == lastTimestamp) {sequence = (sequence + 1) & SEQUENCE_MASK;if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp);  // 等待下一毫秒}} else {sequence = 0;  // 新毫秒,重置序列号}lastTimestamp = timestamp;// 拼接 ID:符号位(0) + 时间戳 + 工作节点 ID + 序列号return (timestamp - START_STAMP) << (WORKER_BIT + SEQUENCE_BIT) | (workerId << SEQUENCE_BIT) | sequence;}/*** 等待到下一毫秒** @param lastTimestamp 上一次时间戳* @return 当前时间戳*/private long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}/*** 获取当前时间戳** @return 毫秒级时间戳*/private long timeGen() {return System.currentTimeMillis();}
}

相关文章:

  • 鸿蒙版FlutterSDK3.27.4可以使用了
  • [论文阅读] 人工智能 | 真实场景下 RAG 系统的工程实践指南
  • 数据结构之顺序表(C语言版本)
  • PHP在做爬虫时的解决方案
  • 跨芯片 AI 算子库 FlagGems 正式加入PyTorch 基金会生态项目体系
  • idea的EasyCode插件连接瀚高数据库(APP)
  • 基于Anaconda环境开发IntelliJ IDEA实用JSON转Java实体插件
  • ASM1042在矿山设备通信中的抗干扰性能优化研究
  • JavaEE-Spring事务和事务的传播机制
  • SpringMVC系列(四)(请求处理的十个实验(下))
  • LabVIEW疲劳试验机模糊PID
  • 人工智能-基础篇-3-什么是深度学习?(DL,卷积神经网络CNN,循环神经网络RNN,Transformer等)
  • 华为云Flexus+DeepSeek征文|高可用部署 Dify 平台构建 Flux 绘画中台 Chatflow 的设计与实现
  • Android11 wifi开启源码分析
  • SQl中多使用EXISTS导致多查出了一条不符合条件的数据
  • 设计模式之房产中介——代理模式
  • redisTemplate简单实现幂等性校验
  • 机器人 URDF学习笔记
  • 51单片机教程(十三)- 单片机串口通信
  • mac docker desktop 安装 oracle