浩鲸科技:为什么要用雪花ID替代数据库自增ID?(转载)

2024-01-04

浩鲸科技的面试题如下:

image.png

其他面试题相对来说比较简单,大部人题目都可以在我的网站上( www.javacn.site)找到答案,这里就不再赘述,咱们今天只聊“为什么要使用雪花 ID 替代数据库自增 ID?”这个问题。

1.什么是雪花 ID?

雪花 ID(Snowflake ID)是一个用于分布式系统中生成唯一 ID 的算法,由 Twitter 公司提出。它的设计目标是在分布式环境下高效地生成全局唯一的 ID,具有一定的有序性。

雪花 ID 的结构如下所示:

image.png

这四部分代表的含义

  1. 符号位 :最高位是符号位,始终为 0,1 表示负数,0 表示正数,ID 都是正整数,所以固定为 0。
  2. 时间戳部分 :由 41 位组成,精确到毫秒级。可以使用该 41 位表示的时间戳来表示的时间可以使用 69 年。
  3. 节点 ID 部分 :由 10 位组成,用于表示机器节点的唯一标识符。在同一毫秒内,不同的节点生成的 ID 会有所不同。
  4. 序列号部分 :由 12 位组成,用于标识同一毫秒内生成的不同 ID 序列。在同一毫秒内,可以生成 4096 个不同的 ID。

2.Java 版雪花算法实现

接下来,我们来实现一个 Java 版的雪花算法:


  

java

public class SnowflakeIdGenerator {
  
  // 定义雪花 ID 的各部分位数
  private static final long TIMESTAMP_BITS = 41L;
  private static final long NODE_ID_BITS = 10L;
  private static final long SEQUENCE_BITS = 12L;

  // 定义起始时间戳(可根据实际情况调整)
  private static final long EPOCH = 1609459200000L;

  // 定义最大取值范围
  private static final long MAX_NODE_ID = (1L << NODE_ID_BITS) - 1;
  private static final long MAX_SEQUENCE = (1L << SEQUENCE_BITS) - 1;

  // 定义偏移量
  private static final long TIMESTAMP_SHIFT = NODE_ID_BITS + SEQUENCE_BITS;
  private static final long NODE_ID_SHIFT = SEQUENCE_BITS;

  private final long nodeId;
  private long lastTimestamp = -1L;
  private long sequence = 0L;

  public SnowflakeIdGenerator(long nodeId) {
    if (nodeId < 0 || nodeId > MAX_NODE_ID) {
      throw new IllegalArgumentException("Invalid node ID");
    }
    this.nodeId = nodeId;
  }

  public synchronized long generateId() {
    long currentTimestamp = timestamp();
    if (currentTimestamp < lastTimestamp) {
        throw new IllegalStateException("Clock moved backwards");
    }
    if (currentTimestamp == lastTimestamp) {
      sequence = (sequence + 1) & MAX_SEQUENCE;
      if (sequence == 0) {
        currentTimestamp = untilNextMillis(lastTimestamp);
      }
    } else {
      sequence = 0L;
    }
    lastTimestamp = currentTimestamp;
    return ((currentTimestamp - EPOCH) << TIMESTAMP_SHIFT) |
           (nodeId << NODE_ID_SHIFT) |
           sequence;
  }

  private long timestamp() {
    return System.currentTimeMillis();
  }

  private long untilNextMillis(long lastTimestamp) {
    long currentTimestamp = timestamp();
    while (currentTimestamp <= lastTimestamp) {
      currentTimestamp = timestamp();
    }
    return currentTimestamp;
  }
}

调用代码如下:


  

java

public class Main {
  public static void main(String[] args) {
    // 创建一个雪花 ID 生成器实例,传入节点 ID
    SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1);
    // 生成 ID
    long id = idGenerator.generateId();
    System.out.println(id);
  }
}

其中,nodeId 表示当前节点的唯一标识,可以根据实际情况进行设置。generateId 方法用于生成雪花 ID,采用同步方式确保线程安全。具体的生成逻辑遵循雪花 ID 的位运算规则,结合当前时间戳、节点 ID 和序列号生成唯一的 ID。

需要注意的是,示例中的时间戳获取方法使用了 System.currentTimeMillis(),根据实际需要可以替换为其他更精确的时间戳获取方式。同时,需要确保节点 ID 的唯一性,避免不同节点生成的 ID 重复。

3.雪花算法问题

虽然雪花算法是一种被广泛采用的分布式唯一 ID 生成算法,但它也存在以下几个问题:

  1. 时间回拨问题 :雪花算法生成的 ID 依赖于系统的时间戳,要求系统的时钟必须是单调递增的。如果系统的时钟发生回拨,可能导致生成的 ID 重复。时间回拨是指系统的时钟在某个时间点之后突然往回走(人为设置),即出现了时间上的逆流情况。
  2. 时钟回拨带来的可用性和性能问题 :由于时间依赖性,当系统时钟发生回拨时,雪花算法需要进行额外的处理,如等待系统时钟追上上一次生成 ID 的时间戳或抛出异常。这种处理会对算法的可用性和性能产生一定影响。
  3. 节点 ID 依赖问题 :雪花算法需要为每个节点分配唯一的节点 ID 来保证生成的 ID 的全局唯一性。节点 ID 的分配需要有一定的管理和调度,特别是在动态扩容或缩容时,节点 ID 的管理可能较为复杂。

