IdGenerator

Seata 优化的雪花算法

Seata基于改良版雪花算法的分布式UUID生成器分析

关于新版雪花算法的答疑

csharp 移植代码

    public class IdGenerator
{
private readonly long twepoch = 1588435200000L;
private const int workerIdBits = 10;
private const int timestampBits = 41;
private const int sequenceBits = 12;
private const int maxWorkerId = ~(-1 << workerIdBits);
private long workerId;
private long timestampAndSequence;
private readonly long timestampAndSequenceMask = ~(-1L << (timestampBits + sequenceBits)); public static readonly IdGenerator Instance = new IdGenerator(GenerateWorkerId()); public IdGenerator(long workerId)
{
InitTimestampAndSequence();
InitWorkerId(workerId);
} private void InitTimestampAndSequence()
{
long timestamp = GetNewestTimestamp();
long timestampWithSequence = timestamp << sequenceBits;
this.timestampAndSequence = timestampWithSequence;
} private void InitWorkerId(long workerId)
{
if (workerId > maxWorkerId || workerId < 0)
{
string message = string.Format("worker Id can't be greater than {0} or less than 0", maxWorkerId);
throw new ArgumentException(message);
}
this.workerId = workerId << (timestampBits + sequenceBits);
} public long NextId()
{
WaitIfNecessary();
long next = Interlocked.Increment(ref timestampAndSequence);
long timestampWithSequence = next & timestampAndSequenceMask;
return workerId | timestampWithSequence;
} public static long NewId()
{
return Instance.NextId();
} private void WaitIfNecessary()
{
long currentWithSequence = timestampAndSequence;
long current = currentWithSequence >> sequenceBits;
long newest = GetNewestTimestamp();
if (current >= newest)
{
Thread.Sleep(5);
}
} private long GetNewestTimestamp()
{
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - twepoch;
} public static long GenerateWorkerId()
{
try
{
return GenerateWorkerIdBaseOnK8S();
}
catch (Exception)
{
try
{
return GenerateWorkerIdBaseOnMac();
}
catch (Exception)
{
return GenerateRandomWorkerId();
}
}
} public static long GenerateWorkerIdBaseOnMac()
{
IEnumerable<NetworkInterface> all = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface networkInterface in all)
{
bool isLoopback = networkInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback;
//bool isVirtual = networkInterface.;
//if (isLoopback || isVirtual)
if (isLoopback)
{
continue;
}
byte[] mac = networkInterface.GetPhysicalAddress().GetAddressBytes();
return ((mac[4] & 0B11) << 8) | (mac[5] & 0xFF);
}
throw new Exception("no available mac found");
} public static long GenerateWorkerIdBaseOnK8S()
{
return GenerateWorkerIdBaseOnString(Environment.GetEnvironmentVariable("K8S_POD_ID"));
} public static long GenerateWorkerIdBaseOnString(string str)
{
ArgumentNullException.ThrowIfNull(str, nameof(str));
int hashValue = 0;
int cc = 2 << (workerIdBits - 1);
foreach (char c in str)
{
hashValue = (hashValue * 31 + c) % cc;
}
return hashValue + 1;
} public static long GenerateRandomWorkerId()
{
return Random.Shared.NextInt64(maxWorkerId + 1);
}
}

YitIdHelper

开源库 https://github.com/yitter/IdGenerator

这是优化的雪花算法(雪花漂移),它生成的ID更短、速度更快。

支持 k8s 等容器环境自动扩容(自动注册 WorkerId),可在单机或分布式环境生成数字型唯一ID。

Guid

https://learn.microsoft.com/zh-cn/dotnet/api/system.guid?view=net-7.0

全局唯一标识符(GUID,Globally Unique Identifier)是一种由算法生成的二进制长度为128位的数字标识符。GUID主要用于在拥有多个节点、多台计算机的网络或系统中。

Nanoid

开源库 https://github.com/codeyu/nanoid-net

一个小巧、安全、URL友好、唯一的字符串ID生成器。

