1、常用生成唯一ID的方式,例如UUID

2、生成唯一自自增长ID方式:

  例如:

    • Zookeeper的增加ID;
    • redis的incr方法
    • mongodb的objectId

3、采用雪花模型

如下代码:

 /**
* 采用twitter的雪花算法,生成有一定顺序且不重复的id,结果类型为64位的long型
*/
public class SnowflakeIdUtils {
//集群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 SnowflakeIdUtils() {
this(0, 0);
} /**
* 指定集群id和机器id
*
* @param datacenterId
* @param workerId
*/
public SnowflakeIdUtils(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 {
SnowflakeIdUtils snowflakeIdGen = new SnowflakeIdUtils();
//测试,生成10个唯一id
for (int i = 0; i < 10; i++) {
long id = snowflakeIdGen.nextId();
System.out.println(id);
}
}
}

这里采用的是默认构造生成 SnowflakeIdUtils,如果分布式服务同时调用的话,会出现重复ID,

所以需要加上 集群id(0~31),workerId(0~31)

了解更多雪花模型知识,后续补充。

最新文章

  1. Ubuntu学习总结-10 XManager
  2. 解决 odoo.py: error: option --addons-path: The addons-path &#39;local-addons/&#39; does not seem to a be a valid Addons Directory!
  3. 关于语句#ifdef OS_GLOBALS #define OS_EXT #else #define OS_EXT extern #endif 的说明
  4. ks全自动安装centos
  5. apache开源项目--Sirona
  6. SRBF Lighting
  7. Oracle成长点点滴滴(3)— 权限管理
  8. Unity开发之实现更换鼠标图片
  9. HTML5地理定位API在chrome中不能正常使用
  10. Java NIO5:通道和文件通道
  11. Java线程和线程池
  12. matlab 基于 libsvm工具箱的svm分类遇到的问题与解决
  13. INET_ADDRSTRLEN 和 INET6_ADDRSTRLEN 长度
  14. tomcat+ngnix单机搭建集群及端口占用问题
  15. 「6月雅礼集训 2017 Day11」delight
  16. C#中线程的委托
  17. (转载)--SG函数和SG定理【详解】
  18. Linux文件系统管理 fdisk分区命令
  19. XtraFinder
  20. DRF接入Oauth2.0认证[微博登录]报错21322重定向地址不匹配

热门文章

  1. [poj] 1204 Word Puzzles || AC自动机
  2. [bzoj] 1036 Count
  3. NOIP2017赛前模拟11月6日—7日总结
  4. Registering RHEL6 Clients into spacewalk
  5. linux缺页异常处理--内核空间【转】
  6. linux内核分析之进程地址空间【转】
  7. [Oracle] Transporting Tablespace
  8. python--asyncio模块
  9. Servlet 2.4 规范之第七篇:过滤器
  10. Selenium2+python自动化15-select下拉框【转载】