4.如何解决时间回拨问题?

百度 UidGenerator 框架中解决了时间回拨的问题,并且解决方案比较经典,所以咱们这里就来给大家分享一下百度 UidGenerator 是怎么解决时间回拨问题的?

UidGenerator 介绍 :UidGenerator 是百度开源的一个分布式唯一 ID 生成器,它是基于 Snowflake 算法的改进版本。与传统的 Snowflake 算法相比,UidGenerator 在高并发场景下具有更好的性能和可用性。它的实现源码在: github.com/baidu/uid-g…

UidGenerator 是这样解决时间回拨问题的:UidGenerator 的每个实例中,都维护一个本地时钟缓存,用于记录当前时间戳。这个本地时钟会定期与系统时钟进行同步,如果检测到系统时钟往前走了(出现了时钟回拨),则将本地时钟调整为系统时钟。

4.为什么要使用雪花 ID 替代数据库自增 ID?

数据库自增 ID 只适用于单机环境,但如果是分布式环境,是将数据库进行分库、分表或数据库分片等操作时,那么数据库自增 ID 就有问题了。

例如,数据库分片之后,会在同一张业务表的分片数据库中产生相同 ID(数据库自增 ID 是由每个数据库单独记录和增加的),这样就会导致,同一个业务表的竟然有相同的 ID,而且相同 ID 背后存储的数据又完全不同,这样业务查询的时候就出问题了。

所以为了解决这个问题,就必须使用分布式中能保证唯一性的雪花 ID 来替代数据库的自增 ID。

5.扩展:使用 UUID 替代雪花 ID 行不行?

如果单从唯一性来考虑的话,那么 UUID 和雪花 ID 的效果是一致的,二者都能保证分布式系统下的数据唯一性,但是即使这样,也 不建议使用 UUID 替代雪花 ID ,因为这样做的问题有以下两个:

  1. 可读性问题 :UUID 内容很长,但没有业务含义,就是一堆看不懂的“字母”。
  2. 性能问题 :UUID 是字符串类型,而字符串类型在数据库的查询中效率很低。

所以,基于以上两个原因,不建议使用 UUID 来替代雪花 ID。

小结

数据库自增 ID 只适用于单机数据库环境,而对于分库、分表、数据分片来说,自增 ID 不具备唯一性,所以要要使用雪花 ID 来替代数据库自增 ID。但雪花算法依然存在一些问题,例如时间回拨问题、节点过度依赖问题等,所以此时,可以使用雪花算法的改进框架,如百度的 UidGenerator 来作为数据库的 ID 生成方案会比较好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浩鲸科技:为什么要用雪花ID替代数据库自增ID?(转载) 的相关文章

  • 猫头虎博主的MySQL救援指南:轻松解决初始化问题(nysqld: Can create directort :mysgl mysg! 9-winx64 data errno such file o)

    博主猫头虎的技术世界 欢迎来到 猫头虎的博客 探索技术的无限可能 专栏链接 精选专栏 面试题大全 面试准备的宝典 IDEA开发秘籍 提升你的IDEA技能 100天精通Golang Go语言学习之旅 领域矩阵 猫头虎技术领域矩阵 深入探索各技
  • 【计算机开题报告】基于JAVA的酒店管理系统的设计与实现

    1 毕业设计 论文 综述 随着社会经济和科技的迅速发展 人们对衣食住行的要求也逐渐提高 酒店 宾馆在服务行业中扮演着越来越重要的角色 本课程设计的内容旨在以管理系统的方式给人们出行提供酒店预订服务 从而能够更方便快捷的帮助酒店工作人员办理客
  • 拓数派加入 OpenCloudOS 操作系统开源社区,作为成员单位参与社区共建

    近日 拓数派签署 CLA Contributor License Agreement 贡献者许可协议 正式加入 OpenCloudOS 操作系统开源社区 拓数派 英文名称 OpenPie 是国内基础数据计算领域的高科技创新企业 作为国内云上
  • MySQL中设置自增主键id从1开始

    可能遇到过这种问题 当你只想新增一条数据时 发现使用Insert语句后 发现id并不是从1开始的 握草 怎么回事 其实很简单 通过执行一下SQL 对应你的表就可以解决 ALTER TABLE user AUTO INCREMENT 1 具体
  • 【计算机开题报告】基于JSP的服装店销售管理系统

    1 选课目的意义 21世纪是一个信息化时代 随着中国经济的发展和人民生活水平的提高 服装商场的普及程度日益增大 竞争也在逐渐白炽化 为了进一步提高服装商场的经营效率 在服装店销售管理中引入计算机管理系统成为了必然的选择 由于中国环境的特殊性
  • 如何处理不稳定的自动化测试?

    abluecolor 在解决这个问题之前 请停止编写更多测试 因为这将花费你较高的测试维护成本 你需要尽快行动起来对不稳定的原因进行深入研究 找到不稳定的根因 并且尝试在流程 环境和代码方面做一些优化工作解决它 MasterKindew 如
  • 合肥一食品仓库发生火灾,富维图像仓库火灾识别避免财产损失

    2024年1月5日 安徽合肥一家食品仓库不幸遭遇了火灾 11时50分左右 浓烟滚滚 火光冲天 令人心惊肉跳 幸运的是 没有造成人员伤亡 但仓库内大量物资被烧毁 财产损失巨大 此次事件再次提醒我们 火灾防护的重要性不容忽视 而在这方面 北京富
  • Kali Linux 安全渗透核心总结,444页核心知识点

    就像IT人离不开Linux系统一样 网安人也离不开Kali Linux 作为攻击性防御和渗透测试的代名词 越来越多的人开始学习Kali 如果你也对kali感兴趣 又想深入了解这方面内容 不妨收藏一下这份Kali Linux安全渗透教程 共4
  • Qt源码分析:Qt程序是怎么运行起来的?

    一 从 exec 谈起 一个标准的Qt gui程序 在启动时我们会coding如下几行简洁的代码 include widget h include
  • 智能时代:自然语言生成SQL与知识图谱问答实战

    语义解析 前言 语义解析的应用场景 总结概论 语义解析和大模型的关系 延伸阅读 前言 语义解析技术可以提高人机交互的效率和准确性 在自然语言处理 数据分析 智能客服 智能家居等领域都有广泛的应用前景 特别是在大数据时代 语义解析能够帮助企业
  • 【Mysql】InnoDB 引擎中的页目录

    一 页目录和槽 现在知道记录在页中按照主键大小顺序串成了单链表 那么我使用主键查询的时候 最顺其自然的办法肯定是从第一条记录 也就是 Infrimum 记录开始 一直向后找 只要存在总会找到 这种在数据量少的时候还好说 一旦数据多了 遍历耗
  • Navicat 16 for MySQL:打造高效数据库开发管理工具

    随着数据的快速增长和复杂性的提升 数据库成为了现代应用开发中不可或缺的一部分 而在MySQL数据库领域 Navicat 16 for MySQL作为一款强大的数据库开发管理工具 正受到越来越多开发者的青睐 Navicat 16 for My
  • 【计算机毕业设计】基于web的山东红色旅游信息管理系统

    有效的处理想要的相关信息和如何传播有效的信息 一直是人类不断探索的动力 人类文明火种的传承都是通过了多种媒介作为载体 也是随着社会生产力的发展不断的更新 随着互联网的到来 信息传播与管理都上升了一个新的台阶 并且方便应用的同时也要考虑信息传
  • 【计算机毕业设计】校园体育赛事管理系统

    身处网络时代 随着网络系统体系发展的不断成熟和完善 人们的生活也随之发生了很大的变化 人们在追求较高物质生活的同时 也在想着如何使自身的精神内涵得到提升 而读书就是人们获得精神享受非常重要的途径 为了满足人们随时随地只要有网络就可以看书的要
  • 38条Web测试经验分享

    1 页面链接检查 每一个链接是否都有对应的页面 并且页面之间切换正确 可以使用一些工具 如LinkBotPro File AIDCS HTML Link Validater Xenu等工具 LinkBotPro不支持中文 中文字符显示为乱码
  • 深入了解 Python MongoDB 操作:排序、删除、更新、结果限制全面解析

    Python MongoDB 排序 对结果进行排序 使用 sort 方法对结果进行升序或降序排序 sort 方法接受一个参数用于 字段名 一个参数用于 方向 升序是默认方向 示例 按名称按字母顺序对结果进行排序 import pymongo
  • 【计算机毕业设计】电影播放平台

    电影播放平台采用B S架构 数据库是MySQL 网站的搭建与开发采用了先进的java进行编写 使用了springboot框架 该系统从两个对象 由管理员和用户来对系统进行设计构建 主要功能包括 个人信息修改 对用户 电影分类 电影信息等功能
  • 【计算机毕业设计】白优校园社团网站的设计与实现

    近些年 随着中国经济发展 人民的生活质量逐渐提高 对网络的依赖性越来越高 通过网络处理的事务越来越多 随着白优校园社团网站的常态化 如果依然采用传统的管理方式 将会为工作人员带来庞大的工作量 这将是一个巨大考验 需要投入大量人力开展对社团
  • 实力认证!鼎捷软件荣膺“领军企业”和“创新产品”两大奖项

    近日 由中国科学院软件研究所 中科软科技股份有限公司联合主办的 2023中国软件技术大会 于北京成功举办 本届大会以 大模型驱动下的软件变革 为主题 数十位来自知名互联网公司和软件巨头企业的技术大咖 不同领域行业专家 畅销书作者等分享嘉宾
  • SAP ERP系统是什么?SAP好用吗?

    A公司是一家传统制造企业 公司曾先后使用过数个管理软件系统 但各部门使用的软件都是单独功能 导致企业日常管理中数据流与信息流相对独立 形成了 信息孤岛 随着公司近年业务规模的快速发展以及客户数量的迅速增加 企业原有的信息系统在销售预测及生产

随机推荐