“一个惊人的无意义的完美主义水平,这简直让人无法不敬佩。”

  • 小巧. 130字节 (经过压缩和gzip处理)。没有依赖。Size Limit 控制大小。
  • 安全. 它使用硬件随机生成器。可在集群中使用。
  • 紧凑. 它使用比 UUID(A-Za-z0-9_-)更大的字母表。因此,ID 大小从36个符号减少到21个符号。
  • 可移植. Nano ID 已被移植到 20种编程语言。

Nano ID 与 UUID v4 (基于随机数) 相当。 它们在 ID 中有相似数量的随机位 (Nano ID 为126,UUID 为122),因此它们的碰撞概率相似::

要想有十亿分之一的重复机会, 必须产生103万亿个版本4的ID.

Nano ID 和 UUID v4之间有两个主要区别:

Nano ID 使用更大的字母表,所以类似数量的随机位 被包装在21个符号中,而不是36个。

Nano ID 代码比 uuid/v4 包少 4倍: 130字节而不是423字节.

性能测试代码

[AllStatisticsColumn]
public class IdGeneratorTest
{
public IdGeneratorTest()
{
var options = new IdGeneratorOptions()
{
WorkerId = 55,
WorkerIdBitLength = 6
};
YitIdHelper.SetIdGenerator(options);
} [Benchmark]
public long IdGeneratorNewId() => IdGenerator.NewId(); [Benchmark]
public long YitIdHelperNextId() => YitIdHelper.NextId(); [Benchmark]
public string NewGuid() => Guid.NewGuid().ToString(); [Benchmark]
public string NanoidGenerate() => Nanoid.Generate();
}

结果


BenchmarkDotNet v0.13.10, Windows 11 (10.0.22000.2538/21H2/SunValley)
Intel Core i7-10700 CPU 2.90GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK 7.0.403
[Host] : .NET 6.0.24 (6.0.2423.51814), X64 RyuJIT AVX2
DefaultJob : .NET 6.0.24 (6.0.2423.51814), X64 RyuJIT AVX2
Method Mean Error StdDev StdErr Median Min Q1 Q3 Max Op/s
IdGeneratorNewId 243.3 ns 1.33 ns 1.25 ns 0.32 ns 243.0 ns 241.42 ns 242.32 ns 244.3 ns 246.1 ns 4,109,814.4
YitIdHelperNextId 241.7 ns 66.08 ns 194.85 ns 19.48 ns 430.2 ns 43.51 ns 43.83 ns 431.8 ns 432.7 ns 4,137,225.0
NewGuid 179.5 ns 3.63 ns 6.06 ns 1.01 ns 177.1 ns 173.10 ns 175.06 ns 182.5 ns 193.3 ns 5,572,366.5
NanoidGenerate 188.6 ns 4.30 ns 12.21 ns 1.27 ns 185.1 ns 174.49 ns 179.40 ns 195.5 ns 219.8 ns 5,301,348.8

