news 2026/5/1 8:39:26

.NET 实现雪花算法:高效生成分布式唯一 ID

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
.NET 实现雪花算法:高效生成分布式唯一 ID

雪花算法(Snowflake)

Twitter 开源的一种分布式 ID 生成算法

能够生成全局唯一的 64 位整数 ID。在分布式系统中,唯一 ID 的生成至关重要,它广泛应用于数据库主键、消息队列、订单号等场景。

具体实现可参考NetCoreKevin中的Kevin.SnowflakeId模块

一个基于NET8搭建DDD-微服务-现代化Saas企业级WebAPI前后端分离架构:前端Vue3、IDS4单点登录、多级缓存、自动任务、分布式、AI智能体、一库多租户、日志、授权和鉴权、CAP事件、SignalR、领域事件、MCP协议服务、IOC模块化注入、Cors、Quartz自动任务、多短信、AI、AgentFramework、SemanticKernel集成、RAG检索增强+Qdrant矢量数据库、OCR识别、API多版本、单元测试、RabbitMQ

项目地址:github:https://github.com/junkai-li/NetCoreKevin

Gitee: https://gitee.com/netkevin-li/NetCoreKevin

本文将详细介绍如何在 .NET 中实现雪花算法,并分析其核心逻辑。

雪花算法(Snowflake)简介

分布式 ID 生成算法的背景与需求

雪花算法的核心特点(全局唯一、趋势递增、高性能)

典型应用场景(数据库主键、消息队列、订单系统等)

雪花算法的核心结构

64 位 ID 的组成(符号位 + 时间戳 + 数据中心 ID + 机器 ID + 序列号)

各部分的位数分配及作用

时间回拨问题的处理机制

.NET 实现雪花算法的关键步骤

定义 ID 生成器的类结构(SnowflakeIdGenerator)

实现时间戳、数据中心 ID、机器 ID 的初始化逻辑

序列号的自增与溢出处理

处理系统时钟回拨的容错机制

| 时间戳(41 位) | 机器 ID(5 位) | 数据中心 ID(5 位) | 序列号(12 位) |

‌时间戳(41 位)‌:记录生成 ID 的毫秒级时间,从自定义起始时间(如 2020-01-01)开始计算,可支持约 69 年。

‌机器 ID(5 位)‌:标识不同的物理机器,范围是 0-31。

‌数据中心 ID(5 位)‌:标识不同的数据中心,范围是 0-31。

‌序列号(12 位)‌:同一毫秒内同一机器生成的 ID 的序列号,范围是 0-4095。

这种结构确保了:时间趋势性‌:ID 随时间递增,有利于数据库索引性能。

‌分布式唯一性‌:通过机器 ID 和数据中心 ID 区分不同节点。

‌高并发支持‌:序列号解决同一毫秒内的并发问题。

.NET 实现代码

核心类定义

csharp

Copy Code

using System;

using System.Threading;

public class SnowflakeIdGenerator

{

// 起始时间戳 (2020-01-01 00:00:00)

private const long TWEPOCH = 1577808000000L;

// 机器 ID 位数

private const int WORKER_ID_BITS = 5;

// 数据中心 ID 位数

private const int DATACENTER_ID_BITS = 5;

// 序列号位数

private const int SEQUENCE_BITS = 12;

// 最大机器 ID (0-31)

private const long MAX_WORKER_ID = -1L ^ (-1L << WORKER_ID_BITS);

// 最大数据中心 ID (0-31)

private const long MAX_DATACENTER_ID = -1L ^ (-1L << DATACENTER_ID_BITS);

// 机器 ID 左移位数

private const int WORKER_ID_SHIFT = SEQUENCE_BITS;

// 数据中心 ID 左移位数

private const int DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;

// 时间戳左移位数

private const int TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;

// 序列号掩码 (0-4095)

private const long SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS);

private long _lastTimestamp = -1L;

private long _sequence = 0L;

public SnowflakeIdGenerator(long workerId, long datacenterId)

{

if (workerId > MAX_WORKER_ID || workerId < 0)

{

throw new ArgumentException($"Worker ID 必须在 0 到 {MAX_WORKER_ID} 之间");

}

if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0)

{

throw new ArgumentException($"Datacenter ID 必须在 0 到 {MAX_DATACENTER_ID} 之间");

}

WorkerId = workerId;

DatacenterId = datacenterId;

}

public long WorkerId { get; private set; }

public long DatacenterId { get; private set; }

private readonly object _lock = new object();

public long NextId()

