ULID(Universally Unique Lexicographically Sortable Identifier)是一种用于生成全局唯一、可按字典序排序的标识符的格式。ULID结合了时间戳和随机数的特性,旨在提供高性能、低碰撞、可排序和易读的标识符。

ULID(Universally Unique Lexicographically Sortable Identifier)是一种用于生成全局唯一、可按字典序排序的标识符的格式。ULID结合了时间戳和随机数的特性,旨在提供高性能、低碰撞、可排序和易读的标识符。

ULID的主要特点包括:

  1. 全局唯一性:通过结合时间戳和随机数的方式,ULID可以生成全局唯一的标识符,避免了碰撞的可能性。
  2. 按字典序排序:ULID生成的标识符是按照时间戳先后顺序排列的,可以方便地进行排序和比较。
  3. 性能优化:ULID的设计旨在提供高性能的生成过程,适用于需要频繁生成标识符的场景。
  4. 可读性:ULID采用了基于Crockford's Base32编码的方式,生成的标识符具有一定的可读性,不同于传统的UUID。

ULID的格式通常由 48 位长度组成,其中包含前缀时间戳和随机数部分。ULID的生成过程包括获取当前时间戳(以毫秒为单位)、生成随机数部分、将时间戳和随机数合并,并进行Base32编码等步骤。

为什么使用ULID:

  • 全局唯一性:ULID生成的标识符在分布式系统中具有全局唯一性,可以避免碰撞风险。
  • 排序能力:ULID生成的标识符可以按照时间戳顺序排序,方便数据库索引和查询操作。
  • 性能优化:ULID的设计考虑了高性能的生成过程,适用于需要频繁生成标识符的场景。
  • 可读性:ULID生成的标识符相对于传统的UUID更具可读性,便于人类阅读和理解。

 ULID作为一种全局唯一、可排序、高性能的标识符生成方案,适用于分布式系统、数据库主键、日志记录等各种场景,为应用程序提供了一种轻量级且有效的标识符生成方式。


ULID的概念最早由Codership的联合创始人Heikki Tuuri在2016年提出。ULID是作为UUID(Universally Unique Identifier)的另一种替代方案而被提出的,主要是为了解决UUID在排序和有效性验证方面的一些问题。

Heikki Tuuri设计ULID时,希望将其标识符设计成既具有全局唯一性,又可以按照时间排序,同时还可以进行有效地验证。ULID的设计灵感主要来自于MongoDB的ObjectID和Twitter的Snowflake,具有一定的可排序性和独特性。

ULID采用了时间戳与随机数结合的方式生成标识符,在保证全局唯一性的同时,还可以按照时间进行排序。ULID还比UUID更加紧凑,采用了32位字符编码,适合用在分布式系统中作为唯一识别符。

ULID的设计取得了一定的成功,被一些开源项目和公司所采用,并逐渐成为了一种常用的标识符生成方案。


ULID(Universally Unique Lexicographically Sortable Identifier)的发展可以分为以下几个阶段:

  1. 提出阶段(2016年):ULID最早由Codership的联合创始人Heikki Tuuri在2016年提出。他设计ULID的初衷是为了解决UUID在排序和有效性验证方面的一些问题,并希望将标识符设计成既具有全局唯一性,又可以按照时间排序,同时还可以进行有效地验证。

  2. 标准化和推广阶段:随着ULID的提出,它得到了一些开发者和社区的关注。ULID的设计被认为是一种有吸引力的解决方案,因为它综合了全局唯一性、可排序性和紧凑性等多个方面的优势。一些开源社区开始将ULID作为一种替代UUID的方案,并推广其使用。

  3. 应用拓展阶段:ULID的应用逐渐拓展到了各个领域,特别是在分布式系统和大规模应用中。由于ULID具有按时间排序和全局唯一的特性,使得它在事件日志、分布式系统中的数据标识和唯一性识别等方面得到了广泛应用。

  4. 工具和库的支持:随着ULID的普及,一些编程语言和平台开始提供ULID生成和处理的工具和库。这些工具和库使得开发者可以更方便地在他们的应用中使用ULID,进一步推动了ULID的发展和应用。

 ULID在短时间内取得了一定的成功,并成为了一种常用的标识符生成方案之一,其发展呈现出逐渐被接受和应用的趋势。


