欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > 大厂为什么要禁止使用数据库自增主键

大厂为什么要禁止使用数据库自增主键

2024/10/23 14:39:54 来源:https://blog.csdn.net/liangmengbk/article/details/143166583  浏览:    关键词:大厂为什么要禁止使用数据库自增主键

大表为何不能用自增主键?

数据库自增主键,以mysql为例,设置表的ID列为自动递增,便可以在插入数据时,ID字段值自动从1开始自动增长,不需要人为干预。

在小公司,或者自己做项目时,设置ID为自动递增,是没有问题的。但是在分布式系统中,自增主键会带来问题,下面举例说明:

有一张商品信息表,表中有3亿条数据,但是3亿条数据是分布在3个数据库中(3个表分片)。前1亿条数据分布在分片1中;中间1亿条数据,分布在分片2;最后1亿条数据分布在分片3中。

问题1:如果单条数据量比较小,在分片1中实际可以容纳1.5亿数据,就无法再进行数据扩展了,因为数据是按照ID范围进行分片的,ID是固定死的,无法在运行期间,进行动态扩展。

问题2:自增主键是数据库层面生成的自增序列,数据库集群只能采用“范围分片”的形式,也就是提前规划好每个分片存储的记录ID。此操作会产生“尾部热点”。

何为尾部热点,在使用范围分片的情况下,测试程序的生成主键是单调递增的,所以新写入的数据往往集中在一个 范围范围内,而范围又是数据调度的最小单位,只能存在于单节点,那么这时集群就退化成单机的写入性能,不能充分利用分布式读写的扩展优势了。当所有写操作都集中在集群的一个节点时,就出现了我们常说的数据访问热点(Hotspot)。

以上面的商品表为例,当数据量达到2.5亿时,数据再进行插入操作时,数据都会进入到分片3中,也就是集中会对分片3这个数据库进行操作,前面两个数据库(分片1、分片2),几乎没有压力。

AB两个数据库,分别采用范围分片和Hash分片的方法,做数据并发处理。可以看到Hash分片的方式效率远高于范围分片看,提高大约2倍。

Hash分片处理效率高,原因是Hash分片不是把数据只写在一个切片上,它是根据ID取模,然后均匀分配在各个切片上,相当于让把压力分摊到各个切片上。

UUID是好的替代方案吗?

如果说自增主键不适用于大数据量分库的表设计,那么是否可以用UUID或者GUID来替代自增主键呢?其实UUID也是不合适的。

UUID是根据当前计算机的时间和其他各种属性计算出来的一个128位长度的字符串,字符串的特点是唯一且无序。

既然是唯一的,那为何不适合作为主键,那就看MySQL的机制。因为UUID是无序的,作为主键会涉及大量索引重排。作为主键,当数据生成时,就自动建立唯一的主键索引。

数据采用B+树的方式进行数据存储,叶子节点按照顺序,1234...进行排列,当要插入一条新数据时,只需要在原有的节点上追加上一个元素,并调整结尾的树形结构。影响的数据范围非常小。

如果使用UUID,就会涉及到索引重排,索引重排以下图为例:

索引重排示意图

当新的数据插入时,整个数据结构都会发生变化。当数据量大时,代价是很大的。

为了解决该问题,也就有了一种分布式且有序的主键生成算法,即雪花算法。

SnowFlake雪花算法是什么?

雪花算法(SnowFlake)是Twitter公司分布式项目采用的ID 生成算法。

雪花算法构成要素

雪花算法构成说明

以时间为依据,结合机器ID及序列,生成的一个定长的数字,这个数字就可以作为主键。它即可以保证是有序的,在分布式情况下,每个分片也是唯一的。 

使用雪花算法时,需要注意时间回拨带来了ID重复问题,也就是如果把服务器时间往回调整,那么生成的值,有可能与之前的值重复。一般不会去随意调整服务器时间,这个问题产生的概率不高。

关于雪花算法的其他内容,参考文章:

SQL-雪花ID算法-全局唯一标识符(GUID)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com