关于雪花算法

158 阅读2分钟

为什么要学

和面试官对线,显得自己很博学!!!

分布式系统中确实要用到全局唯一ID的场景,大家应该知道UUID,但是UUID太low了,首先它比较长而且一般是无序的,我们想要简单些的ID,就想要你给我一个算法,根据时间有序生成一些简单的ID!!!

正好这不是有雪花算法ID吗?

别急,先捋一下概念

概念:分布式雪花算法(Snowflake)是一种用于生成全局唯一的分布式标识符的算法,特别适用于分布式系统中的唯一ID生成需求。

特点:雪花算法生成后是一个 64bit 的 long 型的数值,组成部分引入了时间戳,基本保持了自增。

记住两点就行:全局唯一、跟时间有关!!!

有啥利弊

没有完美的技术!!!

除非你来写一个完美的算法,我给你挑点骨头

先说优点:不依赖于数据库,在内存中生成,生成速度快

缺点呢?

依赖时间,如果系统时间被回调,或者改变,可能会造成 ID 冲突或者重复。

学点底层!方便对线

结构:

image.png

包含四个组成部分:

不使用:1bit,最高位是符号位,0 表示正,1 表示负,固定为 0。

时间戳:41bit,毫秒级的时间戳(41 位的长度可以使用 69 年)。

标识位:5bit 数据中心 ID,5bit 工作机器 ID,两个标识位组合起来最多可以支持部署 1024 个节点。

序列号:12bit 递增序列号,表示节点毫秒内生成重复,通过序列号表示唯一

默认的雪花算法是 64 bit,具体的长度可以自行配置。如果希望运行更久,增加时间戳的位数;如果需要支持更多节点部署,增加标识位长度;如果并发很高,增加序列号位数。

对线须知:它底层包含四个部分:通常最高位不使用,然后是时间戳、标志位、序列号,雪花算法并不是一成不变的,可以根据系统内具体场景进行定制

学点实操,别露馅

在Java项目中使用雪花算法通常涉及到创建一个雪花ID生成器(Snowflake ID Generator)的实例

然后使用该实例生成唯一的ID

引入依赖

 <dependency>
     <groupId>com.github.ben-manes.caffeine</groupId>
     <artifactId>caffeine</artifactId>
     <version>2.9.1</version>
 </dependency>
 ​

创建雪花生成器id实例

 import com.github.benmanes.caffeine.cache.Caffeine;
 import com.github.benmanes.caffeine.cache.LoadingCache;
 ​
 public class SnowflakeIdGenerator {
     private final long workerId;
     private final long datacenterId;
     private final LoadingCache<Long, Snowflake> snowflakeCache;
 ​
     public SnowflakeIdGenerator(long workerId, long datacenterId) {
         this.workerId = workerId;
         this.datacenterId = datacenterId;
         this.snowflakeCache = Caffeine.newBuilder().build(workerId -> new Snowflake(workerId, datacenterId));
     }
 ​
     public long generateId() {
         return snowflakeCache.get(workerId).nextId();
     }
 }

使用雪花ID生成器

 public class Example {
     public static void main(String[] args) {
         SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);
 ​
         long uniqueId = idGenerator.generateId();
         System.out.println("Generated ID: " + uniqueId);
     }
 }