生成主键ID,唯一键id,分布式ID生成器雪花算法代码实现
工具类:
package com.ihrm.common.utils;import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;//雪花算法代码实现
public class IdWorker {// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)private final static long twepoch = 1288834974657L;// 机器标识位数private final static long workerIdBits = 5L;// 数据中心标识位数private final static long datacenterIdBits = 5L;// 机器ID最大值private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);// 数据中心ID最大值private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);// 毫秒内自增位private final static long sequenceBits = 12L;// 机器ID偏左移12位private final static long workerIdShift = sequenceBits;// 数据中心ID左移17位private final static long datacenterIdShift = sequenceBits + workerIdBits;// 时间毫秒左移22位private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;private final static long sequenceMask = -1L ^ (-1L << sequenceBits);/* 上次生产id时间戳 */private static long lastTimestamp = -1L;// 0,并发控制private long sequence = 0L;private final long workerId;// 数据标识id部分private final long datacenterId;public IdWorker(){this.datacenterId = getDatacenterId(maxDatacenterId);this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);}/*** @param workerId* 工作机器ID* @param datacenterId* 序列号*/public IdWorker(long workerId, long datacenterId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}/*** 获取下一个ID** @return*/public synchronized long nextId() {long timestamp = timeGen();if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}if (lastTimestamp == timestamp) {// 当前毫秒内,则+1sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {// 当前毫秒内计数满了,则等待下一秒timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0L;}lastTimestamp = timestamp;// ID偏移组合生成最终的ID,并返回IDlong nextId = ((timestamp - twepoch) << timestampLeftShift)| (datacenterId << datacenterIdShift)| (workerId << workerIdShift) | sequence;return nextId;}private long tilNextMillis(final long lastTimestamp) {long timestamp = this.timeGen();while (timestamp <= lastTimestamp) {timestamp = this.timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}/*** <p>* 获取 maxWorkerId* </p>*/protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {StringBuffer mpid = new StringBuffer();mpid.append(datacenterId);String name = ManagementFactory.getRuntimeMXBean().getName();if (!name.isEmpty()) {/** GET jvmPid*/mpid.append(name.split("@")[0]);}/** MAC + PID 的 hashcode 获取16个低位*/return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);}/*** <p>* 数据标识id部分* </p>*/protected static long getDatacenterId(long maxDatacenterId) {long id = 0L;try {InetAddress ip = InetAddress.getLocalHost();NetworkInterface network = NetworkInterface.getByInetAddress(ip);if (network == null) {id = 1L;} else {byte[] mac = network.getHardwareAddress();id = ((0x000000FF & (long) mac[mac.length - 1])| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;id = id % (maxDatacenterId + 1);}} catch (Exception e) {System.out.println(" getDatacenterId: " + e.getMessage());}return id;}
}
使用:
IdWorker idWorker = new IdWorker();long id = idWorker.nextId();
生成主键ID,唯一键id,分布式ID生成器雪花算法代码实现相关推荐
- springboot 主键重复导致数据重复_程序员:MySQL处理插入过程中主键或唯一键重复值的解决办法
向MySQL插入数据有时会遇到主键重复的场景,原来的做法是先在程序代码中SELECT一下,判断是否存在指定主键或唯一键的数据,如果没有则插入,有的话则执行UPDATE操作,或另外一套逻辑,这种方法是不 ...
- MySQL处理插入过程中主键或唯一键重复值的解决办法
向MySQL插入数据有时会遇到主键重复的场景,原来的做法是先在程序代码中SELECT一下,判断是否存在指定主键或唯一键的数据,如果没有则插入,有的话则执行UPDATE操作,或另外一套逻辑,这种方法是不 ...
- 主键、唯一键、外键、
类型 保证唯一性 是否允许空 一个表中可以有多少个 是否允许组合 主键(primary key) 是 否 至多一个,可以为0 允许(不推荐,因为不稳定) 唯一(unique) 是 是 可以有多个 允许 ...
- mysql唯一性和主键区别_Mysql主键和唯一键的区别点总结
什么是主键? 主键是表中唯一标识该表中每个元组(行)的列.主键对表实施完整性约束.表中只允许使用一个主键.主键不接受任何重复值和空值.表中的主键值很少更改,因此在选择主键是需要小心,要选择很少发生更改 ...
- powerdesigner设置主键为自增字段,设置非主键为唯一键并作为表的外键
转自:https://www.cnblogs.com/CoffeeHome/archive/2014/06/04/3767501.html 这里powerdesigner连接的数据库是以mysql为例 ...
- DB2添加数据时主键、唯一键冲突的解决方法
DB2添加数据时主键.唯一键冲突的解决方法 参考文章: (1)DB2添加数据时主键.唯一键冲突的解决方法 (2)https://www.cnblogs.com/equation/articles/91 ...
- ORA-02437: cannot validate(主键或唯一键约束名) - primary key violated
今天在对现有表建立唯一索引时遇到该Ora异常 ORA-02437: cannot validate(主键或唯一键约束名) - primary key violated 主键或唯一键的数据有重复值,一般 ...
- sql主键和唯一键和外键
mysql数据库中对字段的约束里存在主键约束,也存在唯一键约束,这两种约束很容易出现混淆的情况,这里讲一下两个的区别: 主键和唯一键的对比: 约束 保证唯一性 是否为空 一个表中有多少个 是否允许组合 ...
- MySQL中的主键、唯一键、外键对比
一.主键 主键:每张表中只能有一个字段(复合主键可以有多个字段)使用此属性,用来唯一约束该字段中的数据,不能重复 1.增加主键: 在创建表的时候,直接在字段后,添加primary key关键字 CRE ...
最新文章
- 美妆AI要抢李佳琦的饭碗?
- 第四范式受邀参加信息技术大讲堂 共探新基建发展趋势
- Angular No provider for EffectsRootModule错误消息的出现原因和修复方式
- SAP CRM and C4C PDF print
- 奇淫巧技-Flutter调用C#
- Tab标签页接口---使用Intent对象
- java标识符命名_Java标识符命名规则
- Mysql学习总结(63)——Mysql数据库架构方案选择与分析
- AndroidStudio安卓原生开发_Fragment_认识使用Fragment_创建_删除fragment---Android原生开发工作笔记116
- C# 代码调整屏幕分辨率
- Doris之物化视图
- 并发编程的挑战——sychronized锁
- C语言深度剖析-----数组基础
- X1000对于camera控制部分的翻译
- Ckeditor富文本编辑器的使用Smartupload文件上传
- IC人物志-Intel创世人Robert Norton Noyce(罗伯特·诺伊斯)
- linux什么时候挂载根文件系统,什么时候要重新制作Linux的根文件系统?谢谢
- Unity UGUI 代码改变遮挡层级
- 杭州旭航集团,申请纳斯达克IPO上市,募资9800万美元
- 最详细的SQL注入语句