除了UUID,还有什么更好的方案?

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

042ca9f4150a714ac3117c33266a4d91.gif

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、CRM 等等功能:

  • Boot 仓库:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • Cloud 仓库:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本 

来源:blog.csdn.net/pushiqiang
/article/details/117365290

ea55ec9cfd64216e0a452218a0039090.jpeg


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

为什么不选择UUID

UUID 目前有 5 个版本:

版本1:在许多环境中是不切实际的,因为它需要访问唯一的,稳定的MAC地址,容易被攻击;
版本2:将版本 1 的时间戳前四位换为 POSIX 的 UID 或 GID,问题同上;
版本3:基于 MD5 哈希算法生成,生成随机分布的ID需要唯一的种子,这可能导致许多数据结构碎片化;
版本4:基于随机数或伪随机数生成,除了随机性外没有提供其他信息;
版本5:通过 SHA-1 哈希算法生成,生成随机分布的ID需要唯一的种子,这可能导致许多数据结构碎片化;

这里面常用的就是 UUID4 了,但是,即使是随机的,但是也是存在冲突的风险。
和 UUID 要么基于随机数,要么基于时间戳不同,ULID 是既基于时间戳又基于随机数,时间戳精确到毫秒,毫秒内有1.21e + 24个随机数,不存在冲突的风险,而且转换成字符串比 UUID 更加友好。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

ULID特性:

ulid() # 01ARZ3NDEKTSV4RRFFQ69G5FAV
  • 与UUID的128位兼容性

  • 每毫秒1.21e + 24个唯一ULID

  • 按字典顺序(也就是字母顺序)排序!

  • 规范地编码为26个字符串,而不是UUID的36个字符

  • 使用Crockford的base32获得更好的效率和可读性(每个字符5位)

  • 不区分大小写

  • 没有特殊字符(URL安全)

  • 单调排序顺序(正确检测并处理相同的毫秒)

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

ULID规范

以下是在python(ulid-py)中实现的ULID的当前规范。二进制格式已实现

01AN4Z07BY      79KA1307SR9X4MV3

|----------|    |----------------|
 Timestamp          Randomness
  10chars            16chars
   48bits             80bits

组成

时间戳
  • 48位整数

  • UNIX时间(以毫秒为单位)

  • 直到公元10889年,空间都不会耗尽。

随机性
  • 80位随机数

  • 如果可能的话,采用加密技术保证随机性

排序

最左边的字符必须排在最前面,最右边的字符必须排在最后(词汇顺序)。必须使用默认的ASCII字符集。在同一毫秒内,不能保证排序顺序

编码方式

如图所示,使用了Crockford的Base32。该字母表不包括字母I,L,O和U,以避免混淆和滥用。

0123456789ABCDEFGHJKMNPQRSTVWXYZ
二进制布局和字节顺序

组件被编码为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字段

用法(python)

安装

pip install ulid-py

创建一个全新的ULID。

时间戳记值(48位)来自 time.time(),精度为毫秒。

随机值(80位)来自 os.urandom()

>>> import ulid
>>> ulid.new()
<ULID('01BJQE4QTHMFP0S5J153XCFSP9')>

根据现有的128位值(例如UUID)创建新的ULID 。
支持ULID值类型有 int,bytes,str,和UUID。

>>> import ulid, uuid
>>> value = uuid.uuid4()
>>> value
UUID('0983d0a2-ff15-4d83-8f37-7dd945b5aa39')
>>> ulid.from_uuid(value)
<ULID('09GF8A5ZRN9P1RYDVXV52VBAHS')>

从现有时间戳值(例如datetime对象)创建新的ULID 。
支持时间戳值类型有int,float,str,bytes,bytearray,memoryview,datetime,Timestamp,和ULID

>>> import datetime, ulid
>>> ulid.from_timestamp(datetime.datetime(1999, 1, 1))
<ULID('00TM9HX0008S220A3PWSFVNFEH')>

根据现有的随机数创建一个新的ULID。

支持随机值类型有int,float,str,bytes,bytearray,memoryview,Randomness,和ULID。

>>> import os, ulid
>>> randomness = os.urandom(10)
>>> ulid.from_randomness(randomness)
>>> <ULID('01BJQHX2XEDK0VN0GMYWT9JN8S')>

一旦有了ULID对象,就有多种与之交互的方法。

timestamp()方法将为您提供ULID的前48位的时间戳快照,而randomness()方法将为您提供后80位的随机数快照。

>>> import ulid
>>> u = ulid.new()
>>> u
<ULID('01BJQM7SC7D5VVTG3J68ABFQ3N')>
>>> u.timestamp()
<Timestamp('01BJQM7SC7')>
>>> u.randomness()
<Randomness('D5VVTG3J68ABFQ3N')>

github: https://github.com/ahawker/ulid


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

4bbb6433d859b0f9be74ecd75d3517b0.png

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

c4bc1261fba780dc03e31849782a3ce4.png

893a8bee72b15a9dbcf14c1e654114e0.png8b81d49b403b20cc2373eb1706159c31.png787ef8b5906456fd1a3c5b2d190ab79d.png8e27f093f81f30e1255300df6d0781dd.png

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值