跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
SQL算法

SQL Server 中生成雪花 ID(Snowflake ID) 的方法

SQL Server 中生成雪花 ID 的分布式唯一 ID 方案。介绍雪花 ID 结构特点及局限性,提供基于 T-SQL 函数和存储过程的实现方式,包含时间戳、节点 ID 及序列号处理,解决时钟回拨问题,适用于分布式系统主键生成场景。

CryptoLab发布于 2026/2/21更新于 2026/10/1587 浏览
SQL Server 中生成雪花 ID(Snowflake ID) 的方法

SQL Server 中生成雪花 ID

前言

在我的印象中用到这个雪花 ID 比较少,可能是我接触的大型项目或者开源项目比较少,同时接触到中大型分布式也比较少,基本都是自研系统,用的是自增 ID 和 GuidValue 作为唯一编号。 最近项目上使用了一套第三方框架代码,使用了雪花 ID 作为表的唯一主键,并且之前表没有这个字段,需要进行表迁移的同时初始化雪花 ID 字段值。 因此,趁这次机会简单总结下雪花 ID 以及在 Sql Server 上如何生成雪花 ID。

认识雪花 ID

雪花 ID 是 Twitter 开发的一种分布式唯一 ID 生成算法,主要用于在分布式系统中生成全局唯一的 ID 标识符。它的名称来源于"自然界中没有两片完全相同的雪花"这一概念,象征着每个生成的 ID 都是独一无二的。

雪花 ID 的核心特点

  1. 全局唯一性:在分布式系统中生成的 ID 不会重复
  2. 时间有序性:ID 按照时间顺序递增
  3. 高性能:本地生成,不依赖数据库等外部系统
  4. 可解析:ID 中包含的信息可以被解析出来

雪花 ID 的结构(64 位)

标准的雪花 ID 由以下三部分组成(共 64 位):

| 1 位符号位 | 41 位时间戳 | 10 位工作节点 ID | 12 位序列号 |

具体分解:

  1. 符号位(1 位):始终为 0,保证 ID 为正数
  2. 时间戳(41 位):毫秒级的时间戳,可以使用约 69 年
    • 通常从自定义纪元开始计算(如 Twitter 使用 2010-11-04 01:42:54 UTC)
  3. 工作节点 ID(10 位):
    • 通常分为 5 位数据中心 ID + 5 位机器 ID
    • 最多支持 32 个数据中心,每个数据中心 32 台机器
  4. 序列号(12 位):同一毫秒内的序列号,支持每毫秒生成 4096 个 ID

雪花 ID 的优势

  1. 分布式友好:不同节点可以独立生成 ID 而不需要协调
  2. 时间有序:生成的 ID 按时间递增,有利于数据库索引
  3. 高性能:本地生成,不依赖网络或数据库
  4. 信息丰富:ID 本身包含时间、节点等信息

雪花 ID 的局限性

  1. 时钟依赖:严重依赖系统时钟,时钟回拨会导致 ID 重复
  2. 节点 ID 配置:需要手动或通过外部系统分配节点 ID
  3. 时间耗尽:41 位时间戳大约 69 年后会耗尽

雪花 ID 的应用场景

  1. 分布式系统主键生成
  2. 订单号、交易号等业务编号
  3. 日志跟踪 ID
  4. 任何需要全局唯一且有序 ID 的场景

示例 ID 解析

假设一个雪花 ID:123456789012345678

转换为二进制后可以解析出:

  • 时间戳部分:可以转换为具体的生成时间
  • 工作节点部分:知道是在哪个数据中心哪台机器生成的
  • 序列号部分:知道这是该毫秒内生成的第几个 ID

雪花 ID 因其简单高效的特性,已经成为分布式系统 ID 生成的经典解决方案之一。

生成雪花 ID

雪花 ID 是 Twitter 提出的一种分布式 ID 生成算法,它生成 64 位的唯一 ID,通常包含时间戳、工作节点 ID 和序列号。 在 SQL Server 中可以通过以下几种方式实现雪花 ID 的生成:

使用 T-SQL 函数实现

-- 创建配置表
CREATE TABLE SnowflakeConfig (
    MachineId BIGINT NOT NULL,
    DatacenterId BIGINT NOT NULL,
    LastTimestamp BIGINT NOT NULL,
    Sequence BIGINT NOT NULL,
    CONSTRAINT PK_SnowflakeConfig PRIMARY KEY (MachineId, DatacenterId)
);
-- 初始化配置 (机器 ID 和数据中心 ID 需要在每个节点上配置不同)
INSERT INTO SnowflakeConfig (MachineId, DatacenterId, LastTimestamp, Sequence)
VALUES (1, 1, 0, 0);
-- 创建获取当前时间戳的函数
CREATE FUNCTION GetCurrentTimestamp()
RETURNS BIGINT
AS
BEGIN
    DECLARE @epoch DATETIME2 = '1970-01-01 00:00:00';
    DECLARE @now DATETIME2 = SYSUTCDATETIME();
    RETURN CAST(DATEDIFF_BIG(MILLISECOND, @epoch, @now) AS BIGINT);
END;
-- 创建等待下一毫秒的函数
CREATE FUNCTION ToNextMillis(@lastTimestamp BIGINT)
RETURNS BIGINT
AS
BEGIN
    DECLARE @timestamp BIGINT;
    SET @timestamp = dbo.GetCurrentTimestamp();
    WHILE @timestamp <= @lastTimestamp
    BEGIN
        SET @timestamp = dbo.GetCurrentTimestamp();
    END
    RETURN @timestamp;
END;
GO
-- 创建计算幂的函数(替代位移操作)
CREATE FUNCTION PowerOfTwo(@exponent BIGINT)
RETURNS BIGINT
AS
BEGIN
    RETURN CAST(POWER(CAST(2 AS FLOAT), @exponent) AS BIGINT);
END;
GO
-- 创建生成雪花 ID 的存储过程
CREATE PROCEDURE GenerateSnowflakeId 
    @MachineId BIGINT = 1,
    @DatacenterId BIGINT = 1,
    @SnowflakeId BIGINT OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    -- 常量定义
    DECLARE @Twepoch BIGINT = 1700058600000;
    DECLARE @MachineIdBits BIGINT = 5;
    DECLARE @DatacenterIdBits BIGINT = 5;
    DECLARE @SequenceBits BIGINT = 12;
    -- 使用 POWER 计算替代位移
    DECLARE @MaxMachineId BIGINT = dbo.PowerOfTwo(@MachineIdBits) - 1;
    DECLARE @MaxDatacenterId BIGINT = dbo.PowerOfTwo(@DatacenterIdBits) - 1;
    DECLARE @SequenceMask BIGINT = dbo.PowerOfTwo(@SequenceBits) - 1;
    DECLARE @MachineIdShift BIGINT = @SequenceBits;
    DECLARE @DatacenterIdShift BIGINT = @SequenceBits + @MachineIdBits;
    DECLARE @TimestampLeftShift BIGINT = @SequenceBits + @MachineIdBits + @DatacenterIdBits;
    
    -- 验证参数
    IF @MachineId > @MaxMachineId OR @MachineId < 0
    BEGIN
        THROW 50000, 'MachineId can''t be greater than maxMachineId or less than 0', 1;
        RETURN;
    END
    IF @DatacenterId > @MaxDatacenterId OR @DatacenterId < 0
    BEGIN
        THROW 50000, 'DatacenterId can''t be greater than maxDatacenterId or less than 0', 1;
        RETURN;
    END
    
    -- 使用事务确保原子性
    BEGIN TRANSACTION;
    BEGIN TRY
        DECLARE @LastTimestamp BIGINT;
        DECLARE @Sequence BIGINT;
        DECLARE @Timestamp BIGINT;
        
        -- 获取当前状态
        SELECT @LastTimestamp = LastTimestamp, @Sequence = Sequence 
        FROM SnowflakeConfig WITH (UPDLOCK)
        WHERE MachineId = @MachineId AND DatacenterId = @DatacenterId;
        
        -- 获取当前时间戳
        SET @Timestamp = dbo.GetCurrentTimestamp();
        
        -- 检查时钟回拨
        IF @Timestamp < @LastTimestamp
        BEGIN
            ROLLBACK TRANSACTION;
            THROW 50000, 'Clock moved backwards. Refusing to generate id', 1;
            RETURN;
        END
        
        -- 同一毫秒内生成多个 ID
        IF @LastTimestamp = @Timestamp
        BEGIN
            SET @Sequence = (@Sequence + 1) & @SequenceMask;
            IF @Sequence = 0
            BEGIN
                -- 序列耗尽,等待下一毫秒
                SET @Timestamp = dbo.ToNextMillis(@LastTimestamp);
            END
        END
        ELSE
        BEGIN
            SET @Sequence = 0;
        END
        
        -- 更新状态
        UPDATE SnowflakeConfig 
        SET LastTimestamp = @Timestamp, Sequence = @Sequence
        WHERE MachineId = @MachineId AND DatacenterId = @DatacenterId;
        
        -- 生成 ID (使用乘法替代位移)
        SET @SnowflakeId = (@Timestamp - @Twepoch) * dbo.PowerOfTwo(@TimestampLeftShift) + 
                           @DatacenterId * dbo.PowerOfTwo(@DatacenterIdShift) + 
                           @MachineId * dbo.PowerOfTwo(@MachineIdShift) + 
                           @Sequence;
        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION;
        THROW;
    END CATCH
