五个id生成器性能比较记录

Ulid

ULID :Universally Unique Lexicographically Sortable Identifier(通用唯一词典分类标识符)

c# 实现库 : https://github.com/Cysharp/Ulid

ULID特性

ulid() # 01ARZ3NDEKTSV4RRFFQ69G5FAV

  • 与UUID的128位兼容性
  • 每毫秒1.21e + 24个唯一ULID
  • 按字典顺序(也就是字母顺序)排序!
  • 规范地编码为26个字符串,而不是UUID的36个字符
  • 使用Crockford的base32获得更好的效率和可读性(每个字符5位)
  • 不区分大小写
  • 没有特殊字符(URL安全)
  • 单调排序顺序(正确检测并处理相同的毫秒)

二进制布局和字节顺序

组件被编码为16个八位位组。每个组件都以最高有效字节在前(网络字节顺序)进行编码。


0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      32_bit_uint_time_high                    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     16_bit_uint_time_low      |       16_bit_uint_random      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       32_bit_uint_random                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       32_bit_uint_random                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

应用场景

替换数据库自增id,无需DB参与主键生成
分布式环境下,替换UUID,全局唯一且毫秒精度有序
比如要按日期对数据库进行分区分表,可以使用ULID中嵌入的时间戳来选择正确的分区分表
如果毫秒精度是可以接受的(毫秒内无序),可以按照ULID排序,而不是单独的created_at字段

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

Guid 结构 (System) | Microsoft Learn

全局唯一标识符(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,
            SeqBitLength = 12,
        };
        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();

    [Benchmark]
    public string NewUlid() => Ulid.NewUlid().ToString();
}

结果


BenchmarkDotNet v0.13.12, 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 8.0.100
  [Host]     : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
  DefaultJob : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2


MethodMeanErrorStdDevStdErrMedianMinQ1Q3MaxOp/s
IdGeneratorNewId243.39 ns3.468 ns3.244 ns0.837 ns244.00 ns237.82 ns241.23 ns245.76 ns247.94 ns4,108,554.1
SIdGeneratorNewId90.68 ns0.645 ns0.571 ns0.153 ns90.62 ns89.52 ns90.30 ns91.07 ns91.83 ns11,027,339.7
YitIdHelperNextId241.24 ns66.403 ns195.790 ns19.579 ns431.44 ns42.29 ns42.47 ns432.25 ns433.03 ns4,145,275.0
NewGuid74.77 ns0.575 ns0.480 ns0.133 ns74.56 ns74.03 ns74.48 ns75.05 ns75.66 ns13,374,344.2
NanoidGenerate174.51 ns2.040 ns1.909 ns0.493 ns173.68 ns171.78 ns173.11 ns175.80 ns178.33 ns5,730,341.9
NewUlid54.37 ns0.190 ns0.169 ns0.045 ns54.36 ns54.17 ns54.25 ns54.44 ns54.71 ns18,391,966.4

ps: 之前少了 ulid,现已补上, 换用 .net8之后 guid 有明显性能变化,而其余算法可能由于自身设计,没有明显变化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园信息化系统解决方案旨在通过先进的信息技术,实现教育的全方位创新和优质资源的普及共享。该方案依据国家和地方政策背景,如教育部《教育信息化“十三五”规划》和《教育信息化十年发展规划》,以信息技术的革命性影响为指导,推进教育信息化建设,实现教育思想和方法的创新。 技术发展为智慧校园建设提供了强有力的支撑。方案涵盖了互连互通、优质资源共享、宽带网络、移动APP、电子书包、电子教学白板、3D打印、VR虚拟教学等技术应用,以及大数据和云计算技术,提升了教学数据记录和分析水平。此外,教育资源公共服务平台、教育管理公共服务平台等平台建设,进一步提高了教学、管控的效率。 智慧校园系统由智慧教学、智慧管控和智慧办公三大部分组成,各自具有丰富的应用场景。智慧教学包括微课、公开课、精品课等教学资源的整合和共享,支持在线编辑、录播资源、教学分析等功能。智慧管控则通过平安校园、可视对讲、紧急求助、视频监控等手段,保障校园安全。智慧办公则利用远程视讯、无纸化会议、数字会议等技术,提高行政效率和会议质量。 教育录播系统作为智慧校园的重要组成部分,提供了一套满足学校和教育局需求的解决方案。它包括标准课室、微格课室、精品课室等,通过自动五机位方案、高保真音频采集、一键式录课等功能,实现了优质教学资源的录制和共享。此外,录播系统还包括互动教学、录播班班通、教育中控、校园广播等应用,促进了教育资源的均衡化发展。 智慧办公的另一重点是无纸化会议和数字会议系统的建设,它们通过高效的文件管理、会议文件保密处理、本地会议的音频传输和摄像跟踪等功能,实现了会议的高效化和集中管控。这些系统不仅提高了会议的效率和质量,还通过一键管控、无线管控等设计,简化了操作流程,使得会议更加便捷和环保。 总之,智慧校园信息化系统解决方案通过整合先进的信息技术和教学资源,不仅提升了教育质量和管理效率,还为实现教育均衡化和资源共享提供了有力支持,推动了教育现代化的进程。
智慧校园信息化系统解决方案旨在通过先进的信息技术,实现教育的全方位创新和优质资源的普及共享。该方案依据国家和地方政策背景,如教育部《教育信息化“十三五”规划》和《教育信息化十年发展规划》,以信息技术的革命性影响为指导,推进教育信息化建设,实现教育思想和方法的创新。 技术发展为智慧校园建设提供了强有力的支撑。方案涵盖了互连互通、优质资源共享、宽带网络、移动APP、电子书包、电子教学白板、3D打印、VR虚拟教学等技术应用,以及大数据和云计算技术,提升了教学数据记录和分析水平。此外,教育资源公共服务平台、教育管理公共服务平台等平台建设,进一步提高了教学、管控的效率。 智慧校园系统由智慧教学、智慧管控和智慧办公三大部分组成,各自具有丰富的应用场景。智慧教学包括微课、公开课、精品课等教学资源的整合和共享,支持在线编辑、录播资源、教学分析等功能。智慧管控则通过平安校园、可视对讲、紧急求助、视频监控等手段,保障校园安全。智慧办公则利用远程视讯、无纸化会议、数字会议等技术,提高行政效率和会议质量。 教育录播系统作为智慧校园的重要组成部分,提供了一套满足学校和教育局需求的解决方案。它包括标准课室、微格课室、精品课室等,通过自动五机位方案、高保真音频采集、一键式录课等功能,实现了优质教学资源的录制和共享。此外,录播系统还包括互动教学、录播班班通、教育中控、校园广播等应用,促进了教育资源的均衡化发展。 智慧办公的另一重点是无纸化会议和数字会议系统的建设,它们通过高效的文件管理、会议文件保密处理、本地会议的音频传输和摄像跟踪等功能,实现了会议的高效化和集中管控。这些系统不仅提高了会议的效率和质量,还通过一键管控、无线管控等设计,简化了操作流程,使得会议更加便捷和环保。 总之,智慧校园信息化系统解决方案通过整合先进的信息技术和教学资源,不仅提升了教育质量和管理效率,还为实现教育均衡化和资源共享提供了有力支持,推动了教育现代化的进程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值