好文推荐
圈子
网址导航
登录/注册
{{info.is_collect==1?info.collect_num:'收藏'}}
{{info.is_zan==1?info.zan_num:'点赞'}}
{{info.is_pinglun==1?info.collect_num:'评论'}}
复制下面链接分享给好友吧~
{{shorturl}}
复制链接
分享
ULID 是什么?比 UUID 更好用的全局唯一标识符?
豌豆花下猫
公众号:Python猫
{{info.update_time}}
阅读 {{info.hit_num}}
ULID为什么比UUID好用?

本文来自微信公众号 ”Python猫“,作者:豌豆花下猫,纷传经授权发布。


大家好,我是猫哥。最近陆续看到过有文章介绍 ULID,而我此前并无听闻,因此就搜索了一番,现在分享相关材料给大家。


1、ULID 的理念与规范:https://github.com/ulid/spec

2、ULID 规范解读与实现原理:https://mp.weixin.qq.com/s/jA5CQlqpf2c4NiminZFcfQ,参照规范使用 Java 进行实现,推荐一读


3、Python 社区中有几个实现 ULID 的库(ulid、python-ulid、ulid-py),其中 star 数最多的是 ulid-py,它的功能最为完备,文档也最为丰富。


以下分享的文章是对 ULID 规范文档的部分摘要以及 ulid-py 的使用介绍。


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

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


UUID :Universally Unique Identifier(通用唯一标识符)



01

为什么不选择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 更加友好。



02

ULID特性



微信截图_20221124140055.png



  • 与UUID的128位兼容性

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

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

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

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

  • 不区分大小写

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

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



03

ULID规范



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


微信截图_20221124140033.png


组成


时间戳


  • 48位整数

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

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


随机性


  • 80位随机数

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


排序


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


编码方式


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


微信截图_20221124140009.png


二进制布局和字节顺序


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


微信截图_20221124135935.png


应用场景


  • 替换数据库自增id,无需DB参与主键生成

  • 分布式环境下,替换UUID,全局唯一且毫秒精度有序

  • 比如要按日期对数据库进行分区分表,可以使用ULID中嵌入的时间戳来选择正确的分区分表

  • 如果毫秒精度是可以接受的(毫秒内无序),可以按照ULID排序,而不是单独的created_at字段



04

用法(python)



安装


微信截图_20221124135914.png


创建一个全新的ULID。


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


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


微信截图_20221124135853.png


根据现有的128位值(例如UUID)创建新的ULID 。


支持ULID值类型有 int,bytes,str,和UUID。


微信截图_20221124135833.png


从现有时间戳值(例如datetime对象)创建新的ULID 。


支持时间戳值类型有int,float,str,bytes,bytearray,memoryview,datetime,Timestamp,和ULID


微信截图_20221124135808.png


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


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


微信截图_20221124135740.png


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


微信截图_20221124135713.png


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

#专栏
#工具
评论 /{{info.pinglun_num}}
点击登陆后评论
发布
{{ reply.content }}
回复 删除
回复 {{ reply2.content }}
{{ reply2.create_time }} 回复 删除
更多推荐
{{item.title}}
{{item.update_time+'\u00A0'+item.hit_num+'阅读'}}
友情链接
人人都是产品经理 iconfont 135编辑器 考古加 新鲜码
公众号
作者群
关于
免责声明
Copyright 2016-2021 All Rights Reserved 杭州领帜科技有限公司 浙ICP备2020035253号-3