{

lock (_lock)

{

long timestamp = TimeGen();

// 处理时钟回拨

if (timestamp < _lastTimestamp)

{

throw new Exception($"时钟回拨 detected. 拒绝生成 ID 直到 {_lastTimestamp}");

}

if (_lastTimestamp == timestamp)

{

_sequence = (_sequence + 1) & SEQUENCE_MASK;

if (_sequence == 0)

{

timestamp = TilNextMillis(_lastTimestamp);

}

}

else

{

_sequence = 0;

}

_lastTimestamp = timestamp;

return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) |

(DatacenterId << DATACENTER_ID_SHIFT) |

(WorkerId << WORKER_ID_SHIFT) |

_sequence;

}

}

private long TilNextMillis(long lastTimestamp)

{

long timestamp = TimeGen();

while (timestamp <= lastTimestamp)

{

timestamp = TimeGen();

}

return timestamp;

}

private long TimeGen()

{

return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

}

}

关键逻辑说明 ‌初始化参数‌:

workerId 和 datacenterId 必须唯一,范围是 0-31。

起始时间戳 TWEPOCH 可自定义,确保时间戳部分足够长。

‌生成 ID 的步骤‌:

获取当前时间戳(毫秒)。

如果时间戳小于上一次生成 ID 的时间,抛出异常(时钟回拨)。

如果时间戳相同,递增序列号;如果序列号溢出,等待到下一毫秒。

组合时间戳、机器 ID、数据中心 ID 和序列号。

‌线程安全‌:

使用 lock 确保多线程环境下序列号的正确递增。

使用示例

csharp

Copy Code

public static void Main(string[] args)

{

// 创建生成器实例 (workerId: 1, datacenterId: 1)

var idGenerator = new SnowflakeIdGenerator(1, 1);

// 生成 10 个 ID

for (int i = 0; i < 10; i++)

{

long id = idGenerator.NextId();

Console.WriteLine($"生成的雪花 ID: {id} (二进制: {Convert.ToString(id, 2)})");

Thread.Sleep(1); // 确保不同毫秒

}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 17:14:51

LFM线性调频和脉冲压缩的理论总结与仿真

一、背景使用雷达探测物体时&#xff0c;雷达发射电磁波&#xff0c;电磁波撞到物体后反射回来&#xff0c;雷达接收回波信号来判断物体的位置。想象一下&#xff0c;如果雷达发出的信号非常弱&#xff0c;信号还没有到达物体处或者回波还没回来就衰减差不多了&#xff0c;雷达…

作者头像 李华
网站建设 2026/4/29 3:37:30

APP如何快速上架Apple Store:完整上架流程与常见问题解析

APP如何快速上架Apple Store?Apple Store上架流程及常见问题 在移动应用开发的征程中&#xff0c;将 APP 成功上架 Apple Store 是至关重要的一环。这不仅意味着应用能够触达广大 iOS 用户群体&#xff0c;更是对应用质量与合规性的一种认可。本文将深入探讨 APP 上架 Apple S…

作者头像 李华
网站建设 2026/5/1 7:19:30

医药类电商平台搭建公司有哪些?

说到医药类电商平台搭建公司&#xff0c;我们之前讲过几点判断的方法&#xff0c;我们以此来分析商联达&#xff1a;首先&#xff0c;我们看商联达的公司规模商联达成立有多年时间&#xff0c;技术总部在北京、分别在上海、广州、深圳、南京、成都等地都设立了分公司&#xff0…

作者头像 李华
网站建设 2026/4/30 1:15:33

VLA-ADAPTER: AN EFFECTIVE PARADIGM FOR TINY-SCALE VISION-LANGUAGE-ACTION MODEL

序号 属性值1论文名称VLA-ADAPTER2发表时间/位置20253CodeVLA-Adapter4创新点 1&#xff1a;小模型范式。 放弃了主流的 7B/13B 大模型&#xff0c;直接使用 0.5B (5亿参数) 的 Qwen2.5 作为主干。通过实验证明了只要“桥接”设计得好&#xff0c;小模型也能在具身智能任务上超…

作者头像 李华
网站建设 2026/5/1 7:18:10

突破架构壁垒:在Apple Silicon Mac上完美运行Vivado的完整方案

突破架构壁垒&#xff1a;在Apple Silicon Mac上完美运行Vivado的完整方案 【免费下载链接】vivado-on-silicon-mac Installs Vivado on M1/M2 macs 项目地址: https://gitcode.com/gh_mirrors/vi/vivado-on-silicon-mac 还在为M1/M2芯片Mac无法运行Xilinx Vivado而烦恼…

作者头像 李华
网站建设 2026/4/29 13:54:06

Wan2.1-I2V-14B-480P:消费级硬件上的高效图像到视频生成技术

Wan2.1-I2V-14B-480P&#xff1a;消费级硬件上的高效图像到视频生成技术 【免费下载链接】Wan2.1-I2V-14B-480P-StepDistill-CfgDistill-Lightx2v 项目地址: https://ai.gitcode.com/hf_mirrors/lightx2v/Wan2.1-I2V-14B-480P-StepDistill-CfgDistill-Lightx2v 图像到视…

作者头像 李华