解析snowflake 算法生成的id 中时间、数据中心id 、机器编号、毫秒内序列

数据中主键有多种方式:数据库自增、程序生成。程序生成一般采用的是snowflake 算法。这个算法在网上有很多解释,这里就不做过多的解释。

生成的id大致有以下组成:

Snowflake算法一般生成的每一个ID都是64位的整型数,它的核心算法也比较简单高效,结构如下:

  • 41位的时间序列,精确到毫秒级,41位的长度可以使用69年。时间位还有一个很重要的作用是可以根据时间进行排序。

  • 5位的数据中心标识,5位的长度最多支持部署32个节点。

  • 8位的机器标识,8位的长度最多支持部署255个节点。

  • 12位的计数序列号,序列号即一系列的自增id,可以支持同一节点同一毫秒生成多个ID序号,12位的计数序列号支持每个节点每毫秒产生4095个ID序号。

  • 最高位是符号位,始终为0,不可用。

根据生成规则和实际代码:
(有关算法详解:https://segmentfault.com/a/1190000011282426#articleHeader2

return ((timestamp - 1288834974657) << 25) |
            (datacenterId << 20) |
            (workerId << 12) |
            sequence;

那么我们将生成的id (503565670412513280)转换为2进制:

11011111101000001100100111100101010000001001111000000000000

将其进行拆分

1101111110100001110010000011011001 00000 00010001 000000000000

然后在将各个位置的二进制编码转换为10进制就ok

实例代码:

public JSONObject parseInfo(String id) {
    id = Long.toBinaryString(Long.parseLong(id));
    int len = id.length();
    JSONObject jsonObject = new JSONObject();
    int sequenceStart = len < workerIdShift ? 0 : len - workerIdShift;
    int workerStart = len < dataCenterIdShift ? 0 : len - dataCenterIdShift;
    int timeStart = len < timestampLeftShift ? 0 : len - timestampLeftShift;
    String sequence = id.substring(sequenceStart, len);
    String workerId = sequenceStart == 0 ? "0" : id.substring(workerStart, sequenceStart);
    String dataCenterId = workerStart == 0 ? "0" : id.substring(timeStart, workerStart);
    String time = timeStart == 0 ? "0" : id.substring(0, timeStart);
    int sequenceInt = Integer.valueOf(sequence, 2);
    jsonObject.put("sequence", sequenceInt);
    int workerIdInt = Integer.valueOf(workerId, 2);
    jsonObject.put("workerId", workerIdInt);
    int dataCenterIdInt = Integer.valueOf(dataCenterId, 2);
    jsonObject.put("dataCenter", dataCenterIdInt);
    long diffTime = Long.parseLong(time, 2);
    long timeLong = diffTime + startTime;
    String date = DateUtil.formatTime(null, timeLong);
    jsonObject.put("date", date);
    return jsonObject;
}

完整代码:
https://gitee.com/jiangzeyin/dbutil/blob/master/src/main/java/cn/jiangzeyin/sequence/impl/IdSequence.java

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值