永不重复的id生成器

(1)需要导入的包
主要用在格式化日FastDateFormat.getInstance("yyyyMMddHHmmssSSS");
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
(2)IdGenerator类
import org.apache.commons.lang3.time.FastDateFormat;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* 与snowflake算法区别,返回字符串id,占用更多字节,但直观从id中看出生成时间
* 改写了生成时间的format方法
* @Project concurrency
*/
public enum IdGenerator {
INSTANCE;
private long workerId; //用ip地址最后几个字节标示
private long datacenterId = 0L; //可配置在properties中,启动时加载,此处默认先写成0
private long sequence = 0L;
private long workerIdBits = 8L; //节点ID长度
private long datacenterIdBits = 2L; //数据中心ID长度,可根据时间情况设定位数
private long sequenceBits = 12L; //序列号12位
private long workerIdShift = sequenceBits; //机器节点左移12位
private long datacenterIdShift = sequenceBits + workerIdBits; //数据中心节点左移14位
private long sequenceMask = -1L ^ (-1L << sequenceBits); //4095
private long lastTimestamp = -1L;
private static final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance("yyyyMMddHHmmssSSS");
IdGenerator(){
workerId = 0x000000FF & getLastIP();
}
public synchronized String 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) {
//sequence自增,因为sequence只有12bit,所以和sequenceMask相与一下,去掉高位
sequence = (sequence + 1) & sequenceMask;
//判断是否溢出,也就是每毫秒内超过4095,当为4096时,与sequenceMask相与,sequence就等于0
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp); //自旋等待到下一毫秒
}
} else {
sequence = 0L; //如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加
}
lastTimestamp = timestamp;
long suffix = (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
//String datePrefix = DateFormatUtils.format(timestamp, "yyyyMMddHHmmssSSS");
String datePrefix = FAST_DATE_FORMAT.format(timestamp);
return datePrefix + suffix;
}
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
protected long timeGen() {
return System.currentTimeMillis();
}
private byte getLastIP(){
byte lastip = 0;
try{
InetAddress ip = InetAddress.getLocalHost();
byte[] ipByte = ip.getAddress();
lastip = ipByte[ipByte.length - 1];
} catch (UnknownHostException e) {
e.printStackTrace();
}
return lastip;
}
}
(3)使用举例
String id = IdGenerator.INSTANCE.nextId()
永不重复的id生成器的更多相关文章
- IDUtil 永不重复的ID
package com.xxx.common.util; import java.util.Random; /** * 各种id生成策略 * * @version 1.0 */ public clas ...
- IOS ID生成器
// // IdGenerator.m // Copyright (c) 2014年 青岛拓宇网络科技有限公司. All rights reserved. // #import "IdGen ...
- js生成一个不重复的ID的函数的进化之路
在MongoDB中的ObjectID,可以理解为是一个不会重复的ID,这里有个链接http://blog.csdn.net/xiamizy/article/details/41521025感兴趣可以去 ...
- 分布式ID生成器 zz
简介 这个是根据twitter的snowflake来写的.这里有中文的介绍. 如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余63位可用. 下面的代码与 ...
- 游戏服务器ID生成器组件
游戏服务器程序中,经常需要生成全局的唯一ID号,这个功能很常用,本文将介绍一种通用ID生成组件.游戏服务器程序中使用此组件的场景有: 创建角色时,为其分配唯一ID 创建物品时,每个物品需要唯一ID 创 ...
- ID生成器详解
概述 ID 生成器也叫发号器,它的主要目的就是"为一个分布式系统的数据object产生一个唯一的标识",但其实在一个真实的系统里可能也可以承担更多的作用.概括起来主要有以下几点: ...
- twitter的ID生成器的snowFlake算法的自造版
snowFlake算法在生成ID时特别高效,可参考:https://segmentfault.com/a/1190000011282426 SnowFlake算法生成id的结果是一个64bit大小的整 ...
- c#分布式ID生成器
c#分布式ID生成器 简介 这个是根据twitter的snowflake来写的.这里有中文的介绍. 如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余 ...
- ID 生成器 雪花算法
https://blog.csdn.net/wangming520liwei/article/details/80843248 ID 生成器 雪花算法 2018年06月28日 14:58:43 wan ...
随机推荐
- Katalon Studio之接口测试中token处理
前言 最近抽时间接触了一下Katalon Studio(后面简称KS),并且利用KS做了一些接口测试的试验,感觉还不错,不过其中接口授权中缺少通过token动态验证的方案,虽然KS支持Authoriz ...
- k8s probe
livenessProbe: httpGet: path: /abc/401 port: 8384 scheme: HTTP
- TCP协议学习总结(上)
在计算机领域,数据的本质无非0和1,创造0和1的固然伟大,但真正百花齐放的还是基于0和1之上的各种层次之间的组合(数据结构)所带给我们人类各种各样的可能性.例如TCP协议,我们的生活无不无时无刻的站在 ...
- 贪心算法----区间选点问题(POJ1201)
题目: 题目的大致意思是,给定n个闭区间,并且这个闭区间上的点都是整数,现在要求你使用最少的点来覆盖这些区间并且每个区间的覆盖的点的数量满足输入的要求点覆盖区间的数量. 输入: 第一行输入n,代表n个 ...
- Python代码缩进与测试模块
一.Python代码缩进 Python 函数没有明显的 begin 和 end ,没有标明函数的开始和结束的花括号.唯一的分隔符是一个冒号 ( : ),接着代码本身是缩进的. 例如:缩进 bui ...
- [Swift]LeetCode402. 移掉K位数字 | Remove K Digits
Given a non-negative integer num represented as a string, remove k digits from the number so that th ...
- [Swift]LeetCode414. 第三大的数 | Third Maximum Number
Given a non-empty array of integers, return the third maximum number in this array. If it does not e ...
- [Swift]LeetCode657. 机器人能否返回原点 | Robot Return to Origin
There is a robot starting at position (0, 0), the origin, on a 2D plane. Given a sequence of its mov ...
- [Swift]LeetCode803. 打砖块 | Bricks Falling When Hit
We have a grid of 1s and 0s; the 1s in a cell represent bricks. A brick will not drop if and only i ...
- pytorch学习:准备自己的图片数据
图片数据一般有两种情况: 1.所有图片放在一个文件夹内,另外有一个txt文件显示标签. 2.不同类别的图片放在不同的文件夹内,文件夹就是图片的类别. 针对这两种不同的情况,数据集的准备也不相同,第一种 ...