唯一标识符是软件开发的基础,尤其是在分布式系统中,确保跨多个节点的唯一性至关重要。
虽然 UUID(通用唯一标识符)多年来一直是行业标准,但 ULID(通用唯一词典可排序标识符)在某些情况下正在成为一种更好的替代方案。
本文将深入探讨 UUID 和 ULID 的技术复杂性、它们的实际应用,以及如何在 .NET 中实现它们,重点关注性能和可伸缩性。
UUID 或 .NET 中的 GUID(全局唯一标识符)是设计为全局唯一的 128 位数字。UUID 的标准格式为:
AFDF5738–6A8E-4 D1A-9 0DB-E894A3828320
若要在 .NET 中生成 UUID,请使用该类:Guid
Guid newGuid = Guid.NewGuid();
Console.WriteLine(newGuid.ToString());
UUID,尤其是版本 4,是高度随机的。这种随机性在确保唯一性的同时,由于索引效率低下,可能会导致数据库出现性能瓶颈。顺序 UUID(例如版本 1)在一定程度上缓解了这种情况,但可能会公开时间戳信息,这可能是不可取的。
ULID 解决了 UUID 的一些性能和排序限制。它们将时间戳与随机数据相结合,以创建可按字典排序的 128 位标识符。典型的 ULID 如下所示:
01HZW2RKF63AWC1BT901FPGRGT
Ulid Sturcture 解释 — 图片来源在这里
首先,通过 NuGet 安装包,并生成:Ulid
dotnet add package Ulidusing System;
using NUlid;
class Program
{
static void Main()
{
Ulid newUlid = Ulid.NewUlid();
Console.WriteLine(newUlid.ToString());
}
}
在数据库中使用 ULID 可以大大提高索引效率。由于 ULID 可按其时间戳组件进行排序,因此它们可以保持插入顺序,从而减少碎片并提高读写性能。
示例:实体框架集成
若要在 Entity Framework 中利用 ULID,可以将模型配置为使用 ULID 作为主键:
public class Order
{
[Key]
public Ulid OrderId { get; set; }
public DateTime OrderDate { get; set; }
// Other properties
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.Property(o => o.OrderId)
.HasConversion(
v => v.ToString(),
v => Ulid.Parse(v));
}
在分布式系统中,ULID 的独特性和可排序性使其成为时间顺序很重要的场景(例如日志记录和事件溯源)的理想选择。
示例:在分布式环境中实施 ULID
public class DistributedEvent
{
public Ulid EventId { get; set; }
public string EventData { get; set; }
public DateTimeOffset Timestamp { get; set; }
}
public class EventService
{
public void LogEvent(string eventData)
{
var distributedEvent = new DistributedEvent
{
EventId = Ulid.NewUlid(),
EventData = eventData,
Timestamp = DateTimeOffset.UtcNow
};
// Save to database or send to event queue
}
}
虽然 UUID 是生成唯一标识符的可靠解决方案,但它们在随机性和索引效率低下的局限性在高性能应用程序中可能非常严重。ULID 提供了一种引人注目的替代方案,提供相同级别的唯一性,并具有词典分类和改进的可读性等额外优势。您可以增强应用程序的性能、可伸缩性和可维护性。