Java实现雪花算法的工具类介绍
简介
雪花 (SnowFlake )算法是一种分布式唯一ID生成算法,可以生成全局唯一的ID标识符,就像自然界中雪花一般没有相同的雪花。它的核心思想是将一个64位的整数分成4部分,分别是:
- 1位标识符:即最高位,始终为0,用于区分正数和负数。
- 41位时间戳:表示生成ID的时间戳,精确到毫秒级别,可以使用69年。
- 10位数据中心ID:表示数据中心的编号,可以支持1024个数据中心。
- 12位机器ID:表示机器的编号,可以支持4096台机器。
snowflake生成的ID整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和workerId作区分),并且效率较高。
在同一毫秒内,不同的机器或数据中心可以生成不同的序列号,通过这种方式保证了生成的ID的唯一性。另外,由于时间戳占据了64位整数的高位部分,因此生成的ID是越来越大的,可以满足一些需要按照时间顺序排序的场景需求。
雪花算法的优点在于:
- 简单易实现:主要依赖于时间戳、数据中心ID和机器ID三个参数,实现起来比较简单。
- 唯一性:生成的ID具有全局唯一性,可以满足分布式系统的需求。
- 时间有序:生成的ID是按照时间有序递增的,可以满足一些需要按照时间顺序排序的场景需求,存入数据库中,索引效率高。。
- 可扩展性:可以根据需要增加数据中心ID和机器ID的位数,支持更多的数据中心和机器。
- 高性能高可用:生成时不依赖于数据库,完全在内存中生成。
- 容量大:每秒中能生成数百万的自增ID。
但是,雪花算法也存在一些缺点:
- 依赖于系统时钟:如果系统时钟回拨,则可能会生成重复的ID。
- 数据中心ID和机器ID需要手动分配:需要手动配置数据中心ID和机器ID,不太方便管理。
- 机器编号有限:12位机器ID只能支持4096台机器,如果需要支持更多的机器,则需要增加机器ID的位数。
综上所述,雪花算法是一种简单易实现、具有唯一性和时间有序性的分布式ID生成算法,适用于分布式系统中的唯一ID标识符的生成。
Java实现
public class Snowflake { // 开始时间戳,一般为项目启动时间 private final long twepoch = 1288834974657L; // 机器ID所占的位数 private final long workerIdBits = 5L; // 数据标识ID所占的位数 private final long datacenterIdBits = 5L; // 支持的最大机器ID,结果是31 private final long maxWorkerId = ~(-1L << workerIdBits); // 支持的最大数据标识ID,结果是31 private final long maxDatacenterId = ~(-1L << datacenterIdBits); // 序列号所占的位数 private final long sequenceBits = 12L; // 机器ID向左移12位 private final long workerIdShift = sequenceBits; // 数据标识ID向左移17位(12+5) private final long datacenterIdShift = sequenceBits + workerIdBits; // 时间戳向左移22位(5+5+12) private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; // 生成序列的掩码,这里是4095 private final long sequenceMask = ~(-1L << sequenceBits); private long workerId; // 机器ID private long datacenterId; // 数据标识ID private long sequence = 0L; // 序列号 private long lastTimestamp = -1L; // 上次生成ID的时间戳 public Snowflake(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; } public 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) { // 序列号超过最大值,则等待下一个时间戳 timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; // 序列号重置为0 } lastTimestamp = timestamp; return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; } private long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } private long timeGen() { return System.currentTimeMillis(); } public static void main(String[] args) { Snowflake idWorker = new Snowflake(0, 0); for (int i = 0; i < 1000; i++) { long id = idWorker.nextId(); System.out.println(Long.toBinaryString(id)); System.out.println(id); } } }
Java相关工具类
Java版Snowflake开源库比较多,以下是一些常用的开源库及其使用方式:
1.Twitter的snowflake:是雪花算法最早的Java实现版本,支持高并发、低延迟、高可用等特点。使用方式:
Snowflake snowflake = new Snowflake(workerId, datacenterId); long id = snowflake.nextId();
2.百度的UidGenerator:是基于Twitter的snowflake算法改进而来的,支持高性能、高可用、高并发等特点。使用方式:
UidGenerator uidGenerator = UidGenerator.getUidGenerator(); long id = uidGenerator.getUID();
3.美团的Leaf:是一款高性能、轻量级的分布式ID生成器,支持多种ID生成算法,包括Snowflake算法。使用方式:
SegmentIDGenImpl idGen = new SegmentIDGenImpl(); idGen.init(); long id = idGen.getId();
4.阿里巴巴的nacos:是一款轻量级的服务注册与发现工具,其中包含了雪花算法的Java实现版本。使用方式:
SnowFlake snowFlake = new SnowFlake(dataCenterId, machineId); long id = snowFlake.nextId();
5.yitter
6.hutool工具类
Snowflake snowflake = IdUtil.getSnowflake(1, 1); long id = snowflake.nextId();
到此这篇关于Java实现雪花算法的工具类介绍的文章就介绍到这了,更多相关Java雪花算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
SpringBoot使用Validation进行参数校验的示例详解
在 SpringBoot项目开发中,有一个观点是不要相信前端传入的参数,因为你不知道用户是怎么操作我们接口的,所以在后端也需要对参数进行校验,这篇文章主要讲讲我们项目中最常使用的验证方案2023-05-05
最新评论