为什么要学
和面试官对线,显得自己很博学!!!
分布式系统中确实要用到全局唯一ID的场景,大家应该知道UUID,但是UUID太low了,首先它比较长而且一般是无序的,我们想要简单些的ID,就想要你给我一个算法,根据时间有序生成一些简单的ID!!!
正好这不是有雪花算法ID吗?
别急,先捋一下概念
概念:分布式雪花算法(Snowflake)是一种用于生成全局唯一的分布式标识符的算法,特别适用于分布式系统中的唯一ID生成需求。
特点:雪花算法生成后是一个 64bit 的 long 型的数值,组成部分引入了时间戳,基本保持了自增。
记住两点就行:全局唯一、跟时间有关!!!
有啥利弊
没有完美的技术!!!
除非你来写一个完美的算法,我给你挑点骨头
先说优点:不依赖于数据库,在内存中生成,生成速度快
缺点呢?
依赖时间,如果系统时间被回调,或者改变,可能会造成 ID 冲突或者重复。
学点底层!方便对线
结构:
包含四个组成部分:
不使用: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);
}
}