开源一个c# 新的雪花算法

介绍

用一种全新的雪花漂移算法(以下简称本算法),让ID更短、生成速度更快。
核心在于缩短ID长度的同时,还能保持极高并发处理量(50W/0.1s),且具有很强配置能力。

需求来源

1.作为架构设计的你,想要解决数据库主键唯一的问题,特别是在分布式系统多数据库的时候。

2.你希望这个主键是用最少的存储空间,索引速度更快,Select、Insert 和 Update 更迅速。

3.你要考虑在分库分表(合库合表)的时候,主键值可直接使用,并能反映业务时序。

4.如果这样的主键值太长,超过前端 JS Number 类型最大值,须把 Long 型转换为 String 型,你会觉得有点沮丧。

5.哪怕 Guid 能自增,但占用空间大,这也不是你想要的。

6.你希望系统能运行 100 年以上。

传统算法问题

1.生成的ID太长。

2.并发量不够。

3.不能解决时间回拨问题。

4.不支持后补生成前序ID。

5.依赖外部缓存系统。

新算法特点

1.整形数字,随时间单调递增(不一定连续),长度更短,用50年都不会超过 js Number类型最大值。(默认配置 WorkerId 是6bit,自增数是6bit)

2.速度更快,是传统雪花算法的2-5倍,0.1秒可生成50万个。(i7笔记本,默认算法配置6bit+6bit)

3.支持时间回拨处理。比如服务器时间回拨1秒,本算法能自动适应生成临界时间的唯一ID。

4.支持手工插入新ID。当业务需要在历史时间生成新ID时,用本算法的预留位能生成5000个每秒。

5.漂移时能外发通知事件。让调用方确切知道算法漂移记录,Log并发调用量。

6.不依赖任何外部缓存和数据库。(但 WorkerId 必须由外部指定)

性能数据

(参数:10位自增序列,1000次漂移最大值)

连续请求量 5K 5W 50W
传统雪花算法 0.0045s 0.053s 0.556s
雪花漂移算法 0.0015s 0.012s 0.113s

效果

1.js Number 类型最大数值:9007199254740992,本算法在保持并发性能(5W+/0.01s)和最大64个 WorkerId(6bit)的同时,能用70年才到 js Number Max 值。

2.增加WorkerId位数到8bit(128节点)时,15年达到 js Number Max 值。

3.极致性能:500W/1s。

4.所有测试数据均基于8代低压i7计算。

“我”是什么

1.本算法是一个类库,它基于 net standard2.0 基础库,不依赖任何第三方组件。

2.本算法不依赖任何外部数据系统(除了要被指定 WorkerId 之外)。

适用范围

1.小型、中型、大型需要全局唯一Id(不用Guid)的项目。

2.分布式项目。

3.不想将 Long 型转 String 给前端用的项目。(若前端支持bigint,则可不转类型)

如何处理时间回拨
1.当发生系统时间回拨的时候,算法采用过去时序的预留序数生成新的ID。

2.默认每秒生成100个(速度可调整)。

3.回拨生成的ID序号,默认靠前,也可以调整为靠后。

4.允许时间回拨至本算法预设基数(参数可调)。

能用多久

1.在默认配置下,ID可用 71000 年不重复。

2.在支持 1024 个工作节点时,ID可用 4480 年不重复。

3.在支持 4096 个工作节点时,ID可用 1120 年不重复。

4.以上所有工作节点,均拥有 50W/0.1s 最大处理速度。

★★集成建议★★

常规集成

1.用单例模式调用。外部集成方使用更多的实例并行调用本算法,不会增加ID产出效能,因为本算法采用单线程模式生成ID。

2.指定唯一的 WorkerId。必须由外部系统确保 WorkerId 的全局唯一性,并赋值给本算法入口方法。

3.异常处理。本算法内部会抛出所有Exception,外部系统 catch 相关信息并做好应对处理,以免引发更大的系统崩溃。

4.认真理解 IdGeneratorOptions 的定义,这对集成和使用本算法有帮助。

5.订阅ID异步通知。IIdGenerator.GenIdActionAsync 是一个可以向外部系统异步发送ID生成消息的事件,它包含的消息类型有"漂移开始、漂移结束、时间回拨",具体参考 Yitter.IdGenTest 的 Program.cs 启动代码。不过订阅ID异步通知会有细微的性能损失。

6.同步或同步调用。你可在外部系统的异步(async标记)方法中调用本算法,同步调用同样没问题。

7.使用雪花漂移算法。虽然代码里包含了传统雪花算法的定义,并且你可以在入口处指定(Method=2)来启用传统算法,但仍建议你使用雪花漂移算法(Method=1,默认的),毕竟它具有更好的伸缩力和更高的性能。

