用单库自增键来生成id了,后期怎么分库?哎,这个坑大!

简介: 系统性考虑问题,知其然,知其所以然。

星球水友“写代码的”提问:
沈老师,我们现在用户中心是单库单表uid使用数据库自增主键,uid被很多业务关联,不能变化 现在用户中心数据量逐步变大,有分库需求了,如何由单库升级为多库,保持历史uid不变,并且新生成的数据不冲突有什么好办法么? ==问题描述完== 应该有不少公司都会利用数据库“插入数据自动自增id”来作为业务id,这种方法会使得业务与id生成强耦合,导致id生成算法难以升级。
今天和大家一起简单探讨下,id生成要考虑哪些要素。画外音:别误会,不是说“自增id”不好,是说它与业务耦合了,难以升级。
一、id生成要考虑的技术点 几乎所有业务,都会有一个业务唯一标识:

  • 用户标识:uid(user-id)

  • 消息标识:mid(msg-id)

  • 订单标识:oid(order-id)

这个标识,在存储系统里通常是主键,主键使用聚集索引 (clustered-index) ,即在物理存储上以这个id排序。 于是,对这个id有: 唯一性 趋势递增性的要求。

这个标识,也经常被用来做流量负载均衡,数据负载均衡的依据,即这个id必须在统计上必须是完全随机的。 于是,对这个id有: 随机性 的要求。
同时,id生成算法升级,理论上对业务系统是透明的。 于是,对这个id的生成有: 独立性 需求。 为了保证id生成的上述特性,要有一个: uint64_t GenID() 的独立方法(或者独立接口)来生成id, 生成id具体做什么用,该方法不关心 ,可以是用来做uid,也可以是用来做oid,甚至log-id。 当然, id生成的具体细节,业务也不用关心 。即,GenID()的内部实现,可以是利用数据库的自增id,也可以使用时间递增,目前行业内最流行的,是仿照snowflake生成分布式id。 这个封装, 屏蔽了id生成的细节,保留方案升级的可能性 ,是系统设计中,解耦的体现。 如果使用了此类方法生成业务id,数据库由单库扩展多库就很容易了: (1)确定一个路由算法,例如hash取模; (2)将单库中的数据,通过这个路由算法迁移到多库中去,以实现单库数据量的减少; (3)通过这个路由算法寻找数据(读); (4)通过这个路由算法插入数据(写);
假如架构设计前期没有提前考虑独立的id生成,后期又要实施单库拆多库,该怎么办呢? 二、针对星球水友提到的例子
历史的坑已经铸成,没有解耦id生成方法,而且也没法批量修改id,该怎么办呢?
假设由单库拆分为3库,可以这么玩: (1)做一个1主2从数据库集群,相当于每条数据复制成了3份; (2)将路由算法,设为取模hash算法,%3; (3) 第一个库 ,%3=0, 把余1和余2的uid删掉 (4)第二个库,%3=1,把余0和余2的uid删掉; (5)第三个库,%3=2,把余0和余1的uid删掉; (6) 将每个库的自增步长设置为3 ,这样每个库的id生成就不会重复了; (7)升级用户中心,按照路由算法查询uid数据; 搞定,拆库扩容达成: (1)单库数据量 下降 为了原来的1/3; (2)读写实例个数 扩充 为了原来的3倍; (3)并且id生成与查询都不会冲突; 希望这个取巧的方法对你有帮助。 但更希望,大伙提前考虑id生成 唯一性、随机性、趋势递增性、独立性
系统性 考虑问题,知其然,知其所以然

欢迎大家继续提问,有问必答。

本文转自“架构师之路”公众号,58沈剑提供。

目录
相关文章
|
关系型数据库 MySQL
MySQL中数据插入与主键冲突解决方案
MySQL中数据插入与主键冲突解决方案
527 0
|
9月前
|
存储 SQL 算法
搞定了 6 种分布式ID,分库分表哪个适合做主键?
在《ShardingSphere5.x分库分表原理与实战》系列的第七篇文章中,作者探讨了分布式ID在分库分表中的重要性,以及如何利用`ShardingSphere-jdbc`的多种主键生成策略。文章介绍了`UUID`、`NanoID`、自定义雪花算法和`CosId`等策略的优缺点,并警告不要在SQL中手动拼接主键字段。此外,文章还展示了如何配置这些策略,并提醒读者`CosId`在5.2.0版本可能不可用。最后,文章讨论了如何自定义分布式主键生成算法,并强调选择策略时要考虑全局唯一性、性能和易用性。
841 1
|
数据库 OceanBase
在OceanBase数据库中,当使用主键自增功能插入一条带有主键的数据
在OceanBase数据库中,当使用主键自增功能插入一条带有主键的数据
1786 1
|
存储 数据处理 数据库
分表方案有哪些
分表方案有哪些
135 0
|
存储 程序员 数据库
如何选择合适的分表分库方案
如何选择合适的分表分库方案
103 0
|
算法 数据库
|
存储 算法 关系型数据库
一次数据库分表分库的真实场景应用
一次数据库分表分库的真实场景应用
130 0
|
算法 Scala 数据库
4. 分库分表之后, id 主键如何处理?
4. 分库分表之后, id 主键如何处理?
136 0
4. 分库分表之后, id 主键如何处理?
|
NoSQL 关系型数据库 MySQL
面试官:数据库自增ID用完了会怎么样?
看到这个问题,我想起当初玩魔兽世界的时候,25H难度的脑残吼的血量已经超过了21亿,所以那时候副本的BOSS都设计成了转阶段、回血的模式,因为魔兽的血量是int型,不能超过2^32大小。 估计暴雪的设计师都没想到几个资料片下来血量都超过int上限了,以至于大家猜想才会有后来的属性压缩。 这些都是题外话,只是告诉你数据量大了是有可能达到上限的而已,回到Mysql自增ID上限的问题,可以分为两个方面来说。
面试官:数据库自增ID用完了会怎么样?
|
存储 SQL 关系型数据库
MySQL 建表为啥设置自增 id?用流水号当主键不正好么?
本文主要通过查阅资料,了解为什么要设置一个和业务无关的自增 id 用来当做主键,很多内容比较浅显,比如 InnoDB 的 B+ 树,页分裂及页合并,插入过程等都没有进行深入研究,有兴趣的小伙伴可以更深入的研究下。 同时在建表时除了要设置一个自增 id 用来当做主键,小伙伴们在业务开发过程中是否也会遇到一种情况:用户的注销,数据的删除等都是进行的逻辑删除,而不是物理删除。 本篇文章介绍比较简陋,不足之处,希望大家多多指正。
701 0