ULID的底层原理基于时间戳和随机数的结合,其设计目的是既要保证全局唯一性,又要能够按照时间排序,同时具备一定的紧凑性和可读性。下面是ULID的主要构成部分和底层原理:

  1. 时间戳(Timestamp):ULID的前10个字符是基于当前时间的时间戳。通常,ULID使用的是以自 UTC 1970年1月1日午夜起的毫秒数来表示的时间戳。这确保了在同一时间内生成的ULID会按照时间顺序进行排序。

  2. 随机数(Randomness):ULID的后面16个字符是由随机数生成的。这些字符提供了足够的随机性,以确保在同一毫秒内生成的ULID也能保持唯一性。

  3. 字符编码(Encoding):ULID使用的是Crockford's Base32编码(不包含符号),将时间戳和随机数转换为32个字符的字符串。Base32编码是一种将二进制数据转换为字符数据的编码方式,由32个字母和数字组成,具有紧凑性和可读性。

  4. 组合(Combining):ULID将时间戳和随机数组合在一起,形成一个128位的唯一标识符。


ULID的底层原理主要基于时间戳和随机数生成,使得生成的标识符具有全局唯一性、按时间排序和可读性较强的特点。下面是ULID的主要生成原理:

  1. 时间戳:ULID的前10个字符是基于当前时间戳生成的。通常采用的是自纪元(Epoch)以来的毫秒数,以确保生成的ULID可以按时间排序。时间戳部分的精度是最高的,因此可以确保在正常操作下生成的ULID是递增排序的。

  2. 随机数:ULID的后12个字符是随机生成的。为了保证全局唯一性,随机数部分采用了128位随机数生成算法。这些随机数以字节序列的形式添加到ULID中,确保了每个ULID都有足够的随机性,从而降低了碰撞的可能性。

  3. 编码:ULID使用Crockford's Base32编码将时间戳和随机数转换为可读的字符串形式。Base32编码是一种将字节序列转换为由32个字符组成的字符串的方法,它使用了数字0-9和大写字母A-Z,但排除了容易混淆的字符(如0、1、I、O)以提高可读性。

通过将时间戳和随机数结合并进行Base32编码,ULID生成了一个长度为26个字符的唯一标识符。由于时间戳部分在前面,所以可以按照时间排序,而随机数部分在后面,可以保证全局唯一性。这种设计使得ULID在分布式系统中具有较好的性能和可用性。


ULID(Universally Unique Lexicographically Sortable Identifier)的架构相对简单,它主要由两部分组成:时间戳和随机数。以下是ULID的基本架构:

  1. 时间戳部分:ULID的前10个字符是时间戳部分,通常采用自纪元(Epoch)以来的毫秒数表示。时间戳部分提供了ULID的排序信息,确保生成的ULID在一定程度上按时间顺序排列。这使得ULID在分布式系统中可以基于时间进行排序,有助于提高数据的可读性和可查询性。

  2. 随机数部分:ULID的后12个字符是随机数部分,采用128位随机数生成算法生成。随机数部分提供了ULID的全局唯一性。通过添加随机数部分,即使在相同的时间戳下,也可以生成不同的ULID,从而减少了碰撞的可能性。

  3. Base32编码:生成的时间戳和随机数部分被转换成Base32编码,生成ULID的最终字符串表示。Base32编码使用了数字0-9和大写字母A-V(排除了易混淆的字符),使得ULID具有较好的可读性和紧凑性。

整体架构简单明了,ULID的设计旨在提供一种轻量级、易于实现和使用的唯一标识符方案,同时兼顾了全局唯一性、按时间排序和可读性等方面的需求。这使得ULID在分布式系统中广泛应用,成为了UUID的一种替代方案。


