您的位置 首页 > 数码极客

表中的主键ID如何产生

欢迎关注头条号:老顾聊技术

精品原创技术分享,知识的组装工


目录

  1. 前言
  2. UUID
  3. mysql主键自增
  4. mysql多实例主键自增
  5. 雪花算法
  6. redis生成方案
  7. 总结
  8. 悬念

前言

分布式系统中我们会对一些数据量大的业务进行分拆,如:用户表,订单表。因为数据量巨大一张表无法承接,就会对其进行分库分表。小伙伴们可以去看一下老顾的以前的文章你知道怎么分库分表吗?如何做到永不迁移数据和避免热点吗? 和

如何永不迁移数据和避免热点? 根据服务器指标分配数据量(揭秘篇)

但一旦涉及到分库分表,就会引申出分布式系统中唯一主键ID的生成问题,永不迁移数据和避免热点的文章中要求需要唯一ID的特性:

1、整个系统ID唯一

2、ID是数字类型,而且是趋势递增的

3、ID简短,查询效率快

什么是递增?如:第一次生成的ID为12,下一次生成的ID是13,再下一次生成的ID是14。这个就是生成ID递增。

什么是趋势递增?如:在一段时间内,生成的ID是递增的趋势。如:再一段时间内生成的ID在【0,1000】之间,过段时间生成的ID在【1000,2000】之间。但在【0-1000】区间内的时候,ID生成有可能第一次是12,第二次是10,第三次是14。

那有什么方案呢?往下看

UUID

这个方案是小伙伴们第一个能过考虑到的方案

优点:

1、代码实现简单。

2、本机生成,没有性能问题

3、因为是全球唯一的ID,所以迁移数据容易

缺点:

1、每次生成的ID是无序的,无法保证趋势递增

2、UUID的字符串存储,查询效率慢

3、存储空间大

4、ID本事无业务含义,不可读

应用场景:

1、类似生成token令牌的场景

2、不适用一些要求有趋势递增的ID场景

此UUID方案是不适用老顾的需求

mysql主键自增

这个方案就是利用了mysql的主键自增auto_increment,默认每次ID加1。

优点:

1、数字化,id递增

2、查询效率高

3、具有一定的业务可读

缺点:

1、存在单点问题,如果mysql挂了,就没法生成iD了

2、数据库压力大,高并发抗不住

mysql多实例主键自增

这个方案就是解决mysql的单点问题,在auto_increment基本上面,设置step步长

每台的初始值分别为1,2,3...N,步长为N(这个案例步长为4)

优点:解决了单点问题

缺点:一旦把步长定好后,就无法扩容;而且单个数据库的压力大,数据库自身性能无法满足高并发

应用场景:数据不需要扩容的场景

此方案也不满足老顾的需求,因为不方便扩容(记住这个方案,嘿嘿)

雪花snowflake算法

这个算法网上介绍了很多,老顾这里就不详细介绍。雪花算法生成64位的二进制正整数,然后转换成10进制的数。64位二进制数由如下部分组成:

  • 1位标识符:始终是0
  • 41位时间戳:41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截 )得到的值,这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的
  • 10位机器标识码:可以部署在1024个节点,如果机器分机房(IDC)部署,这10位可以由 5位机房ID + 5位机器ID 组成
  • 12位序列:毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号

优点:

1、此方案每秒能够产生409.6万个ID,性能快

2、时间戳在高位,自增序列在低位,整个ID是趋势递增的,按照时间有序递增

3、灵活度高,可以根据业务需求,调整bit位的划分,满足不同的需求

缺点:

1、依赖机器的时钟,如果服务器时钟回拨,会导致重复ID生成

在分布式场景中,服务器时钟回拨会经常遇到,一般存在10ms之间的回拨;小伙伴们就说这点10ms,很短可以不考虑吧。但此算法就是建立在毫秒级别的生成方案,一旦回拨,就很有可能存在重复ID。

此方案暂不符合老顾的需求(嘿嘿,看看怎么优化这个方案,小伙伴们先记住)

redis生成方案

利用redis的incr原子性操作自增,一般算法为:

年份 + 当天距当年第多少天 + 天数 + 小时 + redis自增

优点:有序递增,可读性强

缺点:占用带宽,每次要向redis进行请求

整体测试了这个性能如下:

需求:同时10万个请求获取ID 1、并发执行完耗时:9s左右 2、单任务平均耗时:74ms 3、单线程最小耗时:不到1ms 4、单线程最大耗时:4.1s

性能还可以,如果对性能要求不是太高的话,这个方案基本符合老顾的要求。

但不完全符合业务老顾希望id从 1 开始趋势递增。(当然算法可以调整为 就一个 redis自增,不需要什么年份,多少天等)。

总结

如果今天老顾就介绍以上几个方案,其实没有必要,网上多的是;

一线大厂的分布式id方案绝没有这个简单,他们对高并发,高可用的要求很高。

如redis方案中,每次都要去redis去请求,有网络请求耗时,并发强依赖了redis。这个设计是有风险的,一旦redis挂了,整个系统不可用。

而且一线大厂也会考虑到ID安全性的问题,如:redis方案中,用户是可以预测下一个id号是多少,因为算法是递增的。

这样的话竞争对手 第一天中午12点下个订单,就可以看到平台的订单id是多少,第二天中午12点再下一单,又平台订单id到多少。这样就可以猜到平台1天能产生多少订单了,这个是绝对不允许的,公司绝密啊。

悬念

那一线大厂是如何设计的呢?老顾这里先卖个关子,下一篇文章中会介绍一线大厂是怎么设计的,小伙伴们先想一下,回顾上面的方案。

老顾提示一下,很多方案的实现,一线大厂的设计思路其实和小伙伴们思路差不多,只是多想了1~2层,设计上面多了1~2个环节。

这篇文章先到这里,下一篇注重介绍一线大厂的设计,谢谢!!!


-End-

如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!

10几年的经验实战分享

相关微服务,分布式,高并发,高可用,企业实战,干货等原创文章正在路上

欢迎关注头条号:老顾聊技术

精品原创技术分享,知识的组装工

推荐阅读

1、如何永不迁移数据和避免热点? 根据服务器指标分配数据量(揭秘篇)

2、你知道怎么分库分表吗?如何做到永不迁移数据和避免热点吗?

3、你了解大型网站的页面静态化吗?

4、你知道如何更新缓存吗?如何保证缓存和数据库双写一致性?

5、你知道怎么解决DB读写分离,导致数据不一致问题吗?

6、DB读写分离情况下,如何解决缓存和数据库不一致性问题?

7、你真的知道怎么使用缓存吗?

8、如何利用锁,防止缓存击穿?重构思想的重要性

9、海量订单产生的业务高峰期,如何避免消息的重复消费?

10、你知道如何保障生产端100%消息投递成功吗?

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“表中的主键ID如何产生”边界阅读