为什么选择 ULID 而不是传统的 UUID 或 ID 来识别数据库?
在创建自定义网络应用程序时,数据库的安全性非常重要。人们在创建数据库时最常犯的错误之一就是使用普通 ID。
使用常规 ID 不仅可以按时间顺序排列,而且只需在开发工具网络上进行检查即可看到,而且查找漏洞和逆向工程也会比使用网络应用程序容易 10 倍。
今天,我们将看到 UUID 和普通 ID 的一种替代方法。在过去的一年里,我在我所有的自定义网站应用程序中都采用了这种方法。
什么是 ULID
首先,你可以在这里阅读 ulid 规范,然后自己去看,不过我们还是要先了解一些重要的事实。ULID 是 Universally Unique Lexicographically Sortable Identifier 的缩写。顾名思义,它具有唯一性和可排序性,看起来像这样 01ARZ3NDEKTSV4RRFFQ69G5FAV
。
它几乎适用于所有语言,几乎可以在所有情况下取代其他两种标识符。换句话说,只要需要索引和分片,就可以使用 ULID。
兼容性
它与 UUID 兼容 128 位,这意味着它们大小相同,但长度更短。因此,你可以在数据库或对象存储系统中轻松替换 UUID。
它还可用于 Kafka 和 RabbitMQ。
此外,每毫秒可生成 1.21e+24 个唯一的 ULID。这个数字比 UUID 低还是高其实并不重要,因为这已经是一个非常大的数字了。
别忘了,ULID 比 UUID 对 URL 更友好。
特征 | ID (id ) |
UUID (uuid ) |
ULID (ulid ) |
格式 | Integer | 128-bit hexadecimal string | 128-bit string |
生成 | Sequential | Random or time-based | Time-based and random |
可读性 | Simple and short | Long and complex | Shorter, human-readable |
唯一性 | Not guaranteed across shards | Globally unique | Globally unique |
排序 | Yes | No | Yes |
生成速度 | Fastest | Slower than id |
Slower than id |
分布式系统可用性 | Poor | Excellent | Excellent |
基于时间 | No | Optional (UUID v1) | Yes |
冲突风险 | Low in single instance | Extremely low | Extremely low |
存储效率 | High | Lower | Lower |
实现复杂性 | None | More complex | Slightly more complex |
实现
它的实现非常简单。我将展示一个使用 Kotlin 和 Spring Boot 的示例来说明它有多简单。只需找到一个生成 ULID 的库并更新模型即可。
import com.github.f4b6a3.ulid.UlidCreator @Entity @Table(name = "users") data class UserModel( @Id var id: String = UlidCreator.getUlid().toString(), // other fields ) : UserDetails { // yourcode }
值得吗?
我不会一一说明 Ulid 更好的原因,但归根结底,这取决于你的个人喜好。我相信从长远来看,Ulid 会给你带来优势。即使你创建的是一个小的应用程序接口,尽早改用 Ulid 也是有好处的。在生产过程中不得不中途改变会很有挑战性。
结论
总之,ULID 为传统的 UUID 和简单的数字 ID 提供了令人信服的替代方案,尤其是对于同时要求唯一性和可排序性的应用而言。
ULID 与 UUID 标准兼容,再加上基于时间的生成和全局唯一性等特性,使其特别适用于对排序和可扩展性要求较高的分布式系统。虽然 ULID 的实现可能比基本 ID 略为复杂,但从系统性能和可维护性的长远利益来看,初期的努力是值得的。