一个简单的用C#实现的分布式雪花ID算法
雪花ID是一个依赖时间戳根据算法生成的一个Int64的数字ID,一般用来做主键或者订单号等。以下是一个用C#写的雪花ID的简单实现方法
using System;
using System.Collections.Concurrent;
using System.Diagnostics;public class SnowflakeIdGenerator
{// 配置常量private const int SignBits = 1;// 符号位private const int TimestampBits = 41;// 时间戳位,最大值2^41-1=2,147,483,647ms,69年private const int DataCenterIdBits = 4;// 数据中心ID位,最大值2^4-1=15private const int MachineIdBits = 6;// 机器ID位,最大值2^6-1=63private const int DefaultSequenceBits = 12;// 自增序号位,最大值2^12-1=4095private const int ProcessIdBits = 4;// 进程ID位,最大值2^4-1=15private const int SequenceBitsWithProcess = 8;//如果使用进程ID,则为8位,否则为12位,最大值2^8-1=255// 位移计算常量private const int TimestampShift = 64 - SignBits - TimestampBits;private const int DataCenterShift = TimestampShift - DataCenterIdBits;private const int MachineShift = DataCenterShift - MachineIdBits;private const int ProcessShift = SequenceBitsWithProcess;// 基准时间private static readonly DateTime Epoch = new(2025, 3, 1, 0, 0, 0, DateTimeKind.Utc);private const long MaxTimestamp = (1L << TimestampBits) - 1;// 单例存储private static readonly ConcurrentDictionary<string, SnowflakeIdGenerator> _instances = new();// 各ID最大值private readonly long _maxDataCenterId = (1 << DataCenterIdBits) - 1;private readonly long _maxMachineId = (1 << MachineIdBits) - 1;private readonly long _maxProcessId = (1 << ProcessIdBits) - 1;private readonly long _maxSequence;// 状态控制private readonly object _lock = new object();private long _lastTimestamp = -1L;private int _sequence = 0;// 节点信息public int DataCenterId { get; }// 数据中心IDpublic int MachineId { get; }// 机器IDpublic int ProcessId { get; }// 进程IDpublic bool UseProcessId { get; }// 是否使用进程IDprivate SnowflakeIdGenerator(int dataCenterId, int machineId, int processId){// 参数校验逻辑ValidateId(dataCenterId, (1 << DataCenterIdBits) - 1, nameof(dataCenterId));ValidateId(machineId, (1 << MachineIdBits) - 1, nameof(machineId));UseProcessId = processId != 0;if (UseProcessId){ValidateId(processId, (1 << ProcessIdBits) - 1, nameof(processId));}DataCenterId = dataCenterId;MachineId = machineId;ProcessId = processId;}public static SnowflakeIdGenerator GetInstance(int dataCenterId, int machineId, int processId = 0){var key = $"{dataCenterId}-{machineId}-{processId}";return _instances.GetOrAdd(key, _ => new SnowflakeIdGenerator(dataCenterId, machineId, processId));}/// <summary>/// 产生下一个ID/// </summary>/// <returns></returns>public long NextId(){lock (_lock){var timestamp = GetValidTimestamp();if (timestamp == _lastTimestamp){_sequence++;if (_sequence > MaxSequence){timestamp = WaitNextMillis(timestamp);_sequence = 0;}}else{_sequence = 0;}_lastTimestamp = timestamp;return BuildId(timestamp);}}/// <summary>/// 获取最大序号/// </summary>private int MaxSequence => UseProcessId ?(1 << SequenceBitsWithProcess) - 1 :(1 << DefaultSequenceBits) - 1;/// <summary>/// 拼接生成ID/// </summary>/// <param name="timestamp"></param>/// <returns></returns>private long BuildId(long timestamp){var id = (timestamp << TimestampShift)| ((long)DataCenterId << DataCenterShift)| ((long)MachineId << MachineShift);if (UseProcessId){return id | ((long)ProcessId << ProcessShift) | (uint)_sequence;}return id | (uint)_sequence;}/// <summary>/// 获取有效的时间戳,防止时间回拨或系统时钟溢出/// </summary>/// <returns></returns>/// <exception cref="InvalidOperationException"></exception>private long GetValidTimestamp(){var timestamp = (DateTimeOffset.UtcNow.Ticks - Epoch.Ticks) / TimeSpan.TicksPerMillisecond;if (timestamp < _lastTimestamp){throw new InvalidOperationException($"Clock moved backwards. Refusing to generate ID for {_lastTimestamp - timestamp}ms");}if (timestamp > MaxTimestamp){throw new InvalidOperationException($"System clock overflow. Timestamp exceeds {TimestampBits} bits.");}return timestamp;}// 等待下一毫秒,产生新的时间戳private static long WaitNextMillis(long currentTimestamp){long timestamp;var spinWait = new SpinWait();do{spinWait.SpinOnce();timestamp = (DateTimeOffset.UtcNow.Ticks - Epoch.Ticks) / TimeSpan.TicksPerMillisecond;} while (timestamp <= currentTimestamp);return timestamp;}// 校验ID,必须在0到最大值之间private static void ValidateId(int value, long maxValue, string paramName){if (value < 0 || value > maxValue){throw new ArgumentOutOfRangeException(paramName,$"Value must be between 0 and {maxValue}");}}
}
调用方式
//获取单例实例var generator = SnowflakeIdGenerator.GetInstance(dataCenterId: 1, machineId: 5);//推荐long id = generator.NextId();//或者,加入进程IDvar generator = SnowflakeIdGenerator.GetInstance(dataCenterId: 1, machineId: 5, processId: 10);long id = generator.NextId();
相关文章:
一个简单的用C#实现的分布式雪花ID算法
雪花ID是一个依赖时间戳根据算法生成的一个Int64的数字ID,一般用来做主键或者订单号等。以下是一个用C#写的雪花ID的简单实现方法 using System; using System.Collections.Concurrent; using System.Diagnostics;public class SnowflakeIdGenerator {// 配置常量p…...
【实战ES】实战 Elasticsearch:快速上手与深度实践-2.2.1 Bulk API的正确使用与错误处理
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 Elasticsearch Bulk API 深度实践:性能调优与容错设计1. Bulk API 核心机制解析1.1 批量写入原理剖析1.1.1 各阶段性能瓶颈 2. 高性能批量写入实践2.1 客户端最佳…...
鸿蒙Flutter开发故事:不,你不需要鸿蒙化
在华为牵头下,Flutter 鸿蒙化如火如荼进行,当第一次看到一份上百个插件的Excel 列表时,我也感到震惊,排名前 100 的插件赫然在列,这无疑是一次大规模的军团作战。 然后,参战团队鱼龙混杂,难免有…...
中间件框架漏洞攻略
中间件(英语:Middleware)是提供系统软件和应⽤软件之间连接的软件,以便于软件各部件之间的沟通。 中间件处在操作系统和更⾼⼀级应⽤程序之间。他充当的功能是:将应⽤程序运⾏环境与操作系统隔离,从⽽实…...
第21周:RestNet-50算法实践
目录 前言 理论知识 1.CNN算法发展 2.-残差网络的由来 一、导入数据 二、数据处理 四、编译 五、模型评估 六、总结 前言 🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 理论知识 1.CNN算法发展 该图列举出…...
构建大语言模型应用:数据准备(第二部分)
本专栏通过检索增强生成(RAG)应用的视角来学习大语言模型(LLM)。 本系列文章 简介数据准备(本文)句子转换器向量数据库搜索与检索大语言模型开源检索增强生成评估大语言模型服务高级检索增强生成 RAG 如上…...
AI-Sphere-Butler之Ubuntu服务器如何部署Nginx代理,并将HTTP升级成HTTPS,用于移动设备访问
环境: AI-Sphere-Butler WSL2 Ubuntu22.04 Nginx 问题描述: AI-Sphere-Butler之Ubuntu服务器如何部署Nginx代理,并将HTTP升级成HTTPS,用于移动设备访问 解决方案: 一、生成加密证书 1.配置OpenSSL生成本地不加…...
飞致云荣获“Alibaba Cloud Linux最佳AI镜像服务商”称号
2025年3月24日,阿里云云市场联合龙蜥社区发布“2024年度Alibaba Cloud Linux最佳AI镜像服务商”评选结果。 经过主办方的严格考量,飞致云(即杭州飞致云信息科技有限公司)凭借旗下MaxKB开源知识库问答系统、1Panel开源面板、Halo开…...
Django项目之订单管理part6(message组件和组合搜索组件)
一.前言 我们前面讲的差不多了,接着上节课讲,今天要来做一个撤单要求,我们可以用ajax请求,但是我这里介绍最后一个知识点,message组件,但是我会把两种方式都讲出来的,讲完这个就开始讲我们最重…...
Taro创建微信小程序项目 第一步搭建项目
1.node: 2.第一步: 安装taro npm install -g tarojs/cli 3.创建文件夹wxxcx, 创建demos的文件夹的项目(demos项目名称) taro init demos 出现以下信息:可以根据自己的需求选择 出现安装项目依赖失败不要紧 4.进入demos文件夹…...
S32K144外设实验(六):FTM输出单路PWM
文章目录 1. 概述1.1 时钟系统1.2 实验目的2. 代码的配置2.1 时钟配置2.2 FTM模块配置2.3 输出引脚配置2.4 API函数调用1. 概述 1.1 时钟系统 FTM的CPU接口时钟为SYS_CLK,在RUN模式下最高80MHz。模块的时钟结构如下图所示。 从上图中可以看出,FTM模块的功能时钟为SYS_CLK,…...
前端工程化开篇
前端发展史梳理: 最早的html,css,js是前端三剑客,足以实现所有的前端开发任务,但是呢,一个简单的前端交互效果可能就需要一大堆的代码去实现。 后来呢,有了前端库jQuery,他可以使前…...
地下管线三维建模软件工具MagicPipe3D V3.6.1
经纬管网建模系统MagicPipe3D,基于二维矢量管线管点数据本地离线参数化构建地下管网三维模型(包括管道、接头、附属设施等),输出标准3DTiles、Obj模型等格式,支持Cesium、Unreal、Unity、Osg等引擎加载进行三维可视化、…...
iOS自定义collection view的page size(width/height)分页效果
前言 想必大家工作中或多或少会遇到下图样式的UI需求吧 像这种cell长度不固定,并且还能实现的分页效果UI还是很常见的 实现 我们这里实现主要采用collection view,实现的方式是自定义一个UICollectionViewFlowLayout的子类,在这个类里对…...
以科技赋能,炫我云渲染受邀参加中关村文化科技融合影视精品创作研讨会!
在文化与科技深度融合的时代浪潮下,影视创作行业经历着前所未有的变革。影视创作行业发展态势迅猛, 同时也面临着诸多挑战。为促进影视创作行业的创新发展,加强业内交流与合作, 3月25日下午,海淀区文化创意产业协会举办…...
华为、浪潮、华三链路聚合概述
1、华为 链路聚合可以提高链路带宽和链路冗余性。有三种类型,分别是手工链路聚合,静态lacp链路聚合,动态lacp链路聚合。 手工链路模式:也称负载分担模式,需手动指定链路,各链路之间平均分担流量。静态LAC…...
Android 蓝牙/Wi-Fi通信协议之:经典蓝牙(BT 2.1/3.0+)介绍
在 Android 开发中,经典蓝牙(BT 2.1/3.0)支持多种协议,其中 RFCOMM/SPP(串口通信)、A2DP(音频流传输)和 HFP(免提通话)是最常用的。以下是它们在 Android 中的…...
【go微服务】Golang微服务之基--rpc的实现原理以及应用实战
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...
Redis的List类型
Redis的List类型 一.List类型简单介绍 二.List的常用命令1.LPUSH2.LRANGE3.LPUSHX4.RPUSH5.RPUSHX6.LPOP7.RPOP8.LINDEX9.LINSERT10.LLEN11.LREM12.LTRIM13.LSET 三.阻塞命令1.BRPOP(i)针对不是空的列表进行操作:(ii)针…...
【C语言】分支与循环(下)
前言:小飞在(上)篇总结了分支结构的内容,本文接上,总结循环结构的知识。 看完觉得有帮助的话记得点赞收藏加关注哦~ 目录 一、while循环 二、for循环 三、do-while循环 四、循环中的break和continue 五、循环结构…...
Android 中两个 APK 之间切换的几中方法
在 Android 中,两个 APK(应用程序)之间的切换通常是通过 Intent 来实现的。以下是一些常见的方法和注意事项,帮助你实现两个 APK 之间的切换。 一、启动目标 APK 的主 Activity 1、setPackage 方法 使用 Intent 的 setPackage …...
SpringBoot集成腾讯云OCR实现身份证识别
OCR身份证识别 官网地址:https://cloud.tencent.com/document/product/866/33524 身份信息认证(二要素核验) 官网地址:https://cloud.tencent.com/document/product/1007/33188 代码实现 引入依赖 <dependency><…...
留记录excel 模板导入
Data EqualsAndHashCode public class FillData {ExcelProperty(value "姓名", index 0)private String name;ExcelProperty(value "数值", index 1)private double number;ExcelProperty(value "日期", index 2)private Date date; }pack…...
【C++数据库】SQLite3数据库连接与操作
注意:本文代码均为C++20标准下实现 一、SQLite3库安装 1.1 安装库文件 【工具】跨平台C++包管理利器vcpkg完全指南 vcpkg install sqlite3# 集成至系统目录,之前执行过此命令的无需再次执行 vcpkg integrate install1.2 验证代码 在VS2022中新建控制台项目,测试代码如下…...
【机器学习基础 4】 Pandas库
一、Pandas库简介 Pandas 是一个开源的 Python 数据分析库,主要用于数据清洗、处理、探索与分析。其核心数据结构是 Series(一维数据)和 DataFrame(二维表格数据),可以让我们高效地操作结构化数据。Pandas …...
如何在根据名称或id找到json里的节点以及对应的所有的父节点?
函数如下: 数据如下: [{ "name": "数据看板", "id": "data", "pageName": "tableeauData", "list": [] }, { "name": "审计模块", "id": &quo…...
JS—异步编程:3分钟掌握异步编程
个人博客:haichenyi.com。感谢关注 一. 目录 一–目录二–引言三–JavaScript 事件循环机制四–定时器的秘密:setTimeout 和 setInterval五–异步编程模型对比 二. 引言 在现代Web开发中,异步编程是提升性能的关键技术。无论是脚本加载&am…...
mxgraph编辑器的使用
前端JS如何使用mxgraph编辑器 说明:此项目是JS项目,目前还不支持TS 引入资源 可以直接从官网上拿下来,或者从其他地方获取 官网编辑器 如果只是展示图形的话只引入 mxClient.js就可以了 一个免费在线编辑器 自己用它做了一个在线编辑器&#…...
electron打包vue2项目流程
1,安装一个node vue2 的项目 2,安装electron: npm install electron -g//如果安装还是 特比慢 或 不想安装cnpn 淘宝镜像查看是否安装成功:electron -v 3,进入到项目目录:cd electron-demo 进入项目目录…...
STM32F103_LL库+寄存器学习笔记11 - 串口收发的中断优先级梳理
导言 推荐的STM32 USARTDMA 中断优先级设置(完整方案): 以你的STM32F103 USART1 DMA实例为例: 推荐中断优先级设置中断优先级USART1空闲中断(接收相关)优先级0DMA1通道5接收中断(半满/满传输…...
