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. 详解TCP网络协议栈的工作原理

    本文分享自华为云社区<网络通信的神奇之旅:解密Linux TCP网络协议栈的工作原理>,作者: Lion Long . 一.TCP网络开发API TCP,全称传输控制协议(Transmis ...

  2. TodoList - 开源研究系列文章

    接着上次的代码,整理出一个待办列表的程序,比较简单易用,读者可自行修改成自己需要的程序. 1.        项目目录: 目录见下图,对代码进行了划分,比较简单.主处理类在Helper目录里. 2.  ...

  3. Nacos启动时报错No DataSource set排查

    问题描述 最近在学习Nacos组件,使用的是最新版本:2.2.3. 在本地虚拟机CentOS 8.5.2111环境中安装Nacos,并使用standalone模式启动,同时配置使用外部MySQL数据库 ...

  4. Pandas:获取Dataframe索引

    解决方案 效果图 参考链接 https://blog.csdn.net/YENTERTAINR/article/details/109254583

  5. openpyxl 设置单元格自动换行

    解决方案 openpyxl的alignment函数中的参数:wrapText=True,就可以了 from openpyxl.styles import Alignment worksheet.cel ...

  6. 数据处理的那些事「GitHub 热点速览」

    撇开一屏占四分之三屏幕的 AI 相关项目之外,本周剩下的热榜项目就是同数据有关的数据库项目,比如 CockroachDB 团队开源的 kv 存储数据库 pebble,旨在提供高性能的消息队列 blaz ...

  7. springboot jar thin

    springboot jar thin springboot 应用 jar 瘦身.springboot jar 太大.jar与依赖包分离. 两种方法,第一种,spring-boot-thin-laun ...

  8. Blazor前后端框架Known-V1.2.13

    V1.2.13 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行. Gitee: https://gitee.com/known/Known Git ...

  9. 手写RISC-V处理器(1)

    由来 由于去年工作变动,有幸进入了芯片行业,但主要工作内容为基于RISC-V的嵌入式应用软件开发,几乎接触不到芯片设计的相关知识,然而随着工作的深入,越来越想探究一下运行在软件之下的CPU的世界,于是 ...

  10. Hugging News #0821: Hugging Face 完成 2.35 亿美元 D 轮融资

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...