一、雪花ID简介
雪花ID是Twitter开源的分布式ID生成算法,采用信息耗尽式算法,生成的id不会重复,可以根据时间戳、机器id、序列号等信息生成64位的长整型ID。雪花ID是一个非常流行的分布式ID生成算法,其底层依赖于一个64位的long型变量,可以通过位运算等方式将long型变量表示成字符串形式的ID号,以此实现唯一ID的生成。
二、雪花ID组成部分
雪花ID组成的64位就是一个long型的数字,从二进制的角度来看,这个数字上有五部分构成:
- 1.首位是符号位(1bit),生成的ID恒为正数,所以这个位的值始终是0。
- 2.接下来的41位是时间戳, 表示生成的时间戳(毫秒级)。
- 3.然后是5位数据中心标识ID和5位进程标识ID,表示在两部分信息中的机器ID标识,15位的机器编号支持的节点数达到32768个机器节点。
- 4.紧接着是10位序列号,表示同一机器同一毫秒内生成的不同ID序号,同时支持单机每毫秒的ID数达到1024个。
通过这样的方式组装成一个64位的long型变量。
三、雪花ID生成的可靠性
雪花ID是满足以下需求的:
- 1.全局唯一,时间戳(包括序列号)相同的id不会重复。
- 2.趋势递增,因为采用时间戳作为生成信息,所以生成的ID越来越大。
- 3.信息安全,序列号占了10位,理论上每个时间戳里的序列号最大可以达到1024,如果超过了这个限制,程序会自旋等待下一个毫秒再生成ID。
- 4.高可用,如果发生时钟回拨,可以通过程序自旋等待后续时钟进行补偿。
四、雪花ID生成步骤
为了更好地理解雪花ID生成规则,我们可以将其步骤总结如下:
- 1.时间戳部分
- 2.数据中心、机器标识部分
- 3.序列号部分
long timestamp = System.currentTimeMillis();
时间戳部分采用当前时间毫秒级别的时间戳,占用41位。
long datacenterId = 1L;
long machineId = 2L;
数据中心和机器标识这两部分都是采用配置的方式来实现,占用10位。
long sequence = 0L;
long lastTimestamp = -1L;
while (true) {
long nowTimestamp = System.currentTimeMillis();
if (nowTimestamp < lastTimestamp) {
throw new RuntimeException("雪花ID系统时钟回退异常,请及时处理!");
}
if (nowTimestamp == lastTimestamp) {
sequence = (sequence + 1) & maxSequence;
if (sequence == 0) {
nowTimestamp = waitNextMillisecond(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = nowTimestamp;
return ((nowTimestamp - twepoch) << timestampShift) |
(datacenterId << datacenterIdShift) |
(machineId << machineIdShift) | sequence;
}
序列号部分采用循环累加的方式实现,可实现每毫秒1024个不同的序列号,占用10位。
五、雪花ID生成总结
雪花ID是一种很好的分布式ID生成算法,其基于时间戳、机器ID、序列号等信息生成唯一的64位ID。同时,其在可靠性、趋势递增、信息安全以及高可用等方面表现出了极佳的效果,并且也有着较为简洁易懂的生成规则。我们在实际项目中常常会使用到这种方式来生成唯一ID,哈哈,不过要注意时钟回拨问题哦~