分布式系统--主键id的选择

本文探讨了在分布式系统中,自增主键和UUID作为主键的优缺点。自增主键在读取性能、写入性能和空间占用上有优势,但面临并发插入的锁竞争问题。UUID则能保证全局唯一性,但在写入速度和存储空间上存在问题。文章还提到了其他主键生成方式,如ID生成服务器和COMB主键,并通过500万级数据测试对比了它们的性能表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自增主键和UUID的区别和选择

自增主键的介绍和优缺点

  • 设计表时,将id字段的值设置为自增的形式,当插入一行数据时,无需指定id会自动根据前一字段的ID值+1 进行填充,mysql中可通过auto-increment来实现。
  • 在分布式业务环境下,需要考虑业务的拓展情况设置步长,比如有三台服务器,就把步长设置为3,起始值分别为(1,2,3),这样三张表的主键就绝对不会重复了,而且也不用另外做三张表的逻辑关联了。
修改MySQL【默认自动增长的步长】
set global auto_increment_increment=1; — 设置序列的增长值
show global variables; — 显示所有的global变量
show global variables like ‘%test%’ — 查询包含test字符串的global变量
自增主键的好处
  • 字段长度小于uuid,可以是bigint甚至int类型,使用innodb引擎时,根据索引找到主键,再找记录。–读取性能高
  • 自增的主键是有顺序的,所以innodb把新的记录存储在最后一条记录的后面。因为如此,mysql定位和寻址的速度很快,不会为了计算新行的位置而额外的消耗性能–写入性能高
  • 当页面达到最大填充因子的时候(默认是15/16,会留出1/16的空间留作以后的修改)下一条记录会写入新的页中,主键页近乎于顺序的方式把记录填满,提升了页面的最大填充率,不会有页的浪费。-- 空间占用小
  • 增加记录时,可以不指定id字段,也不需要担心主键重复问题
自增主键的问题
  • 高并发的情况下,插入时会造成明显的锁争用,并发插入会导致间隙锁的竞争。
  • Auto_increment锁机制会造成自增锁的抢夺,会有性能损失。
  • 如果数据被爬取了,竞争对手可以通过自增id的数字来判断出业务增长信息以及经营状况。

UUID的介绍和优缺点

在一台机器上生成的数字,保证对同一时空中所有的机器都是唯一的,在一定范围内保证主键id的唯一性

UUID的好处
  • 不会产生冲突,进行数据拆分,合并存储时都可以做到全局唯一
  • 在应用层生成,提高数据库吞吐能力(自增的会产生自增锁竞争)
  • 安全性高,无法被分析业务和经营情况
UUID的问题
  • 严重影响插入速度!uuid是毫无规律可言的,innodb无法做到总是把新行插入索引的最后,所以在插入时需要为新行寻找合适的位置来分配新的空间,这个过程会产生很多额外的操作。
    1. 写入的目标页可能已经刷新到磁盘上或者从缓存中移除了,或者还没加载到缓存。
      innodb在插入这条数据时不得不先找到该页,并加载到内存中,这将导致大量的随机IO。
    2. 因为写入是乱序的,innodb不得不频繁的做页分裂操作,以便为新的行分配空间,页分裂会导致移动大量的数据,而且一次插入最少需要修改三个页以上。
    3. 由于频繁的页分裂,页会变得稀疏并被不规则地填充,最终会导致数据有碎片。

为什么uuid插入时比自增ID要慢

对于InnoDB这种聚集主键类型的引擎来说,数据会按照主键进行排序,由于UUID的无序性,InnoDB会产生巨大的IO压力,而且由于索引和数据存储在一起,字符串做主键会造成存储空间增大一倍。

在存储和检索的时候,innodb会对主键进行物理排序,这对auto_increment_int是个好消息,因为后一次插入的主键位置总是在最后。

但是对uuid来说,这却是个坏消息,因为uuid是杂乱无章的,每次插入的主键位置是不确定的,可能在开头,也可能在中间,在进行主键物理排序的时候,势必会造成大量的 IO操作影响效率,在数据量不停增长的时候,特别是数据量上了千万记录的时候,读写性能下降的非常厉害。


其他数据库主键生成方式

1.ID生成服务器(不推荐)
  • 建立两台以上的数据库ID生产服务器,每个服务器都有一张记录当前各表当前ID的MaxId表,MaxId中Id的增长步长是id生成服务器的数量。
ID生成服务器的好处
  • 生成id较短,友好型比较好
  • 将产生ID的压力均匀分散在多台id生成服务器上
  • 当一个服务器失效后,系统能自动切换到另外一个服务器获取id,解决了因为单点问题导致的系统的错误。
ID生成服务器的坏处
  • 把主键生成放到外部服务器进行,那么就不得不通过网络通信来完成主键值的传递,而网络是计算机体系里效率最低的方式,在数据量大,新增操作频繁时会成为关键的短板瓶颈
  • 当要添加id生成器的新节点时,需要对原有数据重新根据步长计算迁移数据。
  • 多服务器会面临引入集群系统带来的风险和工作量,为系统开发增加了开发难度和运维风险,没有必要自讨苦吃。
2.COMB主键:GUID+时间戳 (推荐)

“COMB”(combined guid/timestamp),意思是:组合GUID/时间截

  • 传统使用GUID会因为数据毫无规律可言而导致数据库插入时产生的性能问题,以及索引效率低下。(见UUID部分)
  • COMB方式通过保留GUID的10个字节,用另外6个字节表示生成GUID的时间,这样再组合起来成为COMB主键。
COMB主键的好处
  • 保留了GUID的全局唯一性
  • 增加了GUID的有序性,提升了索引效率,也避免了插入时诸如页分裂这些的操作。
COMB主键的坏处
  • 生成的id不友好,占据了32位
  • 因为id长度问题,索引效率较差

500w级数据测试

  • 2.1 录入500W数据,自增ID节省一半磁盘空间
  • 2.2 单个数据走索引查询,自增id和uuid相差不大
  • 2.3 范围like查询,自增ID性能优于UUID
  • 2.4 写入测试,自增ID是UUID的4倍
  • 2.5、备份和恢复,自增ID性能优于UUID
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值