雪花算法:生成全局唯一 ID 的业务主键

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

雪花算法:生成全局唯一 ID 业务主键


前言

很多公司在开发数据库的时候,往往需要生成全局唯一的 ID 业务主键,方便进行不同表信息的匹配。

全局唯一 ID (或者称为分布式 ID 设计),常用的有:
1.使用 Mysql 的全局表
2.使用 Zookeeper 的有序节点
3.使用 MongoDB 的 objectid
4.redis 的自增 id
5.UUID
6.雪花算法等等

本文主要介绍的是基于 Twitter 早期开源的 Snowflake 雪花算法


一、算法简介

使用 Zookeeper 的有序节点、使用 MongoDB 的 objectid、redis 的自增 id、UUID 等这些方案只是解决基础的 ID 唯一性问题,但这些方案在具体应用的时候有其局限性。

雪花算法算是目前使用较多的算法,例如美团公司开源了一个全局唯一 id 生成系统 leaf,它里面也用到了雪花算法去构建全局唯一 id。

同时,雪花算法的性能比较好,Twitter 测试的峰值是 10 万个每秒。

二、雪花算法原理解析

雪花算法的本质是:根据生成规则,生成一个64位长度的 long 类型的数据

具体生成规则:64位bit被分为四个部分
1.符号位:占1个bit。一般来说,id不会是负数,因此一般符号位默认为0
2.毫秒单位的时间戳:占41个bit。
3.工作机器的id:10个bit。如果有多个机房,还可以将10个bit拆分为两个5bit位,第一个 5bit 位存放机房 id,第二个 5bit 位存放机器 id。
4.序列号:占12个bit,用来表示递增的序列号。

64位bit示意图如下:
在这里插入图片描述

更多详细内容可以参考:雪花算法(SnowFlake)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的雪花算法(Snowflake)可以用于生成唯一主键ID。下面是一个简单的实现示例: ```java public class SnowflakeIdGenerator { private final static long START_TIMESTAMP = 1614556800000L; // 设置起始时间戳,这里假设为2021-03-01 00:00:00 private final static long DATA_CENTER_ID_BITS = 5L; // 数据中心ID所占的位数 private final static long WORKER_ID_BITS = 5L; // 工作机器ID所占的位数 private final static long SEQUENCE_BITS = 12L; // 序列号所占的位数 private final static long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS); // 支持的最大数据中心ID数量 private final static long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS); // 支持的最大工作机器ID数量 private final static long WORKER_ID_SHIFT = SEQUENCE_BITS; // 工作机器ID左移位数 private final static long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS; // 数据中心ID左移位数 private final static long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS; // 时间戳左移位数 private final static long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS); // 序列号掩码 private long workerId; // 工作机器ID private long dataCenterId; // 数据中心ID private long sequence = 0L; // 序列号 private long lastTimestamp = -1L; // 上次生成ID的时间戳 public SnowflakeIdGenerator(long dataCenterId, long workerId) { if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) { throw new IllegalArgumentException("Data center ID can't be greater than " + MAX_DATA_CENTER_ID + " or less than 0"); } if (workerId > MAX_WORKER_ID || workerId < 0) { throw new IllegalArgumentException("Worker ID can't be greater than " + MAX_WORKER_ID + " or less than 0"); } this.dataCenterId = dataCenterId; this.workerId = workerId; } public synchronized long generateId() { long currentTimestamp = System.currentTimeMillis(); if (currentTimestamp < lastTimestamp) { throw new RuntimeException("Clock moved backwards. Refusing to generate ID for " + (lastTimestamp - currentTimestamp) + " milliseconds"); } if (currentTimestamp == lastTimestamp) { sequence = (sequence + 1) & SEQUENCE_MASK; if (sequence == 0) { currentTimestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; } lastTimestamp = currentTimestamp; return ((currentTimestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT) | (dataCenterId << DATA_CENTER_ID_SHIFT) | (workerId << WORKER_ID_SHIFT) | sequence; } private long tilNextMillis(long lastTimestamp) { long timestamp = System.currentTimeMillis(); while (timestamp <= lastTimestamp) { timestamp = System.currentTimeMillis(); } return timestamp; } } ``` 使用示例: ```java public class Main { public static void main(String[] args) { // 创建一个SnowflakeIdGenerator实例,传入数据中心ID和工作机器ID SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1); // 生成ID long id = idGenerator.generateId(); System.out.println("Generated ID: " + id); } } ``` 这样就可以使用雪花算法Java生成唯一主键ID了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值