当前位置: 首页 > 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();}
}

http://www.lqws.cn/news/540091.html

相关文章:

  • 深入解析:Vue 中的 Render 函数、JSX 与 @vitejs/plugin-vue-jsx 实践指南
  • DeepSeek 部署中的常见问题及解决方案:从环境配置到性能优化的全流程指南
  • Merkle Tree原理与Python实现
  • RabbitMQ RPC模式Python示例
  • 【RabbitMQ】基于Spring Boot + RabbitMQ 完成应用通信
  • Idea中Docker打包流程记录
  • C++11 <chrono> 库特性:从入门到精通
  • 线程与协程的比较
  • 【机器学习与数据挖掘实战 | 医疗】案例18:基于Apriori算法的中医证型关联规则分析
  • 《表白模版之聊天记录,前端js,html学习》
  • 2025暑期学习计划​参考
  • CPT204-Advanced OO Programming: Lists, Stacks, Queues, and Priority Queues
  • 026 在线文档管理系统技术架构解析:基于 Spring Boot 的企业级文档管理平台
  • Moxa 加入 The Open Group 的开放流程自动化™论坛,推动以开放、中立标准强化工业自动化
  • AI优化SEO关键词精进
  • 工作台-01.需求分析与设计
  • Django ORM 1. 创建模型(Model)
  • 安全运营中的漏洞管理和相关KPI
  • 桌面小屏幕实战课程:DesktopScreen 13 HTTP SERVER
  • PHP Protobuf 手写生成器,
  • BERT架构详解
  • 智能温差发电杯(项目计划书)
  • LinuxBridge的作用与发展历程:从基础桥接到云原生网络基石
  • AIOps与人工智能的融合:从智能运维到自适应IT生态的革命
  • 【Linux指南】压缩、网络传输与系统工具
  • webGL面试题200道
  • Vue3 + Element Plus Transfer 穿梭框自定义分组
  • 【docker】构建时使用宿主机的代理
  • HarmonyOS NEXT仓颉开发语言实战案例:简约音乐播放页
  • jvm简单八股