Java唯一序列订单号生成源码,基于snowflake算法

本文介绍了基于Snowflake算法的Java实现,用于生成64位的唯一序列订单号。内容包括Snowflake算法的时间序列、机器标识和计数序列号的结构,以及Java源码实现。同时,文中还提到了多线程环境下测试订单号生成的场景,并对比了UUID和时间戳两种其他实现唯一性的方法及其优缺点。

Snowflake简介

Snowflake生成的每一个ID都是64位的整型数,它的核心算法也比较简单高效,结构如下:

  • 41位的时间序列,精确到毫秒级,41位长度可以使用69年。时间位还有一个很重要的作用是可以根据时间进行排序。

  • 10位的机器标识,10位的长度最多支持部署1024个节点。

  • 12位的计数序列号,序列号即一系列的自增id,可以支持同一节点同一毫秒生成多个ID序号,12位的计数序列号支持每个节点每毫秒产生4096个ID序号。

  • 最高位是符号位,始终为0,不可用。

 

Snowflake原生算法java实现

package com.app.xm.utils;

/**
 * 唯一序列ID,原生java算法
 * 从网上查找的源码
 * @author ouyangjun
 *
 */
public class IdSequenceUtils {
	
	private long workerId;
	private long datacenterId;
	private long sequence = 0L;
	private long twepoch = 1514736000000L; //从该时间2018-01-01 00:00:00开始
	private long workerIdBits = 5L; //节点ID长度
	private long datacenterIdBits = 5L; //数据中心ID长度
	private long maxWorkerId = -1L ^ (-1L << workerIdBits); //最大支持机器节点数0~31,一共32个
	private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); //最大支持数据中心节点数0~31,一共32个
	private long sequenceBits = 12L; //序列号12位
	private long workerIdShift = sequenceBits; //机器节点左移12位
	private long datacenterIdShift = sequenceBits + workerIdBits; //数据中心节点左移17
### SnowFlake.java 源代码实现 #### 构造函数与初始化过程 `SnowflakeIDGenImpl` 类的主要职责在于创建 `SnowflakeZookeeperHolder` 对象并调用其 `init()` 方法完成初始化,从而确定当前机器的 `workerId`[^1]。这一步骤对于确保分布式环境中唯一 ID 的生成至关重要。 ```java public class SnowflakeIDGenImpl { private final long workerId; public SnowflakeIDGenImpl(long workerId, long dataCenterId) { this.workerId = workerId; // 进行其他必要的初始化操作... } } ``` #### IdWorker类的核心逻辑 核心功能通过 `IdWorker` 类来实现,该类负责实际的 ID 生产流程。根据设计原则,每个产生的 ID 都会被划分为多个部分,具体结构如下所示: - 时间戳:用于记录毫秒级别的时间信息。 - 数据中心标识符 (`datacenterId`) 和工作进程标识符 (`workerId`) :用来区分不同的数据中心以及同一数据中心内的不同工作节点。 - 序列号:在同一毫秒内可能存在的并发请求分配唯一的序列编号。 ```java private static class IdWorker { // ...省略常量定义... private final long workerId; private final long datacenterId; public IdWorker(long workerId, long datacenterId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); } 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; lastTimestamp = -1L; // 上次生成ID的时间戳 } /** * 获取下一个ID */ protected synchronized long nextId() { long timestamp = timeGen(); if (timestamp < lastTimestamp) { // 如果服务器时间有问题(时钟回拨), 报错. throw new RuntimeException( String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } if (lastTimestamp == timestamp) { // 同一毫秒内,序列号自增 sequence = (sequence + 1) & sequenceMask; if (sequence == 0) { // 当前毫秒内已达到最大序列数,则等待下一毫秒继续尝试获取新的ID timestamp = tilNextMillis(lastTimestamp); } } else { // 不同毫秒内,重置序列号为零 sequence = 0L; } lastTimestamp = timestamp; // 将各部分组合成完整的64位二进制形式返回给调用者 return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; } //...其余辅助方法... } ``` 上述代码展示了如何构建一个基于雪花算法Java 版本实现方案,其中包含了基本的数据成员声明、异常处理机制以及关键业务逻辑的设计思路][^[^23]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值