四个id 生成器性能比较记录的更多相关文章

  1. 高并发场景下System.currentTimeMillis()的性能问题的优化 以及SnowFlakeIdWorker高性能ID生成器

    package xxx; import java.sql.Timestamp; import java.util.concurrent.*; import java.util.concurrent.a ...

  2. id 生成器介绍

    背景介绍 在一般的业务场景中, 初始的时候简单的自增数(比如MySQL 自增键)就可以很好的满足需求, 不过随着业务的发展和驱动, 尤其是在分布式的场景中, 如何生成全局的唯一 id 便成了需要慎重考 ...

  3. zookeepeer ID生成器 (一)

    目录 写在前面 1.1. ZK 的分布式命名服务 1.1.1. 分布式 ID 生成器的类型 UUID方案 1.1.2. ZK生成分布式ID 写在最后 疯狂创客圈 亿级流量 高并发IM 实战 系列 疯狂 ...

  4. 分布式ID生成器的解决方案总结

    在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID.退款ID等.那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决方案是十分重要 ...

  5. ID生成器的一种可扩展实现方案

    ID生成器主要为了解决业务程序生成记录ID的场景,而一个好的ID生成器肯定要满足扩展性好.并发性好的特点,本文下面介绍一种满足上述特点的实现方案. 此方案的核心思想是:每次需要扩容机器时,将每个节点维 ...

  6. Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】(转)

    前段时间细节的了解了Jedis的使用,Jedis是redis的java版本的客户端实现.本文做个总结,主要分享如下内容: [pipeline][分布式的id生成器][分布式锁[watch][multi ...

  7. 分布式唯一id生成器的想法

    0x01 起因 前端时间遇到一个问题,怎么快速生成唯一的id,后来采用了hashid的方法.最近在网上读到了美团关于分布式唯一id生成器的解决方案, 其中提到了三种生成法:(建议看一下这篇文章,写得很 ...

  8. 百度开源的分布式 id 生成器

    UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器.UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于d ...

  9. 全局唯一ID生成器

    分布式环境中,如何保证生成的id是唯一不重复的? twitter,开源出了一个snowflake算法,现在很多企业都按照该算法作为参照,实现了自己的一套id生成器. 该算法的主要思路为: 刚好64位的 ...

  10. 基于Spring Boot的可直接运行的分布式ID生成器的实现以及SnowFlake算法详解

    背景 最近对snowflake比较感兴趣,就看了一些分布式唯一ID生成器(发号器)的开源项目的源码,例如百度的uid-generator,美团的leaf.大致看了一遍后感觉uid-generator代 ...

随机推荐

  1. docker部署zabbix 6.0高可用集群实验

    0 实验环境 虚拟机,postgresql本地部署,zabbix server及nginx容器部署 1 postgresql 参看前作 <postgresql + timescaledb离线安装 ...

  2. ABP 的ajax请求错误:400 Empty or invalid anti forgery header token.

    ABP 的ajax请求错误 记录于2018-03-22 13:31:16 星期四 错误信息:400 Empty or invalid anti forgery header token. 我从网上找到 ...

  3. Element-ui源码解析(一):项目目录解析

    开始看原码了,我们要开始一些准备工作, 既然是拆代码,那么我们要先把代码搞到手 1.如何下载原码  随便开个项目 npm i element-ui -S 将源码下载到本地 随后在node_module ...

  4. pycharm中使用命令行

    //调用django命令 tools->Run manage.py... ->弹出窗口->输入命令,回车 //创建appstartapp [appname] //数据库迁移makem ...

  5. UiAutomator2.0(转)

    1.     概述 UI测试(功能测试.黑盒测试)不需要测试者了解应用程序的内部实现细节,只需要知道当执行了某些特定的动作后是否会得到其预期的输出.这种测试方法,在团队合作中可以更好地分离的开发和测试 ...

  6. [POI2007]GRZ-Ridges and Valleys 题解

    (2022-12-28 ) AcWing 1106 洛谷 P3456 题目大意 找出一个图中所有大于(或小于)周围相邻的非连通块点的所有连通块个数. 就是说,对于一个连通块: 如果它周围的点都低于它, ...

  7. Weblogic T3协议反序列化命令执行漏洞(CVE-2018- 2628)复现

    好久没发新文章了,躲懒了,是时候该更新一篇了,这一篇是关于WebLogic T3协议反序列化命令执行漏洞(CVE-2018- 2628)的复现,该漏洞是weblogic的经典漏洞,而网上有关的复现稍显 ...

  8. CVE-2020-0796 SMB远程代码执行漏洞复现

    前言: 这个windows的永恒之黑漏洞,不得不复现一下啦! 这个漏洞诸多大佬都已经复现了,现在跟随大佬的脚步,逐个复现一下: 可参考:https://www.adminxe.com/1220.htm ...

  9. CAJViewer卡的解决办法

    在做毕业设计时,使用了CAJViewer7.2版本的阅读器,使用起来非常卡,翻页总是不流畅,体验感极差. 最后实在受不了了,去百度了一下,在贴吧中看到了疑似解决方案,尝试了一下,真的不卡了.所以特此写 ...

  10. ATtiny88初体验(六):SPI

    ATtiny88初体验(六):SPI SPI介绍 ATtiny88自带SPI模块,可以实现数据的全双工三线同步传输.它支持主从两种模式,可以配置为LSB或者MSB优先传输,有7种可编程速率,支持从空闲 ...