• 分布式ID生成方案之雪花算法


    目录

    前言

    1、什么是分布式ID?

    2、雪花算法结构

    3、雪花算法的优势

    4、雪花算法的实现

    5、总结


    前言

    当我首次接触到这个算法时,便被其富有诗意的名字所吸引。雪花,亦称未央花,"未央"意味着永恒与无限,象征着希望与未来,代表着光明与前行的道路。言归正传,自然界中存在一种现象:据说不存在两片完全相同的雪花,每一片在形成时都会展现出其独特的形态与纹路。雪花算法这个名字,象征该算法能生成一个全局唯一且不重复的标识符。

    1、什么是分布式ID?

    分布式系统中,数据一般都被分散存储在不同的节点上,由于数据被分散存储在不同的节点上,为了确保每个数据项的唯一性,就需要这样一套机制来生成不会重复的ID。这个不会重复的ID就是分布式ID。

    分布式ID不仅仅是一个简单的数字序列,它还涉及到多个维度的需求和特性,主要包括:

    1. 全局唯一性:这是最基本也是最重要的要求,确保在分布式系统中产生的每一个ID都是独一无二的。

    2. 高性能:在高并发场景下,ID生成服务需要快速响应,减少生成ID的延迟,不影响系统的整体性能。

    3. 高可用性:ID生成服务需要设计成高可用的,即使部分组件发生故障,也能确保ID的正常生成,不影响业务连续性。

    4. 趋势递增(非严格要求):在某些场景下,如数据库索引优化,可能需要生成的ID具有趋势递增的特性,以便提升数据库插入性能。

    5. 安全性:虽然不是所有场景都需要,但在一些敏感或有特殊要求的系统中,ID的生成还应考虑信息安全性,避免通过ID泄露系统敏感信息。

    常见的分布式ID生成策略有Snowflake算法(就是我们今天的主角)、基于数据库的生成方式、基于Zookeeper或Redis等中间件的方案,以及使用UUID等。

    接下来我们就一起解开雪花算法的面纱吧。

    2、雪花算法结构

    雪花算法是Twitter开源的分布式ID生成算法,其生成的ID是一个64位的长整型数字。每个ID按时间顺序生成,并保证在分布式系统中的唯一性。雪花算法生成的ID结构如下:

    | 1位符号位 | 41位时间戳 | 10位机器ID | 12位序列号 |
    • 1位符号位:固定为0,表示生成的ID为正数。
    • 41位时间戳:以毫秒为单位的时间戳,表示从某个固定时间(Twitter Epoch)起的毫秒数,41位可以表示69年的时间。
    • 10位机器ID:用来表示不同的机器,5位数据中心ID和5位机器ID,最多支持1024个节点。
    • 12位序列号:同一毫秒内生成的不同ID的序列号,最多支持每毫秒产生4096个不同的ID。

    3、雪花算法的优势

    1. 高效性:雪花算法在本地生成ID,不需要依赖数据库等外部系统,生成速度极快。
    2. 全局唯一性:通过时间戳、机器ID和序列号的组合,保证了ID的唯一性。
    3. 有序性:生成的ID大致按照时间顺序排列,方便数据的排序和查询。
    4. 分布式支持:支持大规模分布式系统,每秒可以生成大量唯一ID。

    4、雪花算法的实现

    1. public class SnowflakeIdWorker {
    2. // 起始时间戳(2020-01-01)
    3. private final long twepoch = 1577836800000L;
    4. // 机器ID所占的位数
    5. private final long workerIdBits = 5L;
    6. private final long datacenterIdBits = 5L;
    7. // 支持的最大机器ID
    8. private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    9. private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    10. // 序列号所占的位数
    11. private final long sequenceBits = 12L;
    12. // 机器ID左移位数
    13. private final long workerIdShift = sequenceBits;
    14. private final long datacenterIdShift = sequenceBits + workerIdBits;
    15. private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    16. // 序列号掩码
    17. private final long sequenceMask = -1L ^ (-1L << sequenceBits);
    18. private long workerId;
    19. private long datacenterId;
    20. private long sequence = 0L;
    21. private long lastTimestamp = -1L;
    22. public SnowflakeIdWorker(long workerId, long datacenterId) {
    23. if (workerId > maxWorkerId || workerId < 0) {
    24. throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
    25. }
    26. if (datacenterId > maxDatacenterId || datacenterId < 0) {
    27. throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
    28. }
    29. this.workerId = workerId;
    30. this.datacenterId = datacenterId;
    31. }
    32. public synchronized long nextId() {
    33. long timestamp = timeGen();
    34. if (timestamp < lastTimestamp) {
    35. throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
    36. }
    37. if (lastTimestamp == timestamp) {
    38. sequence = (sequence + 1) & sequenceMask;
    39. if (sequence == 0) {
    40. timestamp = tilNextMillis(lastTimestamp);
    41. }
    42. } else {
    43. sequence = 0L;
    44. }
    45. lastTimestamp = timestamp;
    46. return ((timestamp - twepoch) << timestampLeftShift) |
    47. (datacenterId << datacenterIdShift) |
    48. (workerId << workerIdShift) |
    49. sequence;
    50. }
    51. protected long tilNextMillis(long lastTimestamp) {
    52. long timestamp = timeGen();
    53. while (timestamp <= lastTimestamp) {
    54. timestamp = timeGen();
    55. }
    56. return timestamp;
    57. }
    58. protected long timeGen() {
    59. return System.currentTimeMillis();
    60. }
    61. }

    5、总结

    雪花算法是一种高效、可靠的分布式ID生成方案,解决了在分布式系统中ID重复和生成效率的问题。通过时间戳、机器ID和序列号的组合,确保了ID的全局唯一性和有序性。在实际应用中,雪花算法被广泛用于订单系统、用户系统等需要唯一标识符的场景,是一种非常实用的分布式ID生成方案。

  • 相关阅读:
    Java集成支付宝沙箱支付,详细教程(SpringBoot完整版)
    第五章:Java中的方法和方法重载
    SQL - 四大分类(DDL、DML、DQL、DCL)详细介绍
    克拉默法则,逆矩阵,体积
    【OpenCV】VS编译器配置OpenCV库路径
    简单易懂的Spring核心流程介绍
    Outlook邮件视图设置怎么修复
    Redis学习记录------Redis6概述和安装(二)
    安徽某高校《数学建模》上机习题1选讲(建立范德蒙矩阵;解线性方程组)
    吹爆,阿里最新开源的这份Redis全栈小册,涵盖了Redis的所有操作
  • 原文地址:https://blog.csdn.net/weixin_44741471/article/details/139808650