ULID(Universally Unique Lexicographically Sortable Identifier)由于其全局唯一性、按时间排序和可读性等特点,在许多应用场景中都得到了广泛的应用。以下是一些常见的ULID应用场景:

  1. 数据库主键:ULID可以作为数据库表的主键,特别适用于分布式系统中需要保证数据唯一性和按时间排序的场景。由于ULID是按时间排序的,可以在数据库中很方便地进行范围查询和排序操作。

  2. 日志跟踪:在日志系统中,ULID可以作为唯一标识符,用于跟踪和识别日志条目。由于ULID是按时间排序的,可以方便地查找和分析日志数据,并且不会有重复或混乱的情况发生。

  3. 分布式系统:在分布式系统中,ULID可以作为全局唯一的标识符,用于标识分布式系统中的各种资源和实体。通过ULID,可以避免因为不同节点生成相同的标识符而导致的冲突和数据一致性问题。

  4. 消息队列:在消息队列系统中,ULID可以作为消息的唯一标识符,确保消息在系统中的唯一性和顺序性。这对于消息队列系统的数据一致性和顺序性是非常重要的。

  5. 分布式事务:在分布式事务处理中,ULID可以用作事务ID,用于跟踪和管理分布式事务的执行状态。ULID的全局唯一性和按时间排序的特性可以帮助系统更好地管理和监控分布式事务。

  6. 分布式锁管理:在分布式系统中,为了避免多个节点同时操作同一资源而产生的竞态条件,可以使用 ULID 作为唯一标识符来管理分布式锁。每个节点可以生成一个 ULID 作为锁的标识符,以确保每个锁的唯一性。

  7. 实时数据流处理:在实时数据流处理系统中,ULID 可以用作事件的唯一标识符。通过 ULID,可以轻松地对事件进行排序和追溯,以便进行实时分析和处理。

  8. 唯一文件名生成:在文件系统中,ULID 可以用作唯一文件名的生成器。生成的文件名具有全局唯一性,同时由于 ULID 是按时间排序的,所以文件名也能够根据创建时间进行排序。

  9. 版本控制系统:在版本控制系统中,ULID 可以用作提交的唯一标识符。通过 ULID,可以确保每个提交的唯一性,并且可以根据提交时间进行排序,方便进行版本管理和代码审查。

  10. 唯一会话标识符:在网络应用中,ULID 可以用作会话标识符,用于跟踪用户的会话状态。由于 ULID 具有全局唯一性,因此可以确保每个用户会话都有一个唯一的标识符。

  11. 分布式任务调度:在分布式任务调度系统中,ULID 可以用作任务的唯一标识符。通过 ULID,可以确保每个任务的唯一性,并且可以根据创建时间进行排序,方便进行任务调度和管理。

  1. 数据同步和复制:在分布式系统中,需要进行数据同步和复制时,可以使用 ULID 作为数据记录的唯一标识符。通过 ULID,可以轻松地追踪和管理数据的同步和复制过程,确保数据的一致性和完整性。

  2. 跨系统数据关联:在不同系统之间需要关联数据时,可以使用 ULID 作为数据的唯一标识符。通过 ULID,可以确保数据的唯一性,并且可以轻松地在不同系统之间进行数据关联和传递。

  3. 分布式任务队列:在分布式任务队列系统中,ULID 可以用作任务的唯一标识符。通过 ULID,可以确保每个任务的唯一性,并且可以根据创建时间进行排序,方便进行任务调度和管理。

  4. 审计日志:在系统中需要记录审计日志时,可以使用 ULID 作为日志条目的唯一标识符。通过 ULID,可以轻松地追踪和管理审计日志,确保日志的完整性和可靠性。

  5. 消息序列化:在消息传递系统中,可以使用 ULID 来序列化消息。通过 ULID,可以确保消息的唯一性,并且可以根据创建时间对消息进行排序,方便消息的传递和处理。

  6. 数据备份和恢复:在进行数据备份和恢复时,可以使用 ULID 作为备份数据的唯一标识符。通过 ULID,可以轻松地管理备份数据,并且可以根据创建时间进行备份数据的排序和检索。

 ULID在需要唯一标识符、按时间排序和可读性等方面的应用场景中都表现出色,成为了许多分布式系统和应用程序中的首选标识符方案之一。