8.轻易不要修改核心算法。本算法内部参数较多,逻辑较为复杂,在你尚未掌握核心逻辑时,请勿尝试修改核心代码且用于生产环境,除非通过大量细致、科学的测试验证。

大型分布式集成

1.可扩大 WorkerIdBitLength 到最大20,支持 1,048,576 个节点,且不影响上述并发性能(50W/0.1s)。[算法支持]

2.采用中心化 IdGenerator 集群,给节点生成可用 Id 列表,存入 Redis 队列供节点消费。此时64个中心化节点数足够大型互联网项目使用。[需集成方扩展实现]

3.以上2条二选一即可,采用方法2一般是因为不想增加最终 ID 长度,但节点数超过64个。

4.任何加大 WorkerIdBitLength 或 SeqBitLength 的设置,都可能会增加 ID 的长度。

配置变更

配置变更指是系统运行一段时间后,再变更运行参数(IdGeneratorOptions选项值),请注意:

1.最重要的一条原则是:StartTime 只能往前(比老值更小、距离现在更远)赋值,原因是往后赋值极大可能产生相同的时间戳。[不推荐在系统运行之后调整 StartTime]

2.任何时候增加 WorkerIdBitLength 或 SeqBitLength,都是可以的,但是慎用 “减小”的操作,因为这可能导致在未来某天生成的 ID 与过去老配置时相同。[允许在系统运行之后增加任何一个 BitLength 值]

3.如果必须减小 WorkerIdBitLength 或 SeqBitLength 其中的一项,一定要满足一个条件:新的两个 BitLength 之和要大于 老的值之和。[不推荐在运行之后缩小任何一个 BitLength 值]

4.上述3条规则,并未在本算法内做逻辑控制,集成方应根据上述规则做好影响评估,确认无误后,再实施配置变更。

代码示例

运行环境

1..NET Standard 2.0+

文件说明

1.SnowWorkerM1.cs 是雪花漂移算法。

2.SnowWorkerM2.cs 是传统雪花算法。

雪花漂移算法

var options = new IdGeneratorOptions()
{
	// 设置WorkerId,默认最大2^16-1
	WorkerId = 1
};

var newId = new YitIdGenerator(options).NewLong();

传统雪花算法

var options = new IdGeneratorOptions()
{
	Method = 2, // 默认1
	WorkerId = 1
};

var newId = new YitIdGenerator(options).NewLong();

options说明

options参数(Method、StartTime除外)只支持漂移算法,不支持传统雪花算法。

public class IdGeneratorOptions
{
 /// <summary>
 /// 雪花计算方法
 /// (1|2)
 /// </summary>
 public short Method { get; set; } = 1;

 /// <summary>
 /// 开始时间(UTC格式)
 /// 不能超过当前系统时间
 /// </summary>
 public DateTime StartTime { get; set; } = DateTime.MinValue;

 /// <summary>
 /// 机器码
 /// 与 WorkerIdBitLength 有关系
 /// </summary>
 public ushort WorkerId { get; set; } = 0;

 /// <summary>
 /// 机器码位长
 /// 范围:2-21(要求:序列数位长+机器码位长不超过22)。
 /// 建议范围:6-12。
 /// </summary>
 public byte WorkerIdBitLength { get; set; } = 6;

 /// <summary>
 /// 序列数位长
 /// 范围:2-21(要求:序列数位长+机器码位长不超过22)。
 /// 建议范围:6-14。
 /// </summary>
 public byte SeqBitLength { get; set; } = 6;

 /// <summary>
 /// 最大序列数(含)
 /// (由SeqBitLength计算的最大值)
 /// </summary>
 public int MaxSeqNumber { get; set; } = 0;

 /// <summary>
 /// 最小序列数(含)
 /// 默认11,不小于5,不大于MaxSeqNumber-2
 /// </summary>
 public ushort MinSeqNumber { get; set; } = 11;

 /// <summary>
 /// 最大漂移次数(含),
 /// 默认2000,推荐范围500-10000(与计算能力有关)
 /// </summary>
 public int TopOverCostCount { get; set; } = 2000;

生成的ID

默认配置:

WorkerId = 6	(最多64个工作节点)
SeqBitLength = 6

ID示例(基于默认配置):

129053495681099  (本算法运行1年)
387750301904971  (运行3年)
646093214093387  (运行5年)
1292658282840139  (运行10年)
9007199254740992  (js Number 最大值)
165399880288699493  (普通雪花算法生成的ID)

本算法生成的 ID 值,是 js Number 最大值的 1%-10%,是普通雪花算法值的千分之一,而计算能力却超过普通雪花算法。

技术支持

开源地址:https://gitee.com/yitter/idgenerator

以上就是开源一个c# 新的雪花算法的详细内容,更多关于c# 雪花算法的资料请关注我们其它相关文章!

(0)

相关推荐

  • c# 实现模糊PID控制算法

