ID生成规则

1package com.zhiche.tools.application; 2 3import java.util.Random; 4 5public class IdSnowFlake { 6 private final long workerId;//数据中心(5位) 7 private final long datacenterId;//节点(5位) 8 private final long idepoch;//毫秒级时间(41位) 9 private long sequence;//毫秒内序列(12位) 10 11 12 private static final long datacenterIdShift = 17L; 13 private static final long workerIdShift = 12L; 14 private static final long timestampLeftShift = 22L; 15 private static final long maxWorkerId = 31L; 16 private static final long maxDatacenterId = 31L; 17 private static final long sequenceMask = 4095L;//序列编号共12位,每节点每毫秒生成4096个ID 18 19 private long lastTimestamp = -1L;//可以根据需要设定一个最早时间,任何时间不得小于最早时间,默认不设限制。 20 private long defaultTimestamp = 1288834974657L;//可以根据实情进行时间的修改。 21 private static final Random r = new Random(); 22 23 /** 24 * 数据中心=random,节点中心=random,毫秒内序列(12位)=0,毫秒级时间(41位)=now 25 */ 26 public IdSnowFlake() { 27 this(System.currentTimeMillis()); 28 } 29 30 /** 31 * 数据中心=random,节点中心=random,毫秒内序列(12位)=0 32 * @param idepoch 毫秒级时间(41位) 33 */ 34 public IdSnowFlake(long idepoch) { 35 this(r.nextInt((int) maxWorkerId), r.nextInt((int) maxDatacenterId), 0, idepoch); 36 } 37 38 /** 39 * 毫秒内序列 = 0, 毫秒级时间 = now, [常用的构造为这个构造] 40 * @param workerId 数据中心(5位) 41 * @param datacenterId 节点(5位) 42 */ 43 public IdSnowFlake(long workerId, long datacenterId) { 44 this(workerId, datacenterId, 0, System.currentTimeMillis()); 45 } 46 47 /** 48 * 毫秒级时间 = now 49 * @param workerId 数据中心(5位) 50 * @param datacenterId 节点(5位) 51 * @param sequence 毫秒内序列(12位) 52 */ 53 public IdSnowFlake(long workerId, long datacenterId, long sequence) { 54 this(workerId, datacenterId, sequence, System.currentTimeMillis()); 55 } 56 57 /** 58 * 数据中心,节点中心,毫秒内序列(12位),毫秒级时间(41位) 59 * @param workerId 数据中心(5位) 60 * @param datacenterId 节点(5位) 61 * @param sequence 毫秒内序列(12位) 62 * @param idepoch 毫秒级时间(41位) 63 */ 64 public IdSnowFlake(long workerId, long datacenterId, long sequence, long idepoch) { 65 this.workerId = workerId; 66 this.datacenterId = datacenterId; 67 this.sequence = sequence; 68 this.idepoch = idepoch; 69 if (workerId < 0 || workerId > maxWorkerId) { 70 throw new IllegalArgumentException(String.format("非法workerId 数据中心(5位)应大于0而小于%d,而当前值为:%d", maxWorkerId,workerId)); 71 } 72 if (datacenterId < 0 || datacenterId > maxDatacenterId) { 73 throw new IllegalArgumentException(String.format("非法datacenterId 节点(5位)应大于0而小于%d,而当前值为:%d ", maxDatacenterId , datacenterId)); 74 } 75 } 76 77 /** 78 * @return 数据中心5位 79 */ 80 public long getDatacenterId() { 81 return datacenterId; 82 } 83 84 public long getIdepoch() { 85 return idepoch; 86 } 87 88 public long getlastTimeStamp() { 89 return lastTimestamp; 90 } 91 92 public long getSequence() { 93 return sequence; 94 } 95 96 /** 97 * @return 节点5位 98 */ 99 public long getWorkerId() { 100 return workerId; 101 } 102 103 /** 104 * @return 当前时间 105 */ 106 public long getTime() { 107 return System.currentTimeMillis(); 108 } 109 110 /** 111 * @return 得到long类型id 112 */ 113 public long getId() { 114 long id = nextId(); 115 return id; 116 } 117 118 /** 119 * 设置最早时间 120 * @param lastTimestamp 最早时间 121 */ 122 public void setLastTimestamp(long lastTimestamp) { 123 this.lastTimestamp = lastTimestamp; 124 } 125 126 private synchronized long nextId() { 127 long timestamp = timeGen(); 128 if (timestamp < lastTimestamp) { 129 throw new IllegalStateException(String.format("时间早于最低时间:%d",lastTimestamp)); 130 } 131 if (lastTimestamp == timestamp) { 132 sequence = (sequence + 1) & sequenceMask; 133 if (sequence == 0) { 134 timestamp = tilNextMillis(lastTimestamp); 135 } 136 } else { 137 sequence = 0; 138 } 139 lastTimestamp = timestamp; 140 //a|b的意思就是把a和b按位或, 按位或的意思就是先把a和b都换成2进制,然后用或操作 141 //[也可以改成直接+操作,直接+操作效率高,但是会有极低概率产生重复ID] 142 long id = ((timestamp - defaultTimestamp) << timestampLeftShift)//前41位 143 | (datacenterId << datacenterIdShift)//中间前5位 144 | (workerId << workerIdShift)//中间后5位 145 | sequence;//最后12位 146/* long id = ((timestamp - defaultTimestamp) << timestampLeftShift)//前41位 147 + (datacenterId << datacenterIdShift)//中间前5位 148 + (workerId << workerIdShift)//中间后5位 149 + sequence;//最后12位 150*/ 151 return id; 152 } 153 154 private long tilNextMillis(long lastTimestamp) { 155 long timestamp = timeGen(); 156 while (timestamp <= lastTimestamp) { 157 timestamp = timeGen(); 158 } 159 return timestamp; 160 } 161 162 private long timeGen() { 163 return System.currentTimeMillis(); 164 } 165 166 @Override 167 public String toString() { 168 final StringBuilder sb = new StringBuilder("IdWorker{"); 169 sb.append("workerId=").append(workerId); 170 sb.append(", datacenterId=").append(datacenterId); 171 sb.append(", idepoch=").append(idepoch); 172 sb.append(", lastTimestamp=").append(lastTimestamp); 173 sb.append(", sequence=").append(sequence); 174 sb.append('}'); 175 return sb.toString(); 176 } 177} 178 179 180package cn.huiyunche.base.service.utils; 181 182import cn.huiyunche.tools.application.IdSnowFlake; 183 184/** 185 * @ClassName: UniquenessFlagUnits 186 * @Description: 唯一性标示 187 * @author: Aaron 188 * @date: 2016年7月25日 上午10:50:38 189 */ 190public class UniquenessFlagUnits { 191 192 /** 193 * @param prifix 前缀 194 * @return 195 * @Title: generateUniquenessFlag 196 * @Description: 根据前缀生成唯一性标示 197 * @return: String 198 */ 199 public static String generateUniquenessFlag(String prifix) { 200 IdSnowFlake id = new IdSnowFlake(); 201 return String.valueOf(prifix + id.getId()); 202 } 203}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )