雪花算法生成的主键存在哪些问题,为什么不能使用自增ID或者UUID做MySQL的主键

news2025/4/3 4:51:24

MySQL 分布式架构中的主键选择:自增ID、UUID与雪花算法

为什么MySQL分布式架构中不能使用自增主键?

在分布式架构中,自增主键存在以下问题:

  1. 主键冲突风险:多个数据库实例同时生成自增主键会导致ID重复
  2. 分片不均匀
    • 采用范围分片时会出现"尾部热点"现象,压力集中在某个分片
    • 无法实现负载均衡,新数据只能写入当前分片
  3. 数据合并困难:合并多个数据库时,自增主键会重复
  4. 性能瓶颈:自增锁在高并发场景下会成为性能瓶颈
  5. 安全性问题:自增ID容易被猜测,可能被用于恶意爬取数据

UUID作为主键的优缺点

优点

全局唯一性:几乎可以保证全球范围内的唯一性
分布式友好:无需协调即可在不同节点生成
安全性:随机生成的UUID难以被猜测

缺点

存储空间大:16字节(128位),是自增ID(通常4字节)的4倍
索引性能差
• 无序插入导致B+树频繁分裂和平衡
• 增加索引大小,降低缓存命中率
可读性差:长字符串形式不利于人工识别和调试
碎片化问题:随机插入导致磁盘碎片化

MySQL 8.0优化:可使用UUID_TO_BIN函数将UUID转换为16字节二进制并排序,性能接近自增ID

雪花算法(SnowFlake)详解

原理

雪花算法生成64位长整型ID,结构如下:

0 | 0000000 00000000 00000000 00000000 00000000 | 00000 | 00000 | 00000000 0000
  1. 1位符号位:固定为0(正数)
  2. 41位时间戳:毫秒级时间,可用69年(从1970算起)
  3. 10位机器标识
    • 5位数据中心ID(32个可能值)
    • 5位工作机器ID(32个可能值)
  4. 12位序列号:同一毫秒内的计数器(4096个值/ms/机器)

优势

  1. 全局唯一:通过时间戳+机器ID+序列号组合保证
  2. 有序递增:基于时间戳,有利于索引和排序
  3. 高性能:本地生成,每秒可生成数百万ID
  4. 不依赖第三方:算法简单,内存中完成
  5. 分布式友好:支持最多1024个节点(10位机器标识)

不足与解决方案

  1. 时钟回拨问题
    问题:服务器时间被调回导致重复ID
    解决方案
    ◦ 直接抛出异常,停止服务
    ◦ 记录最近时间戳,回拨时等待
    ◦ 使用扩展位记录时钟序列(3位时钟序列+7位机器ID)
    ◦ 采用Leaf、UidGenerator等改进方案

  2. 机器ID限制
    问题:10位仅支持1024个节点
    解决方案
    ◦ 预分配ID(适合固定节点)
    ◦ 动态分配(使用Redis/Zookeeper存储ID)
    ◦ 扩展位数(牺牲部分时间戳或序列号位)

  3. 时间戳耗尽
    问题:41位时间戳约69年后耗尽
    解决方案:调整起始时间(如使用系统上线时间而非1970)

代码示例(Java)

public class SnowflakeIdGenerator {
    private final long twepoch = 1577836800000L; // 自定义起始时间(2020-01-01)
    private final long workerIdBits = 5L;
    private final long datacenterIdBits = 5L;
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    private final long sequenceBits = 12L;
    private final long workerIdShift = sequenceBits;
    private final long datacenterIdShift = sequenceBits + workerIdBits;
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);

    private long workerId;
    private long datacenterId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeIdGenerator(long workerId, long datacenterId) {
        // 参数校验
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }

    public synchronized long nextId() {
        long timestamp = timeGen();
        // 处理时钟回拨
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards");
        }
        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;
    }
    // 其他辅助方法...
}

总结对比

特性自增IDUUID雪花算法
唯一性单机唯一全局唯一全局唯一
有序性严格有序完全无序时间有序
存储空间4-8字节16字节8字节
分布式支持不支持支持支持
生成方式数据库生成应用生成应用生成
性能影响自增锁瓶颈索引分裂时钟依赖
适用场景单机MySQL简单分布式系统高并发分布式系统

推荐选择
• 单机系统:自增ID
• 简单分布式系统:MySQL 8.0的有序UUID
• 高并发分布式系统:雪花算法或其改进版(如Leaf)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2326965.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBean模块(二)bean初始化(2)和容器初始化顺序的比较--引入ApplicationContextInitializer

前面介绍了获取容器可以让spring bean实现ApplicationContextAware&#xff0c;实际也是初始化执行了setApplicationContext接口&#xff0c; 初始化接口还可以借助一些注解或者spring bean的初始化方法&#xff0c;那么他们的执行顺序是什么样的呢&#xff1f; 一、验证&…

【分享】内外网文件摆渡系统:让数据传输更安全更可靠

【分享】Ftrans内外网文件摆渡系统&#xff1a;让数据传输更安全更可靠&#xff01; 随着大数据时代的到来&#xff0c;数据的重要性日渐得到重视&#xff0c;数据作为数字经济时代下的基础性资源和战略性资源&#xff0c;是决定国家经济发展水平和竞争力的核心驱动力。以行业…

2025年江苏省职业院校技能大赛 (高职组)大数据应用开发赛项任务书 (样题)

2025年江苏省职业院校技能大赛 &#xff08;高职组&#xff09;大数据应用开发赛项任务书 &#xff08;样题&#xff09; 背景描述&#xff1a;任务A&#xff1a;离线数据处理&#xff08;35分&#xff09;子任务一&#xff1a;数据抽取子任务三&#xff1a;指标计算 任务B&…

手机显示5GA图标的条件

最近有星友问在什么情况下才能显示5G-A&#xff1f;虽然这个我也不知道&#xff0c;但是我有几个运营商的5G终端白皮书&#xff0c;从上面就可以找到答案。 如上是几个运营商显示5G-A的条件&#xff0c;基本上考虑的都是3CC的情况&#xff0c;联通还有考虑200M CA 2CC的场景&am…

Spring Boot 实现文件秒传功能

前言 在开发Web应用时&#xff0c;文件上传是一个常见需求。然而&#xff0c;当用户需要上传大文件或相同文件多次时&#xff0c;会造成带宽浪费和服务器存储冗余。此时可以使用文件秒传技术通过识别重复文件&#xff0c;实现瞬间完成上传的效果&#xff0c;大大提升了用户体验…

使用AOP技术实现Java通用接口验签工具

一、背景 在给第三方提供接口时,我们需要对接口进行验签。具体来说,当外部系统调用我们的接口时,请求中需要携带一个签名,我们接收到请求后,会解析数据并校验签名是否正确,以确保请求的合法性和安全性。 为了在不同项目中方便地使用这一功能,我们将签名校验规则封装成一…

aarch64-none-elf-gcc与aarch64-linux-gnu-gcc

1. 场景描述 在Ubuntu 24.04.1 LTS x86_64架构下交叉编译能跑在aarch64架构下裸机程序&#xff0c;遇到缺aarch64-none-elf-gcc的情况&#xff0c;做此记录。 2. aarch64-none-elf-gcc与aarch64-linux-gnu-gcc 运行环境 aarch64-none-elf-gcc 生成的代码是 裸机程序&#xf…

【清华大学】DeepSeek政务应用场景与解决方案

目录 一、政务数字化转型三阶段演进二、人工智能政务应用场景四大方向 三、技术方案核心技术 四、解决方案案例1. 公文写作2. 合同协议智能审查3. 行政执法4. 就业指导 五、风险及对策六、落地大四步法七、未来发展展望AI职业替代逻辑空间智能与具身智能人机共生 一、政务数字化…

4.2 单相机引导机器人放料-仅考虑角度变化

【案例说明】 本案例产品在托盘中,角度变化不大(<15度);抓取没有问题,只是放的穴位只能容许3度的角度偏差,因此需要测量产品的角度。 思路是:机器人抓料后、去固定拍照位拍照(找到与标准照片的角度偏差),机器人在放料的位置上多旋转这个角度偏差,把产品放进去。 …

论文阅读笔记:Denoising Diffusion Implicit Models (3)

0、快速访问 论文阅读笔记&#xff1a;Denoising Diffusion Implicit Models &#xff08;1&#xff09; 论文阅读笔记&#xff1a;Denoising Diffusion Implicit Models &#xff08;2&#xff09; 论文阅读笔记&#xff1a;Denoising Diffusion Implicit Models &#xff08…

