C# 分布式自增ID算法snowflake(雪花算法)
文章目录
- 1. 概述
- 2. 结构
- 3. 代码
- 3.1 IdWorker.cs
- 3.2 IdWorkerTest.cs (测试)
1. 概述
分布式系统中,有一些需要使用全局唯一ID
的场景,这种时候为了防止ID
冲突可以使用36位的UUID
,但是UUID
有一些缺点,首先他相对比较长,另外UUID
一般是无序的。有些时候我们希望能使用一种简单一些的ID
,并且希望ID
能够按照时间有序生成。而Twitter
的snowflake
解决了这种需求,最初Twitter
把存储系统从MySQL
迁移到Cassandra
,因为Cassandra
没有顺序ID
生成机制,所以开发了这样一套全局唯一ID
生成服务。
该项目地址为:https://github.com/twitter/snowflake
是用 Scala
实现的
参考:
-
C# 分布式自增ID算法snowflake(雪花算法) - 五维思考 - 博客园 (cnblogs.com)
-
C#雪花Id_c# 雪花id-CSDN博客
2. 结构
第1位 | 第2位 | 第3位 | 第4位 | 第5位 |
---|---|---|---|---|
位数 | 时间戳(ms) | 数据中心ID(DatacenterId ) | 工作节点ID (MachineId ) | 自增序列号 |
0 | 0000000000 | 0000000000 | 0000000000 | 000000000000 |
- 第1位:未使用
- 第2位:接下来的41位为毫秒级时间(41位的长度可以使用69年),用毫秒级的时间戳来表示自1970年1月1日 00:00:00 GMT以来的时间。
- 第3-4位:用来区分不同的数据中心
datacenterId
和machineId
,可根据实际情况分配,最多可容纳1024个数据中心(2^10=10位的长度最多支持部署1024个节点),也可以设置成5位,最大节点是32个。 - 最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个
ID
序号)
一共加起来刚好64位,为一个Long
型。(转换成字符串长度为18)
snowflake
生成的ID
整体上按照时间自增排序,并且 整个分布式
系统内不会产生ID
碰撞(由datacenter
和machineId
作区分),并且效率较高。据说:snowflake
每秒能够产生26万个ID
。
注意:
- 在实际使用中,需要根据不同的分布式环境配置合适的数据中心ID和工作节点ID,以保证生成的雪花Id的唯一性和顺序性。
- 其中
dataCenterId
和workerId
分别是数据中心和工作节点的标识,该生成器依赖于数据中心ID和工作节点ID两个参数进行初始化。具体的生成过程是根据当前时间戳、数据中心ID、工作节点ID和自增序列号,通过位运算组合生成一个64位的唯一标识。
3. 代码
3.1 IdWorker.cs
using System;
/// <summary>
/// Twitter的分布式自增ID雪花算法
/// </summary>
public class IdWorker
{//起始的时间戳private static long START_STMP = 1480166465631L;//每一部分占用的位数private static int SEQUENCE_BIT = 12; //序列号占用的位数private static int MACHINE_BIT = 5; //机器标识占用的位数private static int DATACENTER_BIT = 5;//数据中心占用的位数//每一部分的最大值private static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);private static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);private static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);//每一部分向左的位移private static int MACHINE_LEFT = SEQUENCE_BIT;private static int DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;private static int TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;private long datacenterId = 1; //数据中心private long machineId = 1; //机器标识private long sequence = 0L; //序列号private long lastStmp = -1L;//上一次时间戳#region 单例:完全懒汉private static readonly Lazy<IdWorker> lazy = new Lazy<IdWorker>(() => new IdWorker());public static IdWorker Singleton { get { return lazy.Value; } }private IdWorker() { }#endregionpublic IdWorker(long cid, long mid){if (cid > MAX_DATACENTER_NUM || cid < 0) throw new Exception($"中心Id应在(0,{MAX_DATACENTER_NUM})之间");if (mid > MAX_MACHINE_NUM || mid < 0) throw new Exception($"机器Id应在(0,{MAX_MACHINE_NUM})之间");datacenterId = cid;machineId = mid;}/// <summary>/// 产生下一个ID/// </summary>/// <returns></returns>public long nextId(){long currStmp = getNewstmp();if (currStmp < lastStmp) throw new Exception("时钟倒退,Id生成失败!");if (currStmp == lastStmp){//相同毫秒内,序列号自增sequence = (sequence + 1) & MAX_SEQUENCE;//同一毫秒的序列数已经达到最大if (sequence == 0L) currStmp = getNextMill();}else{//不同毫秒内,序列号置为0sequence = 0L;}lastStmp = currStmp;return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分| datacenterId << DATACENTER_LEFT //数据中心部分| machineId << MACHINE_LEFT //机器标识部分| sequence; //序列号部分}private long getNextMill(){long mill = getNewstmp();while (mill <= lastStmp){mill = getNewstmp();}return mill;}private long getNewstmp(){return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;}
}
3.2 IdWorkerTest.cs (测试)
使用
IdWorker idworker = IdWorker.Singleton;
Console.WriteLine(idworker.nextId());
测试
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;namespace Test.Simple
{public static class IdWorkerTest{public static void Test(){/**** * 两种测试方法,均为500并发,生成5000个Id:* Machine1() 模拟1台主机,单例模式获取实例* Machine5() 模拟5台主机,创建5个实例*/Machine1();Machine2();Machine5();}public static void Machine1(){int cid = 1;int mid = 15;Console.WriteLine("雪花ID -- IdWorkerTest -- 模拟1台主机( 数据中心{0} - 机器节点{1}): ", cid, mid);IdWorker idworker = new IdWorker(cid, mid);Console.WriteLine(idworker.nextId());cid = 2;mid = 10;Console.WriteLine("雪花ID -- IdWorkerTest -- 模拟1台主机( 数据中心{0} - 机器节点{1}): ", cid, mid);idworker = new IdWorker(cid, mid);Console.WriteLine(idworker.nextId());}public static void Machine2(){Console.WriteLine("雪花ID -- IdWorkerTest -- 模拟1台主机 : ");for (int j = 0; j < 500; j++){Task.Run(() =>{IdWorker idworker = IdWorker.Singleton;for (int i = 0; i < 10; i++){Console.WriteLine(idworker.nextId());}});}}public static void Machine5(){Console.WriteLine("雪花ID -- IdWorkerTest -- 模拟5台主机 : ");List<IdWorker> workers = new List<IdWorker>();Random random = new Random();for (int i = 0; i < 5; i++){workers.Add(new IdWorker(1, i + 1));}for (int j = 0; j < 500; j++){Task.Run(() =>{for (int i = 0; i < 10; i++){int mid = random.Next(0, 5);Console.WriteLine(workers[mid].nextId());}});}}}
}
在这里插入图片描述
结束
相关文章:

