【Sql Server】在SQL Server中生成雪花ID(Snowflake ID)
大家好,我是全栈小5,欢迎来到《小5讲堂》。
这是《Sql Server》系列文章,每篇文章将以博主理解的角度展开讲解。
温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!

目录
- 前言
- 认识雪花ID
- 雪花ID的核心特点
- 雪花ID的结构(64位)
- 雪花ID的优势
- 雪花ID的局限性
- 雪花ID的应用场景
- 示例ID解析
- 生成雪花ID
- 使用T-SQL函数实现
- 查看效果
- 文章推荐
前言
在我的印象中用到这个雪花ID比较少,可能是我接触的大型项目或者开源项目比较少,同时接触到中大型分布式也比较少,基本都是自研系统,用的是自增ID和GuidValue作为唯一编号。
最近项目上使用了一套第三方框架代码,使用了雪花ID作为表的唯一主键,并且之前表没有这个字段,需要进行表迁移的同时初始化雪花ID字段值。
因此,趁这次机会简单总结下雪花ID以及在Sql Server上如何生成雪花ID。
认识雪花ID
雪花ID是Twitter开发的一种分布式唯一ID生成算法,主要用于在分布式系统中生成全局唯一的ID标识符。它的名称来源于"自然界中没有两片完全相同的雪花"这一概念,象征着每个生成的ID都是独一无二的。
雪花ID的核心特点
- 全局唯一性:在分布式系统中生成的ID不会重复
- 时间有序性:ID按照时间顺序递增
- 高性能:本地生成,不依赖数据库等外部系统
- 可解析:ID中包含的信息可以被解析出来
雪花ID的结构(64位)
标准的雪花ID由以下三部分组成(共64位):
| 1位符号位 | 41位时间戳 | 10位工作节点ID | 12位序列号 |
具体分解:
- 符号位(1位):始终为0,保证ID为正数
- 时间戳(41位):毫秒级的时间戳,可以使用约69年
- 通常从自定义纪元开始计算(如Twitter使用2010-11-04 01:42:54 UTC)
- 工作节点ID(10位):
- 通常分为5位数据中心ID + 5位机器ID
- 最多支持32个数据中心,每个数据中心32台机器
- 序列号(12位):同一毫秒内的序列号,支持每毫秒生成4096个ID
雪花ID的优势
- 分布式友好:不同节点可以独立生成ID而不需要协调
- 时间有序:生成的ID按时间递增,有利于数据库索引
- 高性能:本地生成,不依赖网络或数据库
- 信息丰富:ID本身包含时间、节点等信息
雪花ID的局限性
- 时钟依赖:严重依赖系统时钟,时钟回拨会导致ID重复
- 节点ID配置:需要手动或通过外部系统分配节点ID
- 时间耗尽:41位时间戳大约69年后会耗尽
雪花ID的应用场景
- 分布式系统主键生成
- 订单号、交易号等业务编号
- 日志跟踪ID
- 任何需要全局唯一且有序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
BEGINDECLARE @epoch DATETIME2 = '1970-01-01 00:00:00';DECLARE @now DATETIME2 = SYSUTCDATETIME();RETURN CAST(DATEDIFF_BIG(MILLISECOND, @epoch, @now) AS BIGINT);
END;
-- 创建等待下一毫秒的函数
CREATE FUNCTION TilNextMillis(@lastTimestamp BIGINT)
RETURNS BIGINT
AS
BEGINDECLARE @timestamp BIGINT;SET @timestamp = dbo.GetCurrentTimestamp();WHILE @timestamp <= @lastTimestampBEGINSET @timestamp = dbo.GetCurrentTimestamp();ENDRETURN @timestamp;
END;
GO
-- 创建计算幂的函数(替代位移操作)
CREATE FUNCTION PowerOfTwo(@exponent BIGINT)
RETURNS BIGINT
AS
BEGINRETURN 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
BEGINSET 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 < 0BEGINTHROW 50000, 'MachineId can''t be greater than maxMachineId or less than 0', 1;RETURN;ENDIF @DatacenterId > @MaxDatacenterId OR @DatacenterId < 0BEGINTHROW 50000, 'DatacenterId can''t be greater than maxDatacenterId or less than 0', 1;RETURN;END-- 使用事务确保原子性BEGIN TRANSACTION;BEGIN TRYDECLARE @LastTimestamp BIGINT;DECLARE @Sequence BIGINT;DECLARE @Timestamp BIGINT;-- 获取当前状态SELECT @LastTimestamp = LastTimestamp, @Sequence = SequenceFROM SnowflakeConfig WITH (UPDLOCK)WHERE MachineId = @MachineId AND DatacenterId = @DatacenterId;-- 获取当前时间戳SET @Timestamp = dbo.GetCurrentTimestamp();-- 检查时钟回拨IF @Timestamp < @LastTimestampBEGINROLLBACK TRANSACTION;THROW 50000, 'Clock moved backwards. Refusing to generate id', 1;RETURN;END-- 同一毫秒内生成多个IDIF @LastTimestamp = @TimestampBEGINSET @Sequence = (@Sequence + 1) & @SequenceMask;IF @Sequence = 0BEGIN-- 序列耗尽,等待下一毫秒SET @Timestamp = dbo.TilNextMillis(@LastTimestamp);ENDENDELSEBEGINSET @Sequence = 0;END-- 更新状态UPDATE SnowflakeConfigSET LastTimestamp = @Timestamp,Sequence = @SequenceWHERE 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 TRYBEGIN CATCHROLLBACK TRANSACTION;THROW;END CATCH
END;
GO
查看效果
-- 使用存储过程版本
DECLARE @Id BIGINT;
EXEC GenerateSnowflakeId @MachineId = 1, @DatacenterId = 1, @SnowflakeId = @Id OUTPUT;
SELECT @Id AS SnowflakeId;

