四个id 生成器性能比较记录
IdGenerator
Seata 优化的雪花算法
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 生成器性能比较记录的更多相关文章
- 高并发场景下System.currentTimeMillis()的性能问题的优化 以及SnowFlakeIdWorker高性能ID生成器
package xxx; import java.sql.Timestamp; import java.util.concurrent.*; import java.util.concurrent.a ...
- id 生成器介绍
背景介绍 在一般的业务场景中, 初始的时候简单的自增数(比如MySQL 自增键)就可以很好的满足需求, 不过随着业务的发展和驱动, 尤其是在分布式的场景中, 如何生成全局的唯一 id 便成了需要慎重考 ...
- zookeepeer ID生成器 (一)
目录 写在前面 1.1. ZK 的分布式命名服务 1.1.1. 分布式 ID 生成器的类型 UUID方案 1.1.2. ZK生成分布式ID 写在最后 疯狂创客圈 亿级流量 高并发IM 实战 系列 疯狂 ...
- 分布式ID生成器的解决方案总结
在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID.退款ID等.那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决方案是十分重要 ...
- ID生成器的一种可扩展实现方案
ID生成器主要为了解决业务程序生成记录ID的场景,而一个好的ID生成器肯定要满足扩展性好.并发性好的特点,本文下面介绍一种满足上述特点的实现方案. 此方案的核心思想是:每次需要扩容机器时,将每个节点维 ...
- Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】(转)
前段时间细节的了解了Jedis的使用,Jedis是redis的java版本的客户端实现.本文做个总结,主要分享如下内容: [pipeline][分布式的id生成器][分布式锁[watch][multi ...
- 分布式唯一id生成器的想法
0x01 起因 前端时间遇到一个问题,怎么快速生成唯一的id,后来采用了hashid的方法.最近在网上读到了美团关于分布式唯一id生成器的解决方案, 其中提到了三种生成法:(建议看一下这篇文章,写得很 ...
- 百度开源的分布式 id 生成器
UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器.UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于d ...
- 全局唯一ID生成器
分布式环境中,如何保证生成的id是唯一不重复的? twitter,开源出了一个snowflake算法,现在很多企业都按照该算法作为参照,实现了自己的一套id生成器. 该算法的主要思路为: 刚好64位的 ...
- 基于Spring Boot的可直接运行的分布式ID生成器的实现以及SnowFlake算法详解
背景 最近对snowflake比较感兴趣,就看了一些分布式唯一ID生成器(发号器)的开源项目的源码,例如百度的uid-generator,美团的leaf.大致看了一遍后感觉uid-generator代 ...
随机推荐
- docker部署zabbix 6.0高可用集群实验
0 实验环境 虚拟机,postgresql本地部署,zabbix server及nginx容器部署 1 postgresql 参看前作 <postgresql + timescaledb离线安装 ...
- mysql中使用sql语句统计日志计算每天的访问量
日志建表语句: CREATE TABLE `syslog` ( `syslogid` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) ...
- 【NestJS系列】核心概念:Providers提供者
前言 Providers是Nest中的一个基本概念,许多Nest中定义的类都可以被视为一个Provider,比如:service.repository.factory.helper等,它们都可以通过c ...
- 2021-8-5 Mysql个人练习题
创建学校表格 CREATE TABLE `Student`( `s_id` VARCHAR(20), `s_name` VARCHAR(20) NOT NULL DEFAULT '', `s_birt ...
- git报错:error: Your local changes to the following files would be overwritten by checkout:
原因 原本想切换到dev分支,拉取远程dev分支,但我将分支上的数据修改了,此时切换分支报错 解决方案 方法一: 存到暂存区 # 暂存 git add . git stash 之后切换分支到dev,执 ...
- Builder 生成器模式简介与 C# 示例【创建型2】【设计模式来了_2】
〇.简介 1.什么是生成器模式? 一句话解释: 在构造一个复杂的对象(参数多且有可空类型)时,通过一个统一的构造链路,可选择的配置所需属性值,灵活实现可复用的构造过程. 生成器模式的重心,在于分离 ...
- 需求太多处理不过来?MoSCoW模型帮你
一.MoSCoW模型是什么 MoSCoW模型是在项目管理.软件开发中使用的一种排序优先级的方法,以便开发人员.产品经理.客户对每个需求交付的重要性达成共识. MoSCoW是一个首字母缩略词,代表: M ...
- 清理MySQL的binlog日志
前言 MySQL的binlog是以二进制形式打印的日志,没设置自动删除的话,时间长了就会占用大量存储空间.删除MySQL的binlog日志有两种方法:自动删除和手动删除. 自动删除 永久生效:修改My ...
- P8810 [蓝桥杯 2022 国 C] 数组个数 题解
思路比较简单的一道题. 用的五维 dp,看到二维和三维的 dp 直接膜了 orz. 正文开始. 分析 不难看出 dp. 因为 \(b_i\) 的值只与 \(a_{i-1},a_i,a_{i+1}\) ...
- 纯分享:将MySql的建表DDL转为PostgreSql的DDL
背景 现在信创是搞得如火如荼,在这个浪潮下,数据库也是从之前熟悉的Mysql换到了某国产数据库. 该数据库我倒是想吐槽吐槽,它是基于Postgre 9.x的基础上改的,至于改了啥,我也没去详细了解,当 ...