雪花算法和UUID

雪花算法和UUID

UUID

UUID是一种唯一且不需要中央协调的ID,它使用某种规则创建ID,而不是某种中心化的自增方式,使得其成为创建成本最低的ID类型。

到目前为止UUID一共有5个实现版本

  • 版本1: 按照 UUID 定义的每个字段的意义来实现,使用的变量因子是时间戳+时钟序列+节点信息(Mac地址),考的最多的版本

  • 版本2:基本和1一致,信息很少,可忽略

  • 版本3:基本name和namespace的hash实现变量因子,使用MD5进行hash,不是随机生成

  • 版本4:使用随机或者伪随机实现变量因子,不具备单调性,使用最广泛

  • 版本5:基本name和namespace的hash实现变量因子,使用sha1进行hash,不是随机生成

这些版本的结构基本都是一致的,只是在版本1的基础上变化了变量因子

UUID长度128比特,换算为16进制数就是有32个16进制数组成,中间用4个-分割,所以一共有36个字符,按照8-4-4-4-4-12的的顺序进行分割。

组成它的变量因子一共有三个,Timestamp时间戳、Clock Sequence时钟序列,node节点信息

Timestamp时间戳:60bit 15个数

这15个数分布在前3个组成中,分别是时间戳低位8个、时间戳中位4个、时间戳高位3个,第三个部分的第一位是UUID版本字段,占4个字节,所以可以有16个版本号

Clock Sequence时钟序列:14bit 三个半数,最左边的2bit是保留位

时钟序列一般用于时间调整时的唯一性保证,当时间调整,或者 nodeId 变化的时候,直接使用一个随机数,或者,在原先的Clock Sequence值上面自增加一也是可以的。

保留位用于未来的扩展以及保持UUID的标准兼容性,确保UUID的格式能够适应将来的需求而不影响现有的实现。

Node节点信息:12个数,一般是MAC地址或者随机数生成

基于name和namespace的hash结构生成是什么意思?

  • Name: 是对象的名称或标识符。比如,在 Kubernetes 中,Pod 的名称就是一个典型的 name
  • Namespace: 是一个命名空间,用于将不同作用域内的对象区分开来。例如,两个相同名称的 Pod 可以存在于不同的命名空间,从而不冲突。

UUID v3UUID v5 中,namenamespace 是生成 UUID 的关键输入,它们并不是自动变化的,而是由开发者根据具体应用场景指定的。每次生成 UUID 时,使用相同的 namenamespace 组合,会得到相同的 UUID。

雪花算法

雪花算法生成的64位ID由以下几部分组成:

第一位(符号位):由于ID都是正整数,所以第一位始终为0。

时间戳(41位):记录时间戳的差值(相对于某个固定时间点),单位是毫秒。41位时间戳可以使用69年(从1970年开始,可用至2039年)。

工作机器id(10位):用于标识不同的工作机器(如不同的服务器实例),支持在同一数据中心内部署最多1024台机器。

如果存在跨机房部署的情况下可以把这10个bit位,拆分成两个5bit,前5个bit表示机房id,后面5个表示机器的id

序列号(12位):用于在同一毫秒内产生不同的ID,支持每个工作机器在同一毫秒内产生最多4096个ID。

时钟回拨和时钟漂移

时钟回拨是指系统时间被人为或自动地调整到过去的某个时间点。

时钟漂移是指由于硬件本身的物理特性,系统时钟的计时速率可能并不完全准确,随着时间推移,会逐渐偏离标准时间。

雪花算法怎么解决时钟回拨和时钟漂移

  • 时间强依赖变成弱依赖,只有第一次算法启动的时候获取时间戳,之后都是算法增加时间戳,而不是依赖于系统时间。这种方式可以避免一毫秒只能生成4096个ID的弊端。仍然会有ID冲突,例如,一小时内获取一千万条ID,这个实际上是获取了未来的ID,这样如果服务器重启,获取了旧的时间戳,就会出现ID重复,解决方案是存储当前使用到的时间戳,下一次启动时获取。

  • 通过机器ID或者序列号进行补偿,可以增加机器ID的部分或者增加序列号的部分,UUID也是这种方案。

  • 阻塞等待时间追赶(兜底策略)。

posted @ 2024-08-28 22:04  枫叶藏在眼眸  阅读(16)  评论(0编辑  收藏  举报