C# 分布式自增ID算法snowflake(雪花算法)
文章目录 1. 概述2. 结构3. 代码3.1 IdWorker.cs3.2 IdWorkerTest.cs (测试) 1. 概述 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,…...
commonJS和esModule的应用
commonJS commonJS规范的核心变量是:exports,module.exports,require exports 和 module.exports可以负责模块的导出require 负责模块的导入 module.exports 导出方案: const name yx const age 18// 1 导出方案 module.exp…...

(十一)RabbitMQ及SpringAMQP
1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话,需要实时响应。 异步通讯:就像发邮件,不需要马上回复。 两种方式各有优劣,打电话可以立即得到响应,…...

STM32 M3内核寄存器概念
内容主要来自<<M3内核权威指南>> 汇编程序中的最低有效位(Least Significant Bit)。LSB是二进制数中最右边的位,它代表了数值中的最小单位。在汇编程序中,LSB通常用于表示数据的最小精度或者作为标志位。 ---------…...

SQL语句的编写
##创建用户-建表建库 #创建一个用户名为 feng,允许从任何主机 % 连接,并使用密码 sc123456 进行身份验证的用户。 rootTENNIS 16:33 scmysql>create user feng% identified by sc123456; Query OK, 0 rows affected (0.04 sec) #创建一个名为fen…...

Lecture 1~3 About Filter
文章目录 空间域上的滤波器- 线性滤波器盒状滤波器Box Filter锐化Sharpening相关运算 vs. 卷积运算 Correlation vs. Convolution - 非线性滤波器高斯滤波器Gaussian filter - 实际问题- 纹理texture 频域上的滤波器 滤波的应用- 模板匹配- 图像金字塔 空间域上的滤波器 图像…...

配置vscode链接linux
1.安装 remote SSH 2.按F1 ssh ljh服务器公网ip 3. 选择保存远端host到本地 某位置 等待片刻后 4. 切换到远程资源管理器中 应该可以看到一台电脑,右键在当前窗口链接,输入你的服务器用户密码后电脑变绿说明远程连接成功 5.一定要登陆上云服务器后再…...

