首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
基础学习课
实战项目课
求职辅导课
专栏&文章
竞赛
搜索
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
AI面试、笔试、校招、雇品
HR免费试用AI面试
最新面试提效必备
登录
/
注册
芒果椰冰
东南大学 后端工程师
发布于上海
关注
已关注
取消关注
学习分库分表
@程序员辰星:
分库分表夺命连环问
整理了几个面试过程中分库分表常见问题分享给大家,这里面有常规面试必掌握题(1、2、3、5、7、10、11、12),也有面试拔高题(4、6、8、9、13、14、15),大家根据自己的需要查看,有关于技术上的问题也可留言讨论,有问必答。1 为什么分库分表1.1 为什么要分库如果业务量剧增,数据库可能会出现性能瓶颈,这时候我们就需要考虑拆分数据库。从这两方面来看:磁盘存储业务量剧增,MySQL单机磁盘容量会撑爆,拆成多个数据库,磁盘使用率大大降低。并发连接支撑我们知道数据库连接数是有限的。在高并发的场景下,大量请求访问数据库,MySQL单机是扛不住的!高并发场景下,会出现too many connections报错。当前非常火的微服务架构出现,就是为了应对高并发。它把订单、用户、商品等不同模块,拆分成多个应用,并且把单个数据库也拆分成多个不同功能模块的数据库(订单库、用户库、商品库),以分担读写压力。1.2 为什么要分表假如你的单表数据量非常大,存储和查询的性能就会遇到瓶颈了,如果你做了很多优化之后还是无法提升效率的时候,就需要考虑做分表了。一般千万级别数据量,就需要分表。这是因为即使SQL命中了索引,如果表的数据量超过一千万的话,查询也是会明显变慢的。这是因为索引一般是B+树结构,数据千万级别的话,B+树的高度会增高,查询就变慢啦。MySQL的B+树的高度怎么计算的呢?跟大家复习一下:InnoDB存储引擎最小储存单元是页,一页大小就是16k。B+树叶子存的是数据,内部节点存的是键值+指针。索引组织表通过非叶子节点的二分查找法以及指针确定数据在哪个页中,进而再去数据页中找到需要的数据,B+树结构图如下:假设B+树的高度为2的话,即有一个根结点和若干个叶子结点。这棵B+树的存放总记录数为=根结点指针数*单个叶子节点记录行数。如果一行记录的数据大小为1k,那么单个叶子节点可以存的记录数 =16k/1k =16. 非叶子节点内存放多少指针呢?我们假设主键ID为bigint类型,长度为8字节(面试官问你int类型,一个int就是32位,4字节),而指针大小在InnoDB源码中设置为6字节,所以就是 8+6=14 字节,16k/14B =16*1024B/14B = 1170因此,一棵高度为2的B+树,能存放1170 * 16=18720条这样的数据记录。同理一棵高度为3的B+树,能存放1170 *1170 *16 =21902400,大概可以存放两千万左右的记录。B+树高度一般为1-3层,如果B+到了4层,查询的时候会多查磁盘的次数,SQL就会变慢。因此单表数据量太大,SQL查询会变慢,所以就需要考虑分表啦。2 什么时候分库分表对于MySQL,InnoDB存储引擎的话,单表最多可以存储10亿级数据。但是的话,如果真的存储这么多,性能就会非常差。一般数据量千万级别,B+树索引高度就会到3层以上了,查询的时候会多查磁盘的次数,SQL就会变慢。阿里巴巴的《Java开发手册》提出:单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。那我们是不是等到数据量到达五百万,才开始分库分表呢?不是这样的,我们应该提前规划分库分表,如果估算3年后,你的表都不会到达这个五百万,则不需要分库分表。MySQL服务器如果配置更好,是不是可以超过这个500万这个量级,才考虑分库分表?虽然配置更好,可能数据量大之后,性能还是不错,但是如果持续发展的话,还是要考虑分库分表一般什么类型业务表需要才分库分表?通用是一些流水表、用户表等才考虑分库分表,如果是一些配置类的表,则完全不用考虑,因为不太可能到达这个量级。3 如何选择分表键分表键,即用来分库/分表的字段,换种说法就是,你以哪个维度来分库分表的。比如你按用户ID分表、按时间分表、按地区分表,这些用户ID、时间、地区就是分表键。一般数据库表拆分的原则,需要先找到业务的主题。比如你的数据库表是一张企业客户信息表,就可以考虑用了客户号做为分表键。为什么考虑用客户号做分表键呢?这是因为表是基于客户信息的,所以,需要将同一个客户信息的数据,落到一个表中,避免触发全表路由。4 非分表键如何查询分库分表后,有时候无法避免一些业务场景,需要通过非分表键来查询。假设一张用户表,根据userId做分表键,来分库分表。但是用户登录时,需要根据用户手机号来登陆。这时候,就需要通过手机号查询用户信息。而手机号是非分表键。非分表键查询,一般有这几种方案:遍历:最粗暴的方法,就是遍历所有的表,找出符合条件的手机号记录(不建议)将用户信息冗余同步到ES,同步发送到ES,然后通过ES来查询(推荐)其实还有基因法:比如非分表键可以解析出分表键出来,比如常见的,订单号生成时,可以包含客户号进去,通过订单号查询,就可以解析出客户号。但是这个场景除外,手机号似乎不适合冗余userId。5 分表策略5.1 range范围range,即范围策略划分表。比如我们可以将表的主键order_id,按照从0~300万的划分为一个表,300万~600万划分到另外一个表。如下图:有时候我们也可以按时间范围来划分,如不同年月的订单放到不同的表,它也是一种range的划分策略。优点: range范围分表,有利于扩容。缺点:可能会有热点问题。因为订单id是一直在增大的,也就是说最近一段时间都是汇聚在一张表里面的。比如最近一个月的订单都在300万~600万之间,平时用户一般都查最近一个月的订单比较多,请求都打到order_1表啦。5.2 hash取模hash取模策略:指定的路由key(一般是user_id、order_id、customer_no作为key)对分表总数进行取模,把数据分散到各个表中。比如原始订单表信息,我们把它分成4张分表:比如id=1,对4取模,就会得到1,就把它放到t_order_1;id=3,对4取模,就会得到3,就把它放到t_order_3;一般,我们会取哈希值,再做取余:优点:hash取模的方式,不会存在明显的热点问题。缺点:如果未来某个时候,表数据量又到瓶颈了,需要扩容,就比较麻烦。所以一般建议提前规划好,一次性分够。(可以考虑一致性哈希)5.3 一致性Hash如果用hash方式分表,前期规划不好,需要扩容二次分表,表的数量需要增加,所以hash值需要重新计算,这时候需要迁移数据了。比如我们开始分了10张表,之后业务扩展需要,增加到20张表。那问题就来了,之前根据orderId取模10后的数据分散在了各个表中,现在需要重新对所有数据重新取模20来分配数据为了解决这个扩容迁移问题,可以使用一致性hash思想来解决。一致性哈希:在移除或者添加一个服务器时,能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系。一致性哈希解决了简单哈希算法在分布式哈希表存在的动态伸缩等问题6 热点倾斜问题如果我们根据时间范围分片,某电商公司11月搞营销活动,那么大部分的数据都落在11月份的表里面了,其他分片表可能很少被查询,即数据倾斜了,有热点数据问题了。我们可以使用range范围+ hash哈希取模结合的分表策略,简单的做法就是:在拆分库的时候,我们可以先用range范围方案,比如订单id在0~4000万的区间,划分为订单库1;id在4000万~8000万的数据,划分到订单库2,将来要扩容时,id在8000万~1.2亿的数据,划分到订单库3。然后订单库内,再用hash取模的策略,把不同订单划分到不同的表。7 分布式事务问题分库分表后,假设两个表在不同的数据库,那么本地事务已经无效啦,需要使用分布式事务了。常用的分布式事务解决方案有:两阶段提交三阶段提交TCC本地消息表最大努力通知saga我是分布式事务框架Seata的Committer,大家有关于分布式事务的问题可以找我讨论8 跨节点Join在单库未拆分表之前,我们如果要使用join关联多张表操作的话,简直so easy啦。但是分库分表之后,两张表可能都不在同一个数据库中了,那么如何跨库join操作呢?跨库Join的几种解决思路:字段冗余:把需要关联的字段放入主表中,避免关联操作;比如订单表保存了卖家ID(sellerId),你把卖家名字sellerName也保存到订单表,这就不用去关联卖家表了。这是一种空间换时间的思想。全局表:比如系统中所有模块都可能会依赖到的一些基础表(即全局表),在每个数据库中均保存一份。数据抽象同步:比如A库中的a表和B库中的b表有关联,可以定时将指定的表做同步,将数据汇合聚集,生成新的表。一般可以借助ETL工具。应用层代码组装:分开多次查询,调用不同模块服务,获取到数据后,代码层进行字段计算拼装。9 分页问题方案1(全局视野法):在各个数据库节点查到对应结果后,在代码端汇聚再分页。这样优点是业务无损,精准返回所需数据;缺点则是会返回过多数据,增大网络传输比如分库分表前,你是根据创建时间排序,然后获取第2页数据。如果你是分了两个库,那你就可以每个库都根据时间排序,然后都返回2页数据,然后把两个数据库查询回来的数据汇总,再根据创建时间进行内存排序,最后再取第2页的数据。方案2(业务折衷法-禁止跳页查询):这种方案需要业务妥协一下,只有上一页和下一页,不允许跳页查询了。这种方案,查询第一页时,是跟全局视野法一样的。但是下一页时,需要把当前最大的创建时间传过来,然后每个节点,都查询大于创建时间的一页数据,接着汇总,内存排序返回。10 分布式ID数据库被切分后,不能再依赖数据库自身的主键生成机制啦,最简单可以考虑UUID,或者使用雪花算法生成分布式ID。雪花算法是一种生成分布式全局唯一ID的算法,生成的ID称为Snowflake IDs。这种算法由Twitter创建,并用于推文的ID。一个Snowflake ID有64位。第1位:Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。接下来前41位是时间戳,表示了自选定的时期以来的毫秒数。接下来的10位代表计算机ID,防止冲突。其余12位代表每台机器上生成ID的序列号,这允许在同一毫秒内创建多个Snowflake ID。11 分库中间件 目前流行的分库分表中间件比较多:Sharding-JDBCcobarMycatAtlasTDDL(淘宝)vitess我们项目当前就是使用Sharding-JDBC实现的分库分12 垂直、水平分库分表策略区别水平分库:以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。水平分表:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。垂直分库:以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。垂直分表:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。13 不停服扩容不用停服。不停服的时候,应该怎么做呢,主要分五个步骤:编写代理层,加个开关(控制访问新的DAO还是老的DAO,或者是都访问),灰度期间,还是访问老的DAO。发版全量后,开启双写,既在旧表新增和修改,也在新表新增和修改。日志或者临时表记下新表ID起始值,旧表中小于这个值的数据就是存量数据,这批数据就是要迁移的。通过脚本把旧表的存量数据写入新表。停读旧表改读新表,此时新表已经承载了所有读写业务,但是这时候不要立刻停写旧表,需要保持双写一段时间。当读写新表一段时间之后,如果没有业务问题,就可以停写旧表啦
点赞 26
评论 0
全部评论
推荐
最新
楼层
暂无评论,快来抢首评~
相关推荐
02-05 20:38
蚌埠坦克学院 嵌入式软件开发
刚入职不懂事,天天下班早
刚入职那会儿,真的是什么都不懂,下班时间特别守规矩,天天准点走。以为按部就班就没问题,结果绩效一看——低得心碎。后来才明白,刚入职不是光守时就行,还得主动学、主动问、多承担一些任务,把能力和价值表现出来。吃了低绩效也没关系,把它当作一面镜子:告诉你哪些地方需要加把劲,也提醒你别再只守时间,要守质量和效率。职场成长,很多时候都是从低绩效开始,慢慢学会主动和规划。
刚入职的你踩过哪些坑
点赞
评论
收藏
分享
昨天 12:51
正浩创新EcoFlow_电力电子软件工程师(准入职员工)
正浩创新内推,正浩创新内推码
一整个面试下来,感觉正浩的技术面真的很扎实!趁热乎整理一波面经(纯干货版),希望能帮到准备面试的学弟学妹们~ 【结尾有血泪总结建议!】🔧 【一面 · 硬核技术面】面试官问的非常细致深入🔥,主要围绕电源知识,我总结出的题目供参考:1为什么相同载波频率下,单相全桥用单极性倍频比双极性调制,变压器发热少?2为什么光靠软件死区不够可靠?(死区门道多啊!)3MOSFET vs IGBT,优缺点怎么选?(器件基础)4LCL滤波器咋设计?(公式忘了,幸好说清了关键参数影响😅)5LC vs LCL滤波器区别?6逆变器输出电流THD从3%降到2%以下,你会改啥?7Boost拓扑和输入输出关系?(基础中的基...
点赞
评论
收藏
分享
01-01 14:48
字节跳动_TT图文_研发(实习员工)
如果你大二就开始实习,那么就会得到........
一整年就是飞飞飞,甚至一天飞两趟好不容易挣点钱全花机票上了明年秋招会善待我么
谁解其中味:
全球可飞
2025年终总结
点赞
评论
收藏
分享
01-13 09:50
哈尔滨工业大学(威海) Java
已经失去大厂梦了
来杭州实习的第三周,天天早九晚六感觉就已经很精神疲惫了,也没有多少私人时间,不敢想象如果是大厂的逆天作息我能活几年。果然人只有真正来上班了才知道自己想要什么,比起天天高强度被压榨拿到一份不错的薪水,我还是更喜欢能边摸鱼边混口饭吃。已经开始准备秋招找国企躺平了,大三想进国企该准备什么,是不是跟私企互联网招聘路子完全不一样,前边的准备是不是一点用没有了
千影逐风:
果然人与人之间的悲伤无法互通,我倒是希望能找到一个朝九晚六的工作
,之前996+246高强度发版直接给我整的ptsd了,现在看大小周都眉清目秀的
点赞
评论
收藏
分享
02-07 17:07
思摩尔国际(SMOORE)_IT开发工程师(准入职员工)
思摩尔内推,思摩尔内推码
思摩尔结构工程师一面一面技术面,面试官比较年轻,共23min1、面试官上来要求先说说你对思摩尔的了解2、自我介绍3、针对第一个项目的提问:项目背景?你承担的工作?你在项目中遇到的问题?你最大的收获?这些项目中设计的产品有在企业中应用过吗?没有应用的原因你觉得是什么?4、针对第二个项目的提问:在项目中成员有分歧怎么办?有人不配合怎么办?5、除了学校学习和项目科研的内容,你最近有学习过什么新技术吗?6、反问环节(最长的一次)面试官详细介绍了工作内容后续流程,还有总部的一轮面试思摩尔国际2026全球校园招聘倒计时❗还没拿到offer的同学抓紧时间⏰【急招岗位】①技术研发类硕士(24-30W):产品企...
点赞
评论
收藏
分享
评论
点赞成功,聊一聊 >
点赞
收藏
分享
评论
提到的真题
返回内容
全站热榜
更多
1
...
聊聊Agent实习
4673
2
...
【AI大模型投递必看】:高潜力投递企业清单(附详细解析)
4136
3
...
推荐一个值得做的AI项目
2329
4
...
字节 后端开发 (Agent中台)一面凉
1582
5
...
实习不会等你“准备好”
1495
6
...
小红书前端二面
1121
7
...
学校不让去实习怎么办,我真的好想哭
1014
8
...
我真的不理解为什么有人喜欢卷
931
9
...
上班一年半
877
10
...
Agent开发怎么转?28届双非求指点
823
创作者周榜
更多
正在热议
更多
#
春招什么时候投?
#
3053次浏览
48人参与
#
春节提前走,你用什么理由请假?
#
3675次浏览
73人参与
#
春节前,你还在投简历吗?
#
5274次浏览
59人参与
#
实习到现在,你最困惑的一个问题
#
1123次浏览
36人参与
#
备战春招/暑实,现在应该做什么?
#
1080次浏览
35人参与
#
牛友的春节生活
#
879次浏览
27人参与
#
从夯到拉,锐评职场mentor
#
1046次浏览
24人参与
#
聊聊Agent开发
#
11416次浏览
275人参与
#
距离春招还有一个月,你现在是什么开局?
#
2426次浏览
45人参与
#
推荐一个值得做的AI项目
#
3121次浏览
96人参与
#
暑期实习什么时候投?
#
2974次浏览
62人参与
#
通信硬件2024笔试面试经验
#
269025次浏览
2053人参与
#
实习必须要去大厂吗?
#
188362次浏览
1765人参与
#
双非本科的出路是什么?
#
208472次浏览
1565人参与
#
最难的技术面是哪家公司?
#
65332次浏览
971人参与
#
机械/制造每日一题
#
86571次浏览
1445人参与
#
实习想申请秋招offer,能不能argue薪资
#
218322次浏览
1171人参与
#
一份好的简历长什么样?
#
25365次浏览
448人参与
#
我想象的实习vs现实的实习
#
320870次浏览
2287人参与
#
机械人面试中的常问题
#
237479次浏览
3521人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务