    跑起来的效果看每个类的test方法,自己调用来测试 目的是看看哪个算法好用,移植的时候比较单纯没有研究懂算法,代码结构也没改动,只是移植到C#方便查看代码和测试,大家要拷贝也很方便,把整个类拷贝到.cs文件即可 这段算法在实际值低于目标值是工作正常,超过后会有问题,不知道如何调教 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Tex

  • C#实现拼手气红包算法

    本文实例为大家分享了C#实现拼手气红包算法的具体代码,供大家参考,具体内容如下 一.方案1:即开即中,考虑机会均等,减少金额差较大的几率 可以每次点击时候,随机产生 static double[] GetRandomMoney(double money, int n) { double[] array = new double[n]; RedPackage red = new RedPackage() { money = money, count = n }; for (int i = 0; i

  • C#中的那些常用加密算法

    前言 本文主要讲解一下C#常用的那些加密算法. 本文源码 本文所用源码均以为大家整理完毕,大家使用以下方式获取 需要的小伙伴,请关注微信公众号: 程序员零距离, 或者扫描下方公众号二维码,回复关键字:加密算法 , 即可获取本文所用的所有源码资源. 关注上方公众号,回复 加密算法获取 MD5加密 MD5加密是最常见的加密方式,因为MD5是不可逆的,所以很多系统的密码都是用MD5加密保存的. 虽然MD5是不可以解码的,但因为MD5加密的字符串是固定的,所以,理论上只需要建立一个庞大的数据库,把所有的

  • 经典实例讲解C#递归算法

