讲师中心 微信公众号
AI工具推荐 视频效率加速

c# 在 C# 中实现一个简单的分布式ID生成器(雪花算法)

云萱姑娘_3997

云萱姑娘_3997

发布时间:2026-02-08 08:14:09

|

630人浏览过

|

来源于php中文网

原创

直接用SnowflakeIdGenerator类易出错,根本原因是未保证workerId和datacenterId全局唯一;需用Redis等中心化服务动态分配,统一用DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()防时钟回拨,sequence溢出时应阻塞等待而非重置。

c# 在 c# 中实现一个简单的分布式id生成器(雪花算法)

为什么直接用 SnowflakeIdGenerator 类容易出错

很多人照着网上的 C# 雪花算法实现抄一个 SnowflakeIdGenerator 类,运行起来 ID 看似递增,但一上多节点就重复——根本原因是没处理好 **机器 ID(workerId)和数据中心 ID(datacenterId)的全局唯一分配**。雪花算法要求同一毫秒内,不同节点的 workerId 必须不重叠,否则 timestamp + workerId + sequence 组合就可能碰撞。

常见错误包括:

  • 硬编码 workerId = 1,本地跑得通,部署到 3 台服务器全设成 1,必然冲突
  • 用 IP 哈希取模算 workerId,但 IPv4 地址段有限,哈希后碰撞概率高
  • 依赖配置文件手动填 workerId,运维漏配或填错,服务启动失败或 ID 冲突静默发生

用 ZooKeeper 或 Redis 自动分配 workerId 更可靠

生产环境推荐用中心化协调服务动态分配,避免人工干预。Redis 是多数团队已有组件,接入成本低:

  • 每个实例启动时,用 Lua 脚本在 Redis 中原子性地申请一个未被占用的 workerId(比如从 0–1023 范围取)
  • 成功后写入临时 key(带 TTL),并监听该 key 过期或主动释放
  • 若申请不到可用 ID,应阻塞等待或快速失败,不能降级为随机数——那就不叫雪花算法了

示例 Lua 脚本逻辑(用于 redis-cli --eval):

Pandas 配置文件报告生成器
Pandas 配置文件报告生成器

使用ydata-profiling(前身为pandas-profiling)生成全面的数据质量报告,包含相关性分析、缺失值模式和基数检测。导出交互式HTML仪表板和JSON摘要。

下载
local used = redis.call('smembers', 'snowflake:used_worker_ids')
local all = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
for _, id in ipairs(all) do
  local is_used = false
  for _, u in ipairs(used) do
    if tonumber(u) == id then is_used = true; break end
  end
  if not is_used then
    redis.call('sadd', 'snowflake:used_worker_ids', id)
    redis.call('setex', 'snowflake:worker:' .. id, 300, 'alive')
    return id
  end
end
return -1

DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() 比 DateTime.Now 更安全

雪花算法依赖时间戳左移,一旦系统时钟回拨(NTP 校正、虚拟机休眠恢复),DateTime.Now 可能跳变,导致生成重复 ID 或序列号溢出。C# 中应统一用 UTC 时间戳:

  • DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() 返回 long,精度毫秒,无时区歧义
  • 不要用 DateTime.Now.Ticks / 10000,它依赖本地时区且易受夏令时影响
  • 建议在 ID 生成器内部缓存上一次时间戳,若新时间 ≤ 上次值,则用 sequence++;若差值 > 5s,可 panic 或抛异常——说明时钟严重异常

序列号 sequence 溢出时必须阻塞等待,不能重置

标准雪花算法中,序列号占 12 bit(0–4095),意味着每毫秒最多生成 4096 个 ID。如果业务峰值超过该速率,常见错误是“超了就清零”,这会破坏单调递增性,且在分布式下极易撞 ID。

  • 正确做法:当 sequence == 4095 且当前毫秒未变时,线程 sleep 到下一毫秒再继续
  • sleep 时间不宜用 Thread.Sleep(1),而应计算目标时间戳后调用 SpinWait.SpinUntil 或基于 Stopwatch 的 busy-wait,减少上下文切换开销
  • 注意:.NET 6+ 中 System.TimeProvider 可用于测试时模拟时间推进,方便压测序列号阻塞逻辑

简单阻塞示意(非完整实现):

while (currentTimestamp == _lastTimestamp)
{
    currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
    if (currentTimestamp == _lastTimestamp)
    {
        // 自旋等待,直到下一毫秒
        while (DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() <= currentTimestamp) { }
        currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
    }
}

时间戳和序列号的协同边界非常敏感,任何想“绕过限制”的优化(比如扩展 sequence 位数、改用 hybrid logical clock)都会脱离雪花协议,下游系统可能无法识别。保持原生 64 位结构,才是兼容性和可维护性的底线。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

2033

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

3054

2023.10.07

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4118

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

543

2025.12.01

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

5816

2023.08.14

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

4489

2023.11.02

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

4035

2023.11.14

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

7452

2024.04.02

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

0

2026.10.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn