基于twitter的雪花算法生成不重复id
来源:互联网 发布:精准数据库营销 编辑:程序博客网 时间:2024/06/05 19:19
一、简介
在很多业务场景中,在单台机器或者由多台机器构成的分布式场景中,我们需要生成全局唯一的id。
在这里,将介绍基于twitter的雪花算法,生成全局的、唯一的、基于时间排序的、基本有序的id生成方法。
二、twitter雪花算法的原理
twitter的雪花算法,是将id按二进制比特位切割,不同的位区间,表示不同的含义,也即是不同位区间
的值生成方式不同,从而生成唯一的id。
如位区间可分为时间位区间、集群位区间、机器位区间、自增位区间,这样可在不同时间内、不同集群、
不同机器间,生成全局唯一的id。
三、twitter雪花算法的实例
在此以生成64位(即long型)为例进行介绍(其实区间位可以根据具体的业务需要自行指定)。
1、位区间化分
最高位(即第64位,从右向左数)为符号位,不使用;
41位(第23位到第63位)为时间位,可使用个数为2199023255551个,以毫秒为单位,大约69.5年;
5位(第18位到第22位)为集群位,可使用个数为32个;
5位(第13位到第17位)为机器位,可使用个数为32个;
12位(第1位到第12位)为序列号位,即是从0开始自增,可使用个数为4096个;
2、确定时间位开始计算的时间点
本例以2017-10-12 00:00:00开始计时,那么过去掉的时间(从1970-01-01 00:00:00开始)的毫秒数
为1507737600000,取时间时需要减去这段时间。
四、代码实例
/** * 采用twitter的雪花算法,生成有一定顺序且不重复的id,结果类型为64位的long型 */public class SnowflakeIdGen { //集群id private long datacenterId; //机器id private long workerId; //序列号 private long sequenceId; //集群id的bit位数 private long datacenterIdBits = 5L; //机器id的bit位数 private long workerIdBits = 5L; //序列号的bit位数 private long sequenceIdBits = 12L; //集群id的最大编号 private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); //机器id的最大编号 private long maxWorkerId = -1L ^ (-1L << workerIdBits); //序列号的掩码 private long sequenceIdMask = -1L ^ (-1L << sequenceIdBits); //生成最终结果时,集群id需移动的bit位数 private long timestampShiftBits = sequenceIdBits + workerIdBits + datacenterIdBits; //生成最终结果时,集群id需移动的bit位数 private long datacenterIdShiftBits = sequenceIdBits + workerIdBits; //生成最终结果时,机器id需移动的bit位数 private long workerIdShiftBits = sequenceIdBits; //去掉过去的时间,即从指定时间(本例以2017-10-12 00:00:00)开始算, // 大约可用69.5年(41位的时间位,最大值换成毫秒,再换算成年,大约69.5年) //1507737600000为从1970-01-01 00:00:00到2017-10-12 00:00:00经过的毫秒数 private long pastMills = 1507737600000L; //上一次生成id使用的timestamp ,以毫秒为单位 private long lastTimestamp = 1L; /** * 若没有指定集群id和机器id,则默认均为0 */ public SnowflakeIdGen() { this(0, 0); } /** * 指定集群id和机器id * * @param datacenterId * @param workerId */ public SnowflakeIdGen(long datacenterId, long workerId) { if (datacenterId < 0 || datacenterId > maxDatacenterId) { throw new RuntimeException(String.format("datacenterId greater than %d or less than 0", maxDatacenterId)); } if (workerId < 0 || workerId > maxWorkerId) { throw new RuntimeException(String.format("workerId greater than %d or less than 0", maxWorkerId)); } this.datacenterId = datacenterId; this.workerId = workerId; } /** * 生成全局唯一的id * * @return */ public synchronized long nextId() { long timestamp = System.currentTimeMillis(); if (timestamp < lastTimestamp) { //出现这种情况,通常是由于机器时间出问题了 throw new RuntimeException("machine time error"); } //同一时刻生成的id号 if (timestamp == lastTimestamp) { sequenceId = (sequenceId + 1) & sequenceIdMask; if (sequenceId == 0) { //说明当前毫秒的序列号用完了,需从下个毫秒数开始重新计数 timestamp = nextTimestamp(lastTimestamp); } } else { //否则序列号从0开始 sequenceId = 0L; } lastTimestamp = timestamp; long id = ((timestamp - pastMills) << timestampShiftBits) | (datacenterId << datacenterIdShiftBits) | (workerId << workerIdShiftBits) | sequenceId; return id; } /** * 获取上次取数毫秒的下一时刻 * * @param lastTimestamp * @return */ long nextTimestamp(long lastTimestamp) { long timestamp = System.currentTimeMillis(); while (timestamp <= lastTimestamp) { timestamp = System.currentTimeMillis(); } return timestamp; } public static void main(String[] args) throws Exception { SnowflakeIdGen snowflakeIdGen = new SnowflakeIdGen(); //测试,生成10个唯一id for (int i = 0; i < 10; i++) { long id = snowflakeIdGen.nextId(); System.out.println(id); } }}
结果输出:
330918199820288
330918199820289
330918199820290
330918199820291
330918199820292
330918199820293
330918199820294
330918199820295
330918199820296
330918199820297
- 基于twitter的雪花算法生成不重复id
- 基于Twitter的snowflake算法生成ID
- ID生成器,Twitter的雪花算法(Java)
- Twitter的雪花算法(snowflake)自增ID
- twitter ID生成算法
- 基于Twitter ID 生成策略
- 分布式全局不重复ID生成算法
- 基于业务对Twitter生成全局唯一ID的SnowFlake算法的改造
- Twitter的分布式自增ID雪花算法snowflake (Java版)
- Twitter的分布式自增ID算法Snowflake的PHP实现,Snowflake PHP版本,高并发唯一id,全局唯一id,不重复id
- 利用java生成不重复的ID
- twitter id生成算法snowflake详解
- twitter snow flake 雪花算法
- twitter 雪花算法 golang 实现
- [组合算法] 生成不重复的字符串
- 一种生成不重复数的算法
- 一种生成不重复数的算法
- 一种生成不重复数的算法
- python 试题:写一个类,并让它尽可能多的支持操作符。
- ambari的Command介绍
- 解决问题:Anaconda not opening: couldn't find or load Qt platform plugin "Windows in "" #1270
- 图层
- 【java设计模式初探0】_单例模式
- 基于twitter的雪花算法生成不重复id
- 搜狐畅游笔试题
- 1015德才论(排序)
- guava缓存的使用及与spring的集成
- 成为未来几年最炙手可热的机器学习人才,基本功、秘密武器和弹药补给
- 微软2017年预科生计划在线编程笔试-#1491 : Monster Killing
- 使用opencv保存多张图片
- html5的视频播放
- Java异常分类