文档章节

IT技术:唯一ID高效率生成方式

Mison
 Mison
发布于 2015/08/11 19:08
字数 708
阅读 130
收藏 5

    这个唯一ID生成器,是Twitter公开的一个算法,源码是用Scala写的,被国内的开源爱好者改写成了Java版本。

    很多情况下只有一个节点作为ID号的生成器,所以这里workerIddatacenterId都设为0,当前时间与计算标记时间twepochThu, 04 Nov 2010 01:42:54 GMT)之间的毫秒数是一个38位长度的long值,再左移timestampLeftShift22位),就得到一个60位长度的long数字,该数字与datacenterId << datacenterIdShift取或,datacenterId最小值为0,最大值为31,所以长度为1-5位,datacenterIdShift17位,所以结果就是最小值为0,最大值为22位长度的long,同理,workerId << workerIdShift的最大值为17位的long。所以最终生成的会是一个60位长度的long型唯一ID。

    需要注意的是,该值只是一个唯一值,但并不能保证会是一个顺序值,就是说两个ID之间可能会跳一些数字,所以对于一些有特殊需求的业务来说请注意这个差异。

    具体的代码实现如下:

    /**
 * 全局唯一ID生成器
 
*/
public class IdGen {

    private long workerId;
    private long datacenterId;
    private long sequence = 0L;
    private long twepoch = 1288834974657L; //Thu, 04 Nov 2010 01:42:54 GMT
    private long workerIdBits = 5L; //节点ID长度
    private long datacenterIdBits = 5L; //数据中心ID长度
    private long maxWorkerId = -1L ^ (-1L << workerIdBits); //最大支持机器节点数0~31,一共32个
    private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); //最大支持数据中心节点数0~31,一共32个
    private long sequenceBits = 12L; //序列号12位
    private long workerIdShift = sequenceBits; //机器节点左移12位
    private long datacenterIdShift = sequenceBits + workerIdBits; //数据中心节点左移17位
    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; //时间毫秒数左移22位
    private long sequenceMask = -1L ^ (-1L << sequenceBits);
    private long lastTimestamp = -1L;
    
    private static class IdGenHolder {
        private static final IdGen instance = new IdGen();
    }
    
    public static IdGen get(){
        return IdGenHolder.instance;
    }

    public IdGen() {
        this(0L, 0L);
    }

    public IdGen(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;
    }
    
    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) {
            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();
    }
}

本文转载自:http://www.blogjava.net/bolo/archive/2015/07/13/426200.html

共有 人打赏支持
Mison
粉丝 0
博文 4
码字总数 1455
作品 0
海淀
私信 提问
OSC 第 94 期高手问答 —— 分布式 ID 生成策略

OSCHINA 本期高手问答( 10月20日- 10月26日) 我们请来了 @Burn1ng1ce 为大家解答关于 分布式 ID 生成策略 方面的问题。 廖雄杰,@Burn1ng1ce ,现在担任听云研发副总裁、架构师,是资深 Java...

叶秀兰
2015/10/19
10.4K
55
【死磕Sharding-jdbc】—–分布式ID

原文作者:阿飞Javaer 原文链接:https://www.jianshu.com/p/7f0661ddd6dd 实现动机 传统数据库软件开发中,主键自动生成技术是基本需求。而各大数据库对于该需求也提供了相应的支持,比如M...

飞哥-Javaer
2018/05/05
0
0
分布式唯一ID极简教程

一,题记 所有的业务系统,都有生成ID的需求,如订单id,商品id,文章ID等。这个ID会是数据库中的唯一主键,在它上面会建立聚集索引! 阅读本文,建议大家已经掌握了扎实的互联网技术,可参考...

架构师小秘圈
2017/11/24
0
0
分布式ID生成器的解决方案总结

在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID、退款ID等。那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决...

Java技术栈
2018/01/11
0
0
SEQSVR:Go + MySQL 实现的高性能 ID 生成服务

SEQSVR Go + MySQL 实现的 ID 生成服务 特性 分布式:可任意横向扩展 高性能:分配 ID 只访问内存(到达上限会请求数据库一次) 易用性:对外提供 HTTP 服务 唯一性:MySQL 自增 ID,永不重复 ...

qichengzx
2018/07/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JS 调用Angularjs 的方法

// 1. 获取 Controllerlet appElement = document.querySelector('[data-ng-controller=MessagesCtrl]');let scope = angular.element(appElement).scope();// 2. 调用方法scope.l......

Moks角木
29分钟前
1
0
dubbo+zookeeper与 eureka的区别

CAP CAP 原则指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得 在分布式架构里, P必须有 Zookeeper保证C P 当...

群星纪元
38分钟前
2
0
云计算之边缘计算大势所趋

如果说边缘计算是公同认定的目标,那么我们看到,不同类型的厂商基于自身的特点,会从不同的起点、沿着不同的路径,向这个目标奔跑。上次参加阿里云的一次活动,看到他们将边缘计算的厂商分成...

linuxCool
43分钟前
0
0
前端通过后端传过来的'\n' ,''等字符串换行失败问题

后台推送换行符 '\n' 或 '<br/>' 等字符串到前台不会换行 详细描述 后台逻辑处理返回String字符串,其中包含\n或<br/>等换行符号,但是前端渲染时候却并没有真正的换行 也尝试了大佬的各种 ...

下次用oschina
50分钟前
2
0
volatile能保证有序性吗?

在前面提到volatile关键字能禁止指令重排序,所以volatile能在一定程度上保证有序性。   volatile关键字禁止指令重排序有两层意思:   1)当程序执行到volatile变量的读操作或者写操作时...

无精疯
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部