文章推荐
【Sql Server】使用row_number over方式进行表分页,数据量达到五千多条记录后,查询变慢需要20多秒的解决方案
【Sql Server】随机查询一条表记录,并重重温回顾下自定义函数的封装和使用
【Sql Server】锁表如何解锁,模拟会话事务方式锁定一个表然后进行解锁
【Sql Server】通过Sql语句批量处理数据,使用变量且遍历数据进行逻辑处理
【新星计划回顾】第六篇学习计划-通过自定义函数和存储过程模拟MD5数据
【新星计划回顾】第四篇学习计划-自定义函数、存储过程、随机值知识点
【Sql Server】Update中的From语句,以及常见更新操作方式
【Sql server】假设有三个字段a,b,c 以a和b分组,如何查询a和b唯一,但是c不同的记录
【Sql Server】新手一分钟看懂在已有表基础上修改字段默认值和数据类型
总结:温故而知新,不同阶段重温知识点,会有不一样的认识和理解,博主将巩固一遍知识点,并以实践方式和大家分享,若能有所帮助和收获,这将是博主最大的创作动力和荣幸。也期待认识更多优秀新老博主。
相关文章:
【Sql Server】在SQL Server中生成雪花ID(Snowflake ID)
大家好,我是全栈小5,欢迎来到《小5讲堂》。 这是《Sql Server》系列文章,每篇文章将以博主理解的角度展开讲解。 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 前言认识雪花ID…...
FPGA——分秒计数器设计(DE2-115开发板)
一、项目创建 1.创建工程 点击File->New Project Wizard...或者直接在页面处点击 在第一行选择文件存放地点,第二行为项目名称,第三行为顶级设计实体名称 (下面的步骤可以暂时不做直接点Finish,因为是先写代码先把它跑出来暂…...
雅思练习总结(九)
雅思练习总结(九) 本文章是雅思练习总结(九),总结了文章《BAKELITE》,内容包括原文精翻,文章脉络总结,单词扩展学习3个部分 1 文章原文及翻译 BAKELITE 翻译:贝克莱特…...
windows USB 了解
GUID GUID 是一个 128 位的数字,在全球范围内是独一无二的,常被用于标识软件组件、设备接口等,以保证在不同系统和环境中能唯一识别特定对象。 DEFINE_GUID(GUID_DEVINTERFACE_USCUSTOMKEYS, 0x12345678, 0x1234, 0x5678, 0x12, 0x12, 0x23…...
光谱相机的光谱信息获取
光谱信息的获取方式主要依赖于不同分光技术和成像方法,将入射光分解为不同波长并记录其强度。以下是常见的光谱信息获取技术分类及原理: 1. 分光技术(物理分解波长) (1) 滤光片法 原理:使用固定或可调滤…...
免去繁琐的手动埋点,Gin 框架可观测性最佳实践
作者:牧思 背景 在云原生时代的今天,Golang 编程语言越来越成为开发者们的首选,而对于 Golang 开发者来说,最著名的 Golang Web 框架莫过于 Gin [ 1] 框架了,Gin 框架作为 Golang 编程语言官方的推荐框架 [ 2] &…...
构建大语言模型应用:简介(第一部分)
本专栏聚焦大语言模型(LLM)相关内容的解析,通过检索增强生成(RAG)应用的视角来进行。 本系列文章 简介(本文)数据准备句子转换器向量数据库搜索与检索大语言模型开源检索增强生成评估大语言模…...
PEmicro Multilink FX调试踩坑
文章目录 1.背景2 功能说明2.1 实时数据查看功能2.1 电压观测2.2 SWO功能 3 设置与支持 1.背景 既然使用了NXP的芯片,笔者就想使用一下它的专用调试器,这里先说一下,笔者是从朋友那里借了一个调试器,型号为PEmicro Multilink FX …...
主流大模型采用的架构、注意力机制、位置编码等汇总表
记录下主流大模型的一些核心知识点,包括: 架构注意力机制位置编码归一化激活函数模型参数 表中的一些模型已经是很久之前的了,比如表中并未收入 DeepSeek V3 中使用的MLA的注意力机制。先占个位,后续如果有更新的汇总表再来更…...
SpringBoot学习笔记3.27
目录 实战篇第二课 1.注册参数的校验: 学习过程中遇到的问题: 1.什么是正则表达式 2.怎么自定义异常? 1. 创建全局异常处理类 2. 定义响应对象 3. 使用 ExceptionHandler 4. 设置响应状态码 5. 返回统一响应 6. 测试全局异常处理 …...
亚马逊严查变体!正常变体突然被拆分?!
近期,亚马逊平台对变体合规性的审查力度再次升级,许多卖家因此遭遇了变体评论被拆分、账号受限甚至被封禁的困境。这一变化让不少卖家措手不及,原本正常的变体评论突然被拆分,子体的评价不再汇总显示,而是各自独立呈现…...
2025NCTF--Web
文章目录 Websqlmap-masterez_dashez_dash_revenge Web sqlmap-master 源码 from fastapi import FastAPI, Request from fastapi.responses import FileResponse, StreamingResponse import subprocessapp FastAPI()app.get("/") async def index():return File…...
如何破解软件自动化测试框架的维护难题
破解软件自动化测试框架的维护难题应从优化测试用例设计、加强脚本的模块化与复用性、提高自动化测试工具的选择与使用效率等方面入手。其中,加强脚本的模块化与复用性尤为关键,通过提高脚本的模块化程度,可以显著降低后续维护成本࿰…...
外星人入侵(python设计小游戏)
这个游戏简而言之就是操作一个飞机对前方的飞船进行射击,和一款很久之前的游戏很像,这里是超级低配版那个游戏,先来看看效果图: 由于设计的是全屏的,所以电脑不能截图。。。。 下面的就是你操控的飞船,上面…...
iOS rootless无根越狱检测方案
不同于安卓的开源生态,iOS一直秉承着安全性更高的闭源生态,系统中的硬件、软件和服务会经过严格审核和测试,来保障安全性与稳定性。 据FairGurd观察,虽然iOS系统具备一定的安全性,但并非没有漏洞,如市面上…...
单端信号差分信号
单端信号和差分信号是电路中常见的两种信号传输方式,它们在具体的应用场景和特点上有着明显的区别。下面就来详细说明一下单端信号和差分信号的区别。 首先,单端信号是指信号通过一个信号线传输,通常一个信号线携带一个信号。这种传输方式适…...
LLM 优化技术(1)——Scaled-Dot-Product-Attention(SDPA)
在 Transformer 中抛弃了传统的 CNN 和 RNN,整个网络结构完全由Scaled Dot Product Attention 和Feed Forward Neural Network组成。一个基于 Transformer 的可训练的神经网络可以通过堆叠 Transformer 的形式进行搭建,Attention is All You Need论文中通…...
AIGC-头条号长文项目创作智能体完整指令(DeepSeek,豆包,千问,Kimi,GPT)
Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列AIGC(GPT、DeepSeek、豆包、千问、Kimi)👉关于作者 专注于Android/Unity和各...
基于音频驱动的CATIA动态曲面生成技术解析
一、技术背景与创新价值 在工业设计领域,参数化建模与动态仿真的结合一直是研究热点。本文提出的音频驱动建模技术突破了传统参数调整方式,实现了音乐节奏与三维曲面的实时动态交互。该技术可广泛应用于以下场景: 艺术化产品设计…...
5-管理员-维护权限
在“后台”-“人员管理”-“权限”下,通过不同的操作按钮,按照权限分组对权限进行设置。操作部分的按钮依次为 视野维护:设置该分组可以查看、访问的视图。权限维护:设置分组成员可以操作的具体动作等所有在禅道中涉及的权限。成…...
全新升级 | Built For You Spring ‘25 发布,Fin 智能客服实现新突破!
图像识别、语音交互、任务自动化,立即体验智能客服蜕变! 上周,Intercom 举办了 Built For You Spring 25 发布会,正式揭晓了 AI Agent Fin 的一系列令人振奋的更新。Fin 正在以前所未有的速度革新客户支持模式——它已经成功解决了…...
turtle的九个使用
一 import turtle as t color [red,green,blue,orange,pink] for i in range(len(color)):t.penup()t.goto(-20070*i,0)t.pendown()t.pencolor(color[i])t.circle(50, steps 5) t.done()二 #在____________上补充代码 #不要修改其他代码import random as r import turtle a…...
营销库存系统设计方案
文章目录 一、营销库存系统设计方案1. 核心模块设计实时库存管理促销库存预占机制库存分层调度动态库存分配2. 技术架构示例二、技术难点与解决方案高并发下的数据一致性防超卖与恶意请求拦截多级库存同步延迟异常场景处理三、关键注意事项1.系统弹性…...
R002-云计算
1 概念 英文名:Cloud Computing 核心:云计算的核心概念就是以互联网为中心,在网站上提供快速且安全的云计算服务与数据存储,让每一个使用互联网的人都可以使用网络上的庞大计算资源与数据中心 2.分类 基础设施即服务(IaaS)它向…...
LeeCode 434. 字符串中的单词数
统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。 请注意,你可以假定字符串里不包括任何不可打印的字符。 示例: 输入: "Hello, my name is John" 输出: 5 解释: 这里的单词是指连续的不是空格的字符,所以 "…...
DriveDreamer动力学模块和博弈论优化器
DriveDreamer的动力学模块与博弈论优化器是其实现复杂场景下高保真重建与多智能体协同优化的核心技术组件。 一、动力学模块(NTGM) 功能定位:作为新轨迹生成模块(Novel Trajectory Generation Module, NTGM)…...
【AI编程学习之Python】第一天:Python的介绍
Python介绍 简介 Python是一种解释型、面向对象的语言。由吉多范罗苏姆(Guido van Rossum)于1989年发明,1991年正式公布。官网:www.python.org Python单词是"大蟒蛇”的意思。但是龟叔不是喜欢蟒蛇才起这个名字,而是正在追剧:英国电视喜剧片《蒙提派森的飞行马戏团》(Mo…...
西域平台商品详情接口设计与实现
接口描述: 该接口用于获取西域平台中指定商品的详细信息,包括商品名称、价格、库存、描述、图片等。 点击获取key和secret 接口地址: GET /api/product/detail 请求参数: 参数名 类型 是否必填 描述 productId st…...
如何让 history 记录命令执行时间?Linux/macOS 终端时间戳设置指南
引言:你真的会用 history 吗? 有没有遇到过这样的情况:你想回顾某个重要命令的执行记录,却发现 history 只列出了命令序号和内容,根本没有时间戳?这在运维排查、故障分析、甚至审计时都会带来极大的不便。 想象一下,你在服务器上误删了某个文件,但不知道具体是几点执…...
云原生四重涅槃·破镜篇:混沌工程证道心,九阳真火锻金身
【乾坤惊变混沌劫起】 "轰——!" 龙渊山巅突然雷云翻滚,九重天外传来梵音轰鸣。监察使手中玄光镜剧烈震颤,镜中映出骇人景象:原本井然有序的Service Mesh星轨竟自行扭曲,数十万Envoy边车化身血色修罗&#…...
