难道主键除了自增就是GUID?支持k8s等分布式场景下的id生成器了解下

本文探讨了数据库主键的选择,分析了自增主键和GUID的优缺点。提出了一种优化的雪花算法,它结合了两者的优点,具备唯一性、递增有序性、较小的存储空间占用和分布式支持。介绍了雪花算法的结构,包括时间戳、工作机器id和自增序号。还讨论了如何解决分布式环境下的机器id分配、时钟回拨问题,并提供了基于Redis的解决方案,确保了ID的高效生成和唯一性。
摘要由CSDN通过智能技术生成
背景

主键(Primary Key),用于唯一标识表中的每一条数据。所以,一个合格的主键的最基本要求应该是唯一性。

那怎么保证唯一呢?相信绝大部分开发者在刚入行的时候选择的都是数据库的自增id,因为这是一种非常简单的方式,数据库里配置下就行了。但自增主键优缺点都很明显。

优点如下:

  1. 无需编码,数据库自动生成,速度快,按序存放。
  2. 数字格式,占用空间小。

缺点如下:

  1. 有数量限制。存在用完的风险。
  2. 导入旧数据时,可能会存在id重复,或id被重置的问题。
  3. 分库分表场景处理过于麻烦。

GUID

GUID,全局唯一标识符,是一种有算法生成的二进制长度为128位的数字标识符,在理想情况下,任何计算机和计算机集群都不会生成两个相同的GUID,所以可以保证唯一性。但也是有优缺点的。分别如下:

优点如下:

  1. 分布式场景唯一。
  2. 跨合并服务器数据合并方便。

缺点如下:

  1. 存储空间占用较大。
  2. 无序,涉及到排序的场景下性能较差。

GUID最大的缺点是无序,因为数据库主键默认是聚集索引,无序的数据将导致涉及到排序场景时性能降低。虽然可以根据算法生成有序的GUID,但对应的存储空间占用还是比较大的。

概念介绍

所以,本文的重点来了。如果能优化自增和GUID的缺点,是不是就算是一个更好的选择呢。一个好的主键需要具备如下特性:

  1. 唯一性。
  2. 递增有序性。
  3. 存储空间占用尽量小。
  4. 分布式支持。

经过优化后的雪花算法可以完美支持以上特性。

下图是雪花算法的构成图:

20200904171521

雪花id组成由1位符号位+41位时间戳+10位工作机器id+12位自增序号组成,总共64比特组成的long类型。

1位符号位 :因为long的最高位是符号位,正数为0,负数为1,咱们要求生成的id都是正数,所以符号位值设置0。

41位时间戳 :41位能表示的最大的时间戳为2199023255552(1L<<41),则可使用的时间为2199023255552/(1000606024365)≈69年。到这里可能会有人百思不得姐,时间戳2199023255552对应的时间应该是2039-09-07 23:47:35,距离现在只有不到20年的时间,为什么笔者算出来的是69年呢?

其实时间戳的算法是1970年1月1日到指点时间所经过的毫秒或秒数,那咱们把开始时间从2020年开始,就可以延长41位时间戳能表达的最大时间。

10位工作机器id :这个表示的是分布式场景中,集群中的每个机器对应的id,所以咱们需要给每个机器编号。10位的二进制最大支持1024个机器节点。

12位序列号 :自增值,毫秒级最大支持4096个id,也就是每秒最大可生成4096000个id。说个题外话,如果用雪花id当成订单号,淘宝的双十一的每秒的订单量有这个多吗?

到这里,雪花id算法的结构已经介绍完了,那怎么根据这个算法封装成可以使用的组件呢?

开发方案

作为一个程序员,根据算法逻辑写代码这属于基础操作,但写之前,还需要把算法里可能存在的坑想清楚,咱们再来一起来过一遍雪花id的结构。

首先,41位的时间戳部分没有特别需要注意的,起始时间你用1970也是可以的,反正也够用十几二十年(二十年之后的事,关我屁事)。或者,你觉得你的系统可以会运行半个世纪以上,那就把当前离你最近的时间作为起始时间吧。

其次,10位的工作机器id,你可以每个机器编个号,0-1023随便选,但人工搞这件事好像有点傻,如果就两三台机器,人工配

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值