在 PowerShell 中,你可以使用以下命令生成 Windows 的 ULID(Universally Unique Lexicographically Sortable Identifier):

powershellCopy Code
Add-Type -TypeDefinition @"
using System;

public class Ulid
{
    private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    private static readonly Random Random = new Random();

    public static string NewUlid()
    {
        byte[] random = new byte[10];
        Random.NextBytes(random);
        long milliseconds = (DateTime.UtcNow - UnixEpoch).Ticks / 10000;
        byte[] time = BitConverter.GetBytes(milliseconds);

        Array.Reverse(time);
        byte[] ulidBytes = new byte[16];
        Buffer.BlockCopy(time, 2, ulidBytes, 0, 6);
        Buffer.BlockCopy(random, 0, ulidBytes, 6, 10);

        return EncodeBase32(ulidBytes);
    }

    private static string EncodeBase32(byte[] data)
    {
        const string base32Chars = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
        const int size = 13;
        var sb = new System.Text.StringBuilder(size);
        int buffer = data[0];
        int next = 1;
        int bitsLeft = 8;
        while (bitsLeft > 0 || next < data.Length)
        {
            if (bitsLeft < 5)
            {
                if (next < data.Length)
                {
                    buffer <<= 8;
                    buffer |= data[next++] & 0xFF;
                    bitsLeft += 8;
                }
                else
                {
                    int pad = 5 - bitsLeft;
                    buffer <<= pad;
                    bitsLeft += pad;
                }
            }
            int index = 0x1F & (buffer >> (bitsLeft - 5));
            bitsLeft -= 5;
            sb.Append(base32Chars[index]);
        }
        return sb.ToString();
    }
}
"@

[Ulid]::NewUlid()

运行以上 PowerShell 命令,将会生成一个 ULID 格式的字符串作为输出。这个 ULID 是根据当前时间和随机数生成的全局唯一标识符,符合 ULID 格式规范。


PowerShell 中,注册表路径应该使用根键的名称来指定,而不是直接指向文件系统路径。

尝试使用以下命令来获取 MachineGuid 的值:

powershellCopy Code
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Cryptography" | Select-Object -Property MachineGuid

这条命令中,我们将注册表路径改为 HKLM:\SOFTWARE\Microsoft\Cryptography,并使用 Get-ItemProperty 命令来获取 MachineGuid 的值。这样应该就能成功读取注册表中的 MachineGuid 值了。


需要生成 48 位长度的 Windows ULID,可以使用以下 PowerShell 脚本:

powershellCopy Code
function New-Ulid {
    $base32Chars = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"

    $timeBytes = [BitConverter]::GetBytes([DateTime]::UtcNow.Ticks)
    $randomBytes = [byte[]]::new(10)
    [System.Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($randomBytes)

    $ulidBytes = $timeBytes[6..11] + $randomBytes

    $sb = [System.Text.StringBuilder]::new()
    $buffer = $ulidBytes[0]
    $next = 1
    $bitsLeft = 8

    while ($bitsLeft -gt 0 -or $next -lt 16) {
        if ($bitsLeft -lt 5) {
            if ($next -lt 16) {
                $buffer = $buffer -shl 8
                $buffer = $buffer -bor $ulidBytes[$next]
                $next += 1
                $bitsLeft += 8
            } else {
                $pad = 5 - $bitsLeft
                $buffer = $buffer -shl $pad
                $bitsLeft += $pad
            }
        }
        $index = 0x1F -band ($buffer -shr ($bitsLeft - 5))
        $bitsLeft -= 5
        $sb.Append($base32Chars[$index])
    }

    return $sb.ToString()
}

New-Ulid

请尝试在 PowerShell 中运行这段代码,它将生成一个符合 ULID 规范的 48 位长度的 Windows ULID 字符串。


 

posted @ 2024-03-04 10:34  suv789  阅读(88)  评论(0编辑  收藏  举报