论文阅读——MVDiffusion
MVDiffusion: Enabling Holistic Multi-view Image Generation with Correspondence-Aware Diffusion 文生图模型 用于根据给定像素到像素对应关系的文本提示生成一致的多视图图像。 MVDiffusion 会在给定任意每个视图文本的情况下合成高分辨率真实感全景图像,或将…...
Linux中的网络命令深度解析与CentOS实践
Linux中的网络命令深度解析与CentOS实践 在Linux系统中,网络命令是管理和诊断网络问题的关键工具。无论是网络管理员还是系统开发者,熟练掌握这些命令都是必不可少的。本文将深入探讨Linux中常用的网络命令,并以CentOS为例,展示这些命令的具体应用。 一、ping命令 ping命…...

nginx配置实例(反向代理)
目录 一、目标-反向代理实现效果 二、安装tomcat 三、配置nginx服务 四、配置反向代理 一、目标-反向代理实现效果 访问过程分析: 二、安装tomcat 1、安装jdk环境 新建/export/server目录 解压jdk 查看是否解压成功 配置jdk软连接 进入jdk的bin目录中&#x…...

Flutter 解决NestedScrollView与TabBar双列表滚动位置同步问题
文章目录 前言一、需要实现的效果如下二、flutter实现代码如下:总结 前言 最近写flutter项目,遇到NestedScrollView与TabBar双列表滚动位置同步问题,下面是解决方案,希望帮助到大家。 一、需要实现的效果如下 1、UI图࿱…...

云计算存在的安全隐患
目录 一、概述 二、ENISA云安全漏洞分析 三、云计算相关系统漏洞 3.1 概述 3.2 漏洞分析 3.2.1 Hypervisor漏洞 3.2.1.1 CVE-2018-16882 3.2.1.2 CVE-2017-17563 3.2.1.3 CVE-2010-1225 3.2.2 虚拟机漏洞 3.2.2.1 CVE-2019-14835 3.2.2.2 CVE-2019-5514 3.2.2.3 CV…...

黑翅鸢优化算法(BKA)-2024年SCI一区新算法-公式原理详解与性能测评 Matlab代码免费获取
声明:文章是从本人公众号中复制而来,因此,想最新最快了解各类智能优化算法及其改进的朋友,可关注我的公众号:强盛机器学习,不定期会有很多免费代码分享~ 目录 原理简介 一、种群初始化 二、攻击行为 三…...

sqlmap(四)案例
一、注入DB2 http://124.70.71.251:49431/new_list.php?id1 这是墨者学院里的靶机,地址:https://www.mozhe.cn/ 1.1 测试数据库类型 python sqlmap.py -u "http://124.70.71.251:49431/new_list.php?id1" 1.2 测试用户权限类型 查询选…...

【C++初阶】String在OJ中的使用(一):仅仅反转字母、字符串中的第一个唯一字母、字符串最后一个单词的长度、验证回文串、字符串相加
前言: 🎯个人博客:Dream_Chaser 🎈博客专栏:C 📚本篇内容:仅仅反转字母、字符串中的第一个唯一字母、字符串最后一个单词的长度、验证回文串、字符串相加 目录 917.仅仅反转字母 题目描述&am…...

【25考研】:四川大学计算机学院24届874考研考情分析
去年的考情分析也是我做的, 今年就在去年的基础上做了。保持形式不变,更改数据。 21考情: 万载月寒肠断客:四川大学计算机学院21届CS考研考情分析 22考情: 懒羊羊:四川大学计算机学院2022考研考情分析 2…...

【GPT-4 Turbo】、功能融合:OpenAI 首个开发者大会回顾
GPT-4 Turbo、功能融合:OpenAI 首个开发者大会回顾 就在昨天 2023 年 11 月 6 日,OpenAI 举行了首个开发者大会 DevDay,即使作为目前大语言模型行业的领军者,OpenAI 卷起来可一点都不比同行差。 OpenAI 在大会上不仅公布了新的 …...
java-Stream原理及相关操作详解(filter、map、flatMap、peek、reduce、anyMatch等等)
java-Stream原理及相关操作详解 Stream流前言Stream流原理介绍Stream-Api常用方法介绍filter()map()flatMappeekreducemax、minfindAny、 findFirstallMatch、anyMatch、noneMatchsortedcount Stream流前言 Java8特性主要是Stream流以及函数式接口的出现;本片文章主…...

基于Springboot中小企业设备管理系统设计与实现(论文+源码)_kaic
摘 要 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代&a…...
ORACLE 12 C估算 用户历史上的CPU消耗
在使用ASH不能满足,需要从AWR,即HIST系列表估算每个用户的cpu消耗,只能进行大概估算 先计算各用户使用的cpu time计算出各用户占比将用户cpu time 与osstat的cpu 使用率相乘 with cpu_usage as (select snap_id,BUSY_TIME/(IDLE_TIMEBUSY…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...