END;
GO

查看效果

-- 使用存储过程版本
DECLARE @Id BIGINT;
EXEC GenerateSnowflakeId @MachineId=1, @DatacenterId=1, @SnowflakeId=@Id OUTPUT;
SELECT @Id AS SnowflakeId;

雪花 ID 生成结果

目录

  1. SQL Server 中生成雪花 ID
  2. 前言
  3. 认识雪花 ID
  4. 雪花 ID 的核心特点
  5. 雪花 ID 的结构(64 位)
  6. 雪花 ID 的优势
  7. 雪花 ID 的局限性
  8. 雪花 ID 的应用场景
  9. 示例 ID 解析
  10. 生成雪花 ID
  11. 使用 T-SQL 函数实现
  12. 查看效果

更多推荐文章

查看全部
  • LLaMA-Factory 本地部署与安装指南
  • C++ 入门实战指南:从环境搭建到核心概念解析
  • Java 入门基础教程
  • 2024 年大模型 LLM 技术学习路线图与核心岗位分析
  • 电商系统商品管理模块设计与实现
  • 2024 中国政务行业大模型发展洞察与学习路径指南
  • C++ 反射内存 (RFM) 双机通讯实战:微秒级同步
  • Conda 环境 Python 版本升级实战指南
  • PyTorch 实战:StyleGAN 模型详解与风格迁移实现
  • OpenClaw 集成飞书机器人实战指南
  • 大语言模型与机器学习分类解析
  • DeepSeek 中冷启动数据与多阶段训练的作用
  • Web3 学习笔记 Day1: 概览与开发环境搭建
  • Linux 进程间通信进阶:管道与共享内存
  • 文心一言开源版部署与多维度测评实践
  • Spring Boot Web 后端开发核心注解详解
  • FPGA SPI Flash配置模式:从硬件设计到约束文件的隐形桥梁
  • 6 种常用自定义数据结构设计与实现技巧
  • Redis 主从复制的原理及作用
  • PyWebIO 实现精准弹窗交互的关键点

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • SQL 美化和格式化

    在线格式化和美化您的 SQL 查询(它支持各种 SQL 方言)。 在线工具,SQL 美化和格式化在线工具,online

  • SQL转CSV/JSON/XML

    解析 INSERT 等受限 SQL,导出为 CSV、JSON、XML、YAML、HTML 表格(见页内语法说明)。 在线工具,SQL转CSV/JSON/XML在线工具,online

  • CSV 工具包

    CSV 与 JSON/XML/HTML/TSV/SQL 等互转,单页多 Tab。 在线工具,CSV 工具包在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online