当前位置: 首页 > 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.lryc.cn/news/575881.html

相关文章:

  • 微信小程序跳转传参方式
  • 链表最终章——双向链表及其应用
  • Stable Diffusion入门-ControlNet 深入理解-第三课:结构类模型大揭秘——深度、分割与法线贴图
  • 【向上教育】结构化面试开口秘籍.pdf
  • 【江科大】STM32F103C8T6 + TB6612 + N20编码器减速电机《03-增量式PID定速控制》(增量式PID,定时器输入捕获,定时器编码器)
  • 动手学Python:从零开始构建一个“文字冒险游戏”
  • Fiddler中文版抓包工具在跨域与OAuth调试中的深度应用
  • 电子电气架构 --- 车联网技术简介
  • 什么是国际期货?期货交易平台搭建
  • 在反向代理环境下精准获取客户端真实 IP 的最佳实践
  • Java项目:基于SSM框架实现的宠物综合服务平台管理系统【ssm+B/S架构+源码+数据库+毕业论文+开题报告】
  • 论分布式设计
  • 学习设计模式《十五》——模板方法模式
  • Python打卡:Day39
  • LLM驱动开发:正在重塑软件工程的下一场革命
  • Moxa 加入 The Open Group 的开放流程自动化™论坛,推动以开放、中立标准强化工业自动化
  • uniapp处理后端返回的html字符串
  • Redis-zset有序集合
  • 什么是DNS缓存投毒?有哪些防御措施?
  • mac 安装python,切换python版本
  • 聚铭网络入选嘶吼《中国网络安全细分领域产品名录》“云平台安全管理”与“态势感知”双领域TOP10
  • 【C++】责任链模式
  • VSCode中创建和生成动态库项目
  • CSS3实现同心圆效果
  • flink同步kafka到paimon,doris加速查询
  • RediSearch高性能全文搜索引擎
  • AI优化SEO关键词精进
  • 基于Redis分布式的限流
  • JavaScript性能优化
  • Feign 实战指南:从 REST 替代到性能优化与最佳实践