博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
根据twitter的snowflake算法生成唯一ID
阅读量:4475 次
发布时间:2019-06-08

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

C#版本

///     /// 根据twitter的snowflake算法生成唯一ID    /// snowflake算法 64 位    /// 0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000    /// 第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。    /// 其中datacenter标识位起始是机器位,机器ID其实是线程标识,可以同一一个10位来表示不同机器    ///     public class IdWorker    {        //机器ID        private static long workerId = 1;        private static long twepoch = 687888001020L; //唯一时间,这是一个避免重复的随机量,自行设定不要大于当前时间戳        private static long sequence = 0L;        private static int workerIdBits = 4; //机器码字节数。4个字节用来保存机器码        public static long maxWorkerId = -1L ^ -1L << workerIdBits; //最大机器ID        private static int sequenceBits = 10; //计数器字节数,10个字节用来保存计数码        private static int workerIdShift = sequenceBits; //机器码数据左移位数,就是后面计数器占用的位数        private static int timestampLeftShift = sequenceBits + workerIdBits; //时间戳左移动位数就是机器码和计数器总字节数        public static long sequenceMask = -1L ^ -1L << sequenceBits; //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成        private long lastTimestamp = -1L;        public long nextId()        {            lock (this)            {                long timestamp = timeGen();                if (this.lastTimestamp == timestamp)                { //同一微妙中生成ID                    IdWorker.sequence = (IdWorker.sequence + 1) & IdWorker.sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限                    if (IdWorker.sequence == 0)                    {                        //一微妙内产生的ID计数已达上限,等待下一微妙                        timestamp = tillNextMillis(this.lastTimestamp);                    }                }                else                { //不同微秒生成ID                    IdWorker.sequence = 0; //计数清0                }                if (timestamp < lastTimestamp)                { //如果当前时间戳比上一次生成ID时时间戳还小,抛出异常,因为不能保证现在生成的ID之前没有生成过                    throw new Exception(string.Format("Clock moved backwards.  Refusing to generate id for {0} milliseconds",                        this.lastTimestamp - timestamp));                }                this.lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳                long nextId = (timestamp - twepoch << timestampLeftShift) | IdWorker.workerId << IdWorker.workerIdShift | IdWorker.sequence;                return nextId;            }        }        ///         /// 获取下一微秒时间戳        ///         ///         /// 
private long tillNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } /// /// 生成当前时间戳 /// ///
private long timeGen() { return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds; } }

 

JAVA版本

 

import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;public class IdWorker {    protected static final Logger LOG = LoggerFactory.getLogger(IdWorker.class);    private long workerId;    private long datacenterId;    private long sequence = 0L;    private long twepoch = 1288834974657L;    private long workerIdBits = 5L;    private long datacenterIdBits = 5L;    private long maxWorkerId = -1L ^ (-1L << workerIdBits);    private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);    private long sequenceBits = 12L;    private long workerIdShift = sequenceBits;    private long datacenterIdShift = sequenceBits + workerIdBits;    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;    private long sequenceMask = -1L ^ (-1L << sequenceBits);    private long lastTimestamp = -1L;    public IdWorker(long workerId, long datacenterId) {        // sanity check for workerId        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;        LOG.info(String.format("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d", timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId));    }    public synchronized long nextId() {        long timestamp = timeGen();        if (timestamp < lastTimestamp) {            LOG.error(String.format("clock is moving backwards.  Rejecting requests until %d.", lastTimestamp));            throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));        }        if (lastTimestamp == timestamp) {            sequence = (sequence + 1) & sequenceMask;            if (sequence == 0) {                timestamp = tilNextMillis(lastTimestamp);            }        } else {            sequence = 0L;        }        lastTimestamp = timestamp;        return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;    }    protected long tilNextMillis(long lastTimestamp) {        long timestamp = timeGen();        while (timestamp <= lastTimestamp) {            timestamp = timeGen();        }        return timestamp;    }    protected long timeGen() {        return System.currentTimeMillis();    }}

 

 

 
 

转载于:https://www.cnblogs.com/soundcode/p/7199356.html

你可能感兴趣的文章
什么是敏捷设计
查看>>
.NET中栈和堆的比较
查看>>
如何优化limit
查看>>
几种常用数据库字段类型查询语句
查看>>
Java判断语句中判断条件的执行顺序
查看>>
Windows平台下tomcat+java的web程序持续占cpu问题调试
查看>>
Content Server HA搭建
查看>>
[leetCode]Linked List Cycle I+II
查看>>
leetcode中的python学习
查看>>
Zookeeper zkui-zookeeper图形化管理工具
查看>>
CenOS+宝塔(模拟)上线博客项目
查看>>
接口,lambda表达式与内部类(二)
查看>>
Phabricator是什么,代码审查工具
查看>>
DirectX:函数可以连接任意两个filter 分类: Direct...
查看>>
算法:求从1到n这n个整数的十进制表示中1出现的次数-- python 实现
查看>>
CSU 1160 把十进制整数转换为十六进制,格式为0x开头,10~15由大写字母A~F表示
查看>>
WinPE启动U盘的制作方法与软件下载(通用PE工具箱/老毛桃/大白菜WinPE)(转载)...
查看>>
PMP学习感想
查看>>
集合-强大的集合工具类:java.util.Collections中未包含的集合工具
查看>>
CSS清除浮动
查看>>