    一 .递归算法简介 在数学与计算机科学中,递归是指在函数的定义中使用函数自身的方法. 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 递归算法解决问题的特点: (1) 递归就是在过程或函数里调用自身. (2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口. (3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低.所以一般不提倡用递归算法设计程序. (4) 在递归调用的过程当中

  • 少见的C# RSA算法

    当下最流行的RSA加密算法,只有公钥和私钥同时拥有才能破解加密信息,RSA加密算法的出现有利于数据安全性传输 1.C#中自带RSACryptoServiceProvider类可以让你很好的生成XML格式的公钥和私钥,两句代码就搞定 2.但是生成的XML格式前端不能很好的利用和读懂,所以在生成的XML格式里需要转换成PEM格式,这样才能直接Copy到验证工具里加密解密,非常方便 首先,我们先导入一个第三方库,因为下面涉及到的转换代码都是需要依赖这个库来实现,导入操作如下 控制台里输入 PM > I

  • c# 实现位图算法(BitMap)

    算法原理 BitMap的基本思想就是用一个bit位来标记某个元素对应的Value,而Key即是该元素.由于采用了Bit为单位来存储数据,因此可以大大节省存储空间. BitMap可以看成一种数据结构. 假设有这样一个需求:在20亿个随机整数中找出某个数m是否存在其中,并假设32位操作系统,4G内存. 在Java中,int占4字节,1字节=8位(1 byte = 8 bit). 如果每个数字用int存储,那就是20亿个int,因而占用的空间约为 (2000000000*4/1024/1024/102

  • c# 实现KMP算法的示例代码

    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息.KMP算法的时间复杂度O(m+n) . 实现方式就不再这里献丑了,网上很多讲解,此处只是记录下c#实现的代码. public class KMP { public

  • C#实现一阶卡尔曼滤波算法的示例代码

    //FilterKalman.cs namespace FusionFiltering { public class FilterKalman { private double A = 1; private double B = 0; private double H = 1; private double R; private double Q; private double cov = double.NaN; private double x = double.NaN; public Fil

  • C# 使用SHA1算法对密码进行加密

    C#中如何使用SHA1对密码进行加密呢?先声明一下,对于编程小编在这个方面还是个小白,如果小编有说的不对的地方,请各位大佬联系小编,小编好进行修改.好了不说废话了上图.在这里呢小编创建的是ASP.NET Web 项目应用程序,winform窗体应用也是可以的 创建好项目之后再你的项目里创建一个类 第二步 在你创建好的类里边先把登录的方法写好,让后再定义一个密加密的方法请看图 第三步在写好加密方法后在你的登录验证方法里面调用你的加密方法就可以了具体调用的代码请看下图 完成上边的操作后你再去你登录按

  • 开源一个c# 新的雪花算法

    介绍 用一种全新的雪花漂移算法(以下简称本算法),让ID更短.生成速度更快. 核心在于缩短ID长度的同时,还能保持极高并发处理量(50W/0.1s),且具有很强配置能力. 需求来源 1.作为架构设计的你,想要解决数据库主键唯一的问题,特别是在分布式系统多数据库的时候. 2.你希望这个主键是用最少的存储空间,索引速度更快,Select.Insert 和 Update 更迅速. 3.你要考虑在分库分表(合库合表)的时候,主键值可直接使用,并能反映业务时序. 4.如果这样的主键值太长,超过前端 JS

  • Java 基于雪花算法生成分布式id

    SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为了让整个系统能够承载更大的访问量.诸如订单号这些我们需要它是全局唯一的,同时我们基本上都会将它作为查询条件:出于系统安全考虑不应当让其它人轻易的就猜出我们的订单号,同时也要防止公司的竞争对手直接通过订单号猜测出公司业务体量:为了保证系统的快速响应那么生成算法不能太耗时.而雪花算法正好解决了这些问题. SnowFlake 算法(雪花算法), 是Twitter开源的分

  • 基于python实现雪花算法过程详解

    这篇文章主要介绍了基于python实现雪花算法过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Snowflake是Twitter提出来的一个算法,其目的是生成一个64bit的整数: 1bit:一般是符号位,不做处理 41bit:用来记录时间戳,这里可以记录69年,如果设置好起始时间比如今年是2018年,那么可以用到2089年,到时候怎么办?要是这个系统能用69年,我相信这个系统早都重构了好多次了. 10bit:10bit用来记录机器ID

  • 利用mysql实现的雪花算法案例

    一.为何要用雪花算法 1.问题产生的背景 现如今越来越多的公司都在用分布式.微服务,那么对应的就会针对不同的服务进行数据库拆分,然后当数据量上来的时候也会进行分表,那么随之而来的就是分表以后id的问题. 例如之前单体项目中一个表中的数据主键id都是自增的,mysql是利用autoincrement来实现自增,而oracle是利用序列来实现的,但是当单表数据量上来以后就要进行水平分表,阿里java开发建议是单表大于500w的时候就要分表,但是具体还是得看业务,如果索引用的号的话,单表千万的数据也是

  • Java实现雪花算法的原理

    SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法.其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id.在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的,后面的代码中有详细的注解. 这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号. 给大家举个例子吧,比如下面那个 64 bit 的 long 型数字: 第一个部分

  • java算法之静态内部类实现雪花算法

    概述 在生成表主键ID时,我们可以考虑主键自增 或者 UUID,但它们都有很明显的缺点 主键自增:1.自增ID容易被爬虫遍历数据.2.分表分库会有ID冲突. UUID: 1.太长,并且有索引碎片,索引多占用空间的问题 2.无序. 雪花算法就很适合在分布式场景下生成唯一ID,它既可以保证唯一又可以排序.为了提高生产雪花ID的效率, 在这里面数据的运算都采用的是位运算 一.概念 1.原理 SnowFlake算法生成ID的结果是一个64bit大小的整数,它的结构如下图: 算法描述: 1bit 因为二进

  • Go语言实现Snowflake雪花算法

    每次放长假的在家里的时候,总想找点简单的例子来看看实现原理,这次我们来看看 Go 语言雪花算法. 介绍 有时候在业务中,需要使用一些唯一的ID,来记录我们某个数据的标识.最常用的无非以下几种:UUID.数据库自增主键.Redis的Incr命令等方法来获取一个唯一的值.下面我们分别说一下它们的优劣,以便引出我们的分布式雪花算法. 雪花算法 雪花算法的原始版本是scala版,用于生成分布式ID(纯数字,时间顺序),订单编号等. 自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景. GUID:采

  • 带你入门java雪花算法原理

    雪花算法(SnowFlake) 雪花算法是Twitter开源的分布式ID生成算法. 主要是由64bit的long型生成的全局ID,引入了时间戳和ID保持自增的属性. 64bit分为四个部分: 第一个部分是1bit, 这不 使用,没有意义; 第二个部分是41bit, 组成时间戳; 第三个部分是10bit, 工作机器ID,里面分为两个部分,5个bit是的是机房号,代表最多有25即32个机房,5个bit是指机器的ID,代表最多有25个机器,即32个机器 . 第四部分是12bit, 代表是同一个毫秒类产

  • Java实现雪花算法的原理和实战教程

    目录 SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法.其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id.在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的,后面的代码中有详细的注解. 这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号. 给大家举个例子吧,比如下面那个 64 bit 的 long 型数字: 第一

  • Go实现分布式唯一ID的生成之雪花算法

    目录 背景: 特性: 雪花算法: 分布式唯一ID的生成 背景: 在分布式架构下,唯一序列号生成是我们在设计一个尤其是数据库使用分库分表的时候会常见的一个问题 特性: 全局唯一,这是基本要求,不能出现重复数字类型,趋势递增,后面的ID必须比前面的大长度短,能够提高查询效率,这也是从MySQL数据库规范出发的,尤其是ID作为主键时**信息安全,**如果ID连续生成,势必会泄露业务信息,所以需要无规则不规则高可用低延时,ID生成快,能够扛住高并发,延时足够低不至于成为业务瓶颈. 雪花算法: ​ sno

随机推荐