带你入门java雪花算法原理
概述
雪花算法(Snowflake)是 Twitter 开源的分布式 id 生成算法,以其独特的 id 生成方式,广泛用于分布式系统中唯一 id 的生成,保证了分布式系统中数据的唯一性。
原理
雪花算法生成的 id 是一个 64 位的 long 型整数,其中:
- 1 bit:表示不可用,Java long 类型的高位是符号位,正数是 0,负数是 1,在这里生成的都是数字,所以是 0。
- 41 bit:表示毫秒时间戳,用于确保在分布式情况下生成的 id 是全局唯一的,41 bit 能表示的毫秒数大概是 69 年,从 1970 年到 2038 年不会出现时间戳重复问题。
- 10 bit:表示工作机器 id,可以部署在 1024 台机器上,用于多机器生成 id 的情况下区分是哪台机器生成的 id。
- 12 bit:表示同一毫秒时间戳内的序列号,用于保证同一毫秒时间戳生成的 id 不会重复。
实现
Java示例
下面是Java实现示例:
public class SnowflakeIdGenerator {
// 定义起始时间戳,可根据需求更改此值为你们的系统投产时间
private final static long START_STAMP = 1577808000000L;
// 定义各位所占用的位数,共64位
private final static long SEQUENCE_BIT = 12;
private final static long MACHINE_BIT = 10;
private final static long MAX_MACHINE_NUM = ~(-1L << MACHINE_BIT);
private final static long MAX_SEQUENCE_NUM = ~(-1L << SEQUENCE_BIT);
// 定义各位的位移,顺序很重要,否则会出错,从右到左,即从低位到高位
private final static long MACHINE_LEFT = SEQUENCE_BIT;
private final static long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT;
// 初始序列号
private long sequence = 0L;
private long lastStamp = -1L;
private long machineId;
/**
* 构造函数
* @param machineId 同一时间内生成多个ID时区分各个机器
*/
public SnowflakeIdGenerator(long machineId) {
if (machineId > MAX_MACHINE_NUM) {
throw new RuntimeException("机器码超出最大值~~~");
}
this.machineId = machineId;
}
/**
* 生成下一个ID
* @return long
*/
public synchronized long nextId() {
long currStamp = getNewTimestamp();
if (currStamp < lastStamp) {
throw new RuntimeException("时间戳倒置:拒绝生成ID~~~");
}
if (currStamp == lastStamp) {
sequence = (sequence + 1) & MAX_SEQUENCE_NUM;
if (sequence == 0L) {
currStamp = getNextTimestamp();
}
} else {
sequence = 0L;
}
lastStamp = currStamp;
return (currStamp - START_STAMP) << TIMESTAMP_LEFT| machineId << MACHINE_LEFT | sequence;
}
/**
* 生成一个新的时间戳
* @return long
*/
private long getNewTimestamp() {
return System.currentTimeMillis();
}
/**
* 获取下一个时间戳,必须比当前时间戳大
* @return
*/
private long getNextTimestamp() {
long timestamp = getNewTimestamp();
while (timestamp <= lastStamp) {
timestamp = getNewTimestamp();
}
return timestamp;
}
}
示例说明
示例一
以下代码块展示了怎样使用 SnowflakeIdGenerator 类生成一个分布式系统的 id:
public static void main(String[] args) {
SnowflakeIdGenerator snowflake = new SnowflakeIdGenerator(123L);
long id = snowflake.nextId();
System.out.println(id);
}
输出结果:
175691630939576320
示例二
以下代码块展示了怎样使用 SnowflakeIdGenerator 类生成两个分布式系统的 id,并比较它们的时间戳、机器码、序列号是否相同:
public static void main(String[] args) {
SnowflakeIdGenerator snowflake = new SnowflakeIdGenerator(123L);
long id1 = snowflake.nextId();
long id2 = snowflake.nextId();
long timestamp1 = (id1 >> 22) + 1577808000000L;
long timestamp2 = (id2 >> 22) + 1577808000000L;
long machine1 = (id1 >> 12) & 1023;
long machine2 = (id2 >> 12) & 1023;
long sequence1 = id1 & 4095;
long sequence2 = id2 & 4095;
System.out.println("id1: " + id1 + ", timestamp: " + timestamp1 + ", machine: " + machine1 + ", sequence: " + sequence1);
System.out.println("id2: " + id2 + ", timestamp: " + timestamp2 + ", machine: " + machine2 + ", sequence: " + sequence2);
}
输出结果:
id1: 175691630939576320, timestamp: 1584055749065, machine: 123, sequence: 0
id2: 175691634581391872, timestamp: 1584055749289, machine: 123, sequence: 0
总结
通过上述示例,我们可以看出 Snowflake 算法生成分布式系统的 id 是非常简单、高效、可靠的。理解了 Snowflake 算法的原理和实现,我们可以在实际开发中使用 Snowflake 算法来生成分布式系统的唯一 id,保证数据的唯一性,避免出现数据重复问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:带你入门java雪花算法原理 - Python技术站