博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ID生成规则
阅读量:6521 次
发布时间:2019-06-24

本文共 5643 字,大约阅读时间需要 18 分钟。

hot3.png

package com.zhiche.tools.application;import java.util.Random;public class IdSnowFlake {	private final long workerId;//数据中心(5位)    private final long datacenterId;//节点(5位)    private final long idepoch;//毫秒级时间(41位)    private long sequence;//毫秒内序列(12位)        private static final long datacenterIdShift = 17L;    private static final long workerIdShift = 12L;    private static final long timestampLeftShift = 22L;    private static final long maxWorkerId = 31L;    private static final long maxDatacenterId = 31L;    private static final long sequenceMask = 4095L;//序列编号共12位,每节点每毫秒生成4096个ID    private long lastTimestamp = -1L;//可以根据需要设定一个最早时间,任何时间不得小于最早时间,默认不设限制。    private long defaultTimestamp = 1288834974657L;//可以根据实情进行时间的修改。    private static final Random r = new Random();        /**     * 数据中心=random,节点中心=random,毫秒内序列(12位)=0,毫秒级时间(41位)=now     */    public IdSnowFlake() {        this(System.currentTimeMillis());    }        /**     * 数据中心=random,节点中心=random,毫秒内序列(12位)=0     * @param idepoch 毫秒级时间(41位)     */    public IdSnowFlake(long idepoch) {        this(r.nextInt((int) maxWorkerId), r.nextInt((int) maxDatacenterId), 0, idepoch);    }        /**     * 毫秒内序列 = 0, 毫秒级时间 = now, [常用的构造为这个构造]     * @param workerId 数据中心(5位)     * @param datacenterId 节点(5位)     */    public IdSnowFlake(long workerId, long datacenterId) {        this(workerId, datacenterId, 0, System.currentTimeMillis());    }        /**     * 毫秒级时间 = now     * @param workerId 数据中心(5位)     * @param datacenterId 节点(5位)     * @param sequence 毫秒内序列(12位)     */    public IdSnowFlake(long workerId, long datacenterId, long sequence) {    	this(workerId, datacenterId, sequence, System.currentTimeMillis());    }    /**     * 数据中心,节点中心,毫秒内序列(12位),毫秒级时间(41位)     * @param workerId 数据中心(5位)     * @param datacenterId 节点(5位)     * @param sequence 毫秒内序列(12位)     * @param idepoch 毫秒级时间(41位)     */    public IdSnowFlake(long workerId, long datacenterId, long sequence, long idepoch) {        this.workerId = workerId;        this.datacenterId = datacenterId;        this.sequence = sequence;        this.idepoch = idepoch;        if (workerId < 0 || workerId > maxWorkerId) {            throw new IllegalArgumentException(String.format("非法workerId 数据中心(5位)应大于0而小于%d,而当前值为:%d", maxWorkerId,workerId));        }        if (datacenterId < 0 || datacenterId > maxDatacenterId) {            throw new IllegalArgumentException(String.format("非法datacenterId 节点(5位)应大于0而小于%d,而当前值为:%d ", maxDatacenterId , datacenterId));        }    }        /**     * @return 数据中心5位     */    public long getDatacenterId() {        return datacenterId;    }        public long getIdepoch() {        return idepoch;    }        public long getlastTimeStamp() {        return lastTimestamp;    }        public long getSequence() {        return sequence;    }        /**     * @return 节点5位     */    public long getWorkerId() {        return workerId;    }        /**     * @return 当前时间     */    public long getTime() {        return System.currentTimeMillis();    }    /**     * @return 得到long类型id     */    public long getId() {        long id = nextId();        return id;    }        /**     * 设置最早时间     * @param lastTimestamp 最早时间     */    public void setLastTimestamp(long lastTimestamp) {		this.lastTimestamp = lastTimestamp;	}    	private synchronized long nextId() {        long timestamp = timeGen();        if (timestamp < lastTimestamp) {            throw new IllegalStateException(String.format("时间早于最低时间:%d",lastTimestamp));        }        if (lastTimestamp == timestamp) {            sequence = (sequence + 1) & sequenceMask;            if (sequence == 0) {                timestamp = tilNextMillis(lastTimestamp);            }        } else {            sequence = 0;        }        lastTimestamp = timestamp;        //a|b的意思就是把a和b按位或, 按位或的意思就是先把a和b都换成2进制,然后用或操作        //[也可以改成直接+操作,直接+操作效率高,但是会有极低概率产生重复ID]        long id = ((timestamp - defaultTimestamp) << timestampLeftShift)//前41位                | (datacenterId << datacenterIdShift)//中间前5位                | (workerId << workerIdShift)//中间后5位                | sequence;//最后12位/*        long id = ((timestamp - defaultTimestamp) << timestampLeftShift)//前41位        		+ (datacenterId << datacenterIdShift)//中间前5位        		+ (workerId << workerIdShift)//中间后5位        		+ sequence;//最后12位*/               return id;    }    private long tilNextMillis(long lastTimestamp) {        long timestamp = timeGen();        while (timestamp <= lastTimestamp) {            timestamp = timeGen();        }        return timestamp;    }    private long timeGen() {        return System.currentTimeMillis();    }    @Override    public String toString() {        final StringBuilder sb = new StringBuilder("IdWorker{");        sb.append("workerId=").append(workerId);        sb.append(", datacenterId=").append(datacenterId);        sb.append(", idepoch=").append(idepoch);        sb.append(", lastTimestamp=").append(lastTimestamp);        sb.append(", sequence=").append(sequence);        sb.append('}');        return sb.toString();    }}
package cn.huiyunche.base.service.utils;import cn.huiyunche.tools.application.IdSnowFlake;/** * @ClassName: UniquenessFlagUnits * @Description: 唯一性标示 * @author: Aaron * @date: 2016年7月25日 上午10:50:38 */public class UniquenessFlagUnits {    /**     * @param prifix 前缀     * @return     * @Title: generateUniquenessFlag     * @Description: 根据前缀生成唯一性标示     * @return: String     */    public static String generateUniquenessFlag(String prifix) {        IdSnowFlake id = new IdSnowFlake();        return String.valueOf(prifix + id.getId());    }}

 

转载于:https://my.oschina.net/u/2608890/blog/2247931

你可能感兴趣的文章
【selenium学习笔记一】python + selenium定位页面元素的办法。
查看>>
Linux禁止ping
查看>>
【Matplotlib】 标注一些点
查看>>
[AX]乐观并发控制Optimistic Concurrency Control
查看>>
自定义类加载器
查看>>
MySQL数据库事务各隔离级别加锁情况--Repeatable Read && MVCC(转)
查看>>
C++构造函数例程
查看>>
通过INI文件实现HYDRA各插件间对象共享
查看>>
把某一列值转换为逗号分隔字符串
查看>>
分布式计算领域的哥德尔Eric Brewer
查看>>
DLL,DML,DCL,TCL in Oracle
查看>>
android之存储篇_存储方式总览
查看>>
AngularJS 拦截器和应用例子(转)
查看>>
SSE指令集学习:Compiler Intrinsic
查看>>
两种attach to process的方法
查看>>
WCF如何使用X509证书(安装和错误)(二)
查看>>
遍历聚合对象中的元素——迭代器模式(二)
查看>>
Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
查看>>
iOS中--NSArray调用方法详解 (李洪强)
查看>>
java异步操作实例
查看>>