16|分库分表主键生成:如何设计一个主键生成算法?
前置知识
- 深入了解
- 翻译
- 解释
- 总结
分库分表是数据库领域的热门话题,本文深入探讨了分库分表的主键生成算法,介绍了UUID、数据库自增和雪花算法等常见主键生成策略。文章详细解释了这些策略的优缺点,并提出了优化方案。此外,还强调了面试准备的重要性,包括深入理解主键生成策略、准备有亮点的方案以及记住可行的优化方案。通过深入讨论分库分表的主键生成问题,为读者提供了面试准备和技术知识的指导。文章还提出了主键内嵌分库分表键的亮点方案,将主键生成策略和分库分表键结合,为读者呈现了一种创新的设计思想。 在主键生成策略方面,文章介绍了全局递增、独一无二等方案,并对其优缺点进行了详细分析。此外,还提出了优化思路,包括批量取、提前取、singleflight取、局部分发等方法,以降低发号器的并发压力,提高性能。 总之,本文通过深入讨论分库分表的主键生成问题,为读者提供了全面的技术知识指导,同时强调了面试准备的重要性,为读者提供了实用的面试准备建议。
《后端工程师的高阶面经》,新⼈⾸单¥59
全部留言(19)
- 最新
- 精选
- Joharmysql里面也可以把uuid转换为16字节,同时将时间戳按照高,中,低排列,也可以实现自增
作者回复: 新用法!我倒是没想到还有这种玩法,算是学了一招,感谢!
2023-07-21归属地:重庆3 - Homto你设想这么一个场景:你的分库分表是按照 ID 除以 32 的余数来进行的,那么如果你的业务非常低频,以至于每一个时刻都只生成了尾号为 1 的 ID,那么是不是所有的数据都分到了一张表里面呢? 问题来了:非常低频的话那,是不是就没有必要分表了?
作者回复: 其实这个主要考虑的高峰和低谷。高峰很高但是低谷也很低。
2023-08-06归属地:四川2 - 小晨在主键内嵌分库分表键的方案中,为什么第三段要采用随机数而不是顺序序列号呢?
作者回复: 这个跟你怎么落地 ID 生成程序有关系。在这种方案中,可以直接在应用服务器中生成。而一个创建订单的服务有很多实例,通过负载均衡之后,同一个人的请求会落到不同的机器上,这时候你要顺序序列号,就得协调这些机器。 随机就没这个烦恼。
2023-07-31归属地:江苏2 - sheep回答问题: 1. 可以是可以,但是缩减之后所能代表的机器数量也就减少了 2. Go里面的GMP调度中的本地队列和全局队列,Go内存分配中的mcache
作者回复: 赞!
2023-10-27归属地:广东1 - 我好像一点都不像程序员1、个人认为还是个 trade off 问题,缩短时间戳和缩短机器位数两种方式都是可取的,如果你的业务活不了太久,那么缩短时间戳位数问题不大,如果你确定你不会拼命堆机器来提高业务吞吐量,当然也可以缩短机器位数,没有对与错之分,只有哪个方式更适合当前情况 2、记得PHP是每次都是向OS申请一大片内存空间的,然后再慢慢用,算不 by the way :补充一个我们日常的使用场景《数据迁移》,自增ID对数据迁移来说是非常不友好的,动不动就冲突,如果还用自增ID来做业务关联,那就更麻烦了,如果真的要用自增ID,最好是把它当作占坑用的,业务不要用它,而UUID 的主键虽然可以解决冲突问题,但是它的缺点也很明显,页分裂,查询不友好,占用空间大,这样索引树的空间占用也变大了(非主键索引树叶子节点存的是主键),而雪花ID可以递增又可以解决冲突问题,所以目前我们的新服务我都是要求用雪花ID,雪花ID冲突的场景我工作中确实没有遇到过(业务不给力呀,好想搞电商) 另外,分段思想还挺不错的,感谢大明兄分享
作者回复: 1. 赞! 2. 哈哈哈,也算。很多系统,包括我们自己设计缓存都是这种套路,自己申请一块,内部慢慢分。 多交流!
2023-07-22归属地:广东51 - 波多黎各仔我觉得实际上,应该不可以挪用机器Id比特位。 虽然说,如果项目规模不大,部署的微服务较少,可以去挪用。但是,现在的情况是微服务的序列都不够用了,说明业务量比较大,一般是有增加机器的需求,怎么还会去减少机器Id比特位呢
作者回复: 赞!对,这是一个理由!
2023-07-21归属地:江苏1 - NullPointerException普遍情况下,我们都是用买家 ID 来查询对应的订单信息。在别的场景下,比如说我们只有一个订单 ID,这种时候我们可以取出订单 ID 里嵌入进去的买家 ID 后四位,来判断数据存储在哪个库、哪个表。类似的设计还有答题记录按照答题者 ID 来分库分表,但是答题记录 ID 本身可以嵌入这个答题者 ID 中用于分库分表的部分 没太明白只有uid后四位怎么判断uid对应的库表的?
作者回复: 你是按照买家的后四位来分库分表的,那么你知道这个后四位,就知道数据在哪里了。
2023-12-14归属地:上海 - jCodePorter在主键内嵌分库分表键的方案中,使用4位的用户id,那么如果本身用户体量非常大,已经达到亿级用户了。那么后四位完全一样的用户数就存在很多很多了,如果同时下单,那生成的主键不就冲突很严重了吗?解决方案除了让业务等待暂停下,还有其他方案吗
作者回复: 冲突也没想象中的严重。因为时间戳本身是记录的是毫秒数,那么你可以预期,如果是千万 QPS(一秒一千万个订单已经很高了),那么同一毫秒,也就是有一万个请求而已。后四位相同的概率就是 1/9999,而随机数是 8比特,也就是随机数相同的概率是 1/2^8,一万个请求也不一定会有一个相同的 ID。 我这个算法应该不太对,但是量级应该是这样一个量级,就是冲突并没有想象中的那么厉害。并且,冲突了之后,可以再次生成一个随机数,这个时候估计就避开了上一个冲突的同尾号的用户了。
2023-10-28归属地:河南 - sheep发号器一般都需要单独部署一个新的服务么,类似于基于Redis的发号器这些?
作者回复: 我主观来说,我是觉得独立部署的发号器是一个纯纯馊主意。我更加倾向于应用服务器本身也充当发号器(也就是不同的线程/goroutine),然后直接应用就从本地的发号器里面拿ID。 独立部署的发号器就是你说的这种,还有微服务集群形态的发号器。
2023-10-26归属地:广东 - sheep1. 页分裂除了逻辑相邻的数据在磁盘上不相邻之外,页分裂过程也会对数据库性能有所消耗吧 2. 亮点3: 数据堆积这里,这里是对雪花算法之后的数字进行求余,然后确定对应要插入到的数据库么
作者回复: 1. 对的 2. 是的。比如说你很不幸把所有的大商家的数据都分配到了同一个表里,这张表就会有极多的数据。
2023-10-26归属地:广东