Git(八)如何在同一台电脑登录两个Git

目录 一、理解 SSH 密钥机制二、具体实现步骤1.删除GIT全局配置2.生成多个 SSH 密钥3.添加公钥到 Git 账户4.配置 SSH config 文件5.测试SSH key是否生效6.下载代码 三、Git仓库级别配置四、HTTPS方式的多账号管理 引言&#xff1a; 在日常开发中&#xff0c;我们经常会遇到需要…

如何改电脑网络ip地址:一步步指导

有时我们需要更改电脑的网络IP地址以满足特定的网络需求。本文将为您提供一份详细的步骤指南&#xff0c;帮助您轻松完成电脑网络IP地址的更改。以下是更改计算机IP地址的分步指南&#xff0c;适用于常见的操作系统&#xff1a; 一、更换内网ip Windows 系统&#xff08;Win10…

PyTorch 分布式训练(Distributed Data Parallel, DDP)简介

PyTorch 分布式训练&#xff08;Distributed Data Parallel, DDP&#xff09; 一、DDP 核心概念 torch.nn.parallel.DistributedDataParallel 1. DDP 是什么&#xff1f; Distributed Data Parallel (DDP) 是 PyTorch 提供的分布式训练接口&#xff0c;DistributedDataPara…

【Unity】记录TMPro使用过程踩的一些坑

1、打包到webgl无法输入中文&#xff0c;编辑器模式可以&#xff0c;但是webgl不行&#xff0c;试过网上的脚本&#xff0c;还是不行 解决方法&#xff1a;暂时没找到 2、针对字体asset是中文时&#xff0c;overflow的效果模式处理奇怪&#xff0c;它会出现除了overflow模式以…

计算机视觉初步(环境搭建)

1.anaconda 建议安装在D盘&#xff0c;官网正常安装即可&#xff0c;一般可以安装windows版本 安装成功后&#xff0c;可以在电脑应用里找到&#xff1a; 2.创建虚拟环境 打开anaconda prompt&#xff0c; 可以用conda env list 查看现有的环境&#xff0c;一般打开默认bas…

基于聚类与引力斥力优化的选址算法

在众多实际场景中&#xff0c;诸如消防设施选址、基站布局规划以及充电桩站点部署等&#xff0c;都面临着如何利用最少的资源&#xff0c;实现对所有目标对象全面覆盖的难题。为有效解决这类问题&#xff0c;本文提出一种全新的组合算法模型 —— 基于聚类与引力斥力优化的选址…

Mac 电脑移动硬盘无法识别的解决方法

在使用 Mac 电脑的过程中&#xff0c;不少用户都遇到过移动硬盘没有正常推出&#xff0c;导致无法识别的问题。这不仅影响了数据的传输&#xff0c;还可能让人担心硬盘内数据的安全。今天&#xff0c;我们就来详细探讨一下针对这一问题的解决方法。 当发现移动硬盘无法识别时&…

LeetCode Hot100 刷题笔记(4)—— 二叉树、图论

目录 一、二叉树 1. 二叉树的深度遍历&#xff08;DFS&#xff1a;前序、中序、后序遍历&#xff09; 2. 二叉树的最大深度 3. 翻转二叉树 4. 对称二叉树 5. 二叉树的直径 6. 二叉树的层序遍历 7. 将有序数组转换为二叉搜索树 8. 验证二叉搜索树 9. 二叉搜索树中第 K 小的元素 …

【计算机视觉】YOLO语义分割

一、语义分割简介 1. 定义 语义分割&#xff08;Semantic Segmentation&#xff09;是计算机视觉中的一项任务&#xff0c;其目标是对图像中的每一个像素赋予一个类别标签。与目标检测只给出目标的边界框不同&#xff0c;语义分割能够在像素级别上区分不同类别&#xff0c;从…

【SpringBoot + MyBatis + MySQL + Thymeleaf 的使用】

目录&#xff1a; 一&#xff1a;创建项目二&#xff1a;修改目录三&#xff1a;添加配置四&#xff1a;创建数据表五&#xff1a;创建实体类六&#xff1a;创建数据接口七&#xff1a;编写xml文件八&#xff1a;单元测试九&#xff1a;编写服务层十&#xff1a;编写控制层十一…