后端存储实战课
李玥
京东零售计算存储平台部资深架构师
立即订阅
4656 人已学习
课程目录
已完结 28 讲
0/4登录后,你可以任选4讲全文学习。
课前必读 (2讲)
开篇词 | 从今天起,换种方式学存储
免费
课前加餐 | 电商系统是如何设计的?
创业篇 (7讲)
01 | 创建和更新订单时,如何保证数据准确无误?
02 | 流量大、数据多的商品详情页系统该如何设计?
03 | 复杂而又重要的购物车系统,应该如何设计?
04 | 事务:账户余额总是对不上账,怎么办?
05 | 分布式事务:如何保证多个系统间的数据是一致的?
06 | 如何用Elasticsearch构建商品搜索系统?
07|MySQL HA:如何将“删库跑路”的损失降到最低?
高速增长篇 (7讲)
08 | 一个几乎每个系统必踩的坑儿:访问数据库超时
09 | 怎么能避免写出慢SQL?
10 | 走进黑盒:SQL是如何在数据库中执行的?
11 | MySQL如何应对高并发(一):使用缓存保护MySQL
12 | MySQL如何应对高并发(二):读写分离
13 | MySQL主从数据库同步是如何实现的?
14 | 订单数据越来越多,数据库越来越慢该怎么办?
海量数据篇 (10讲)
15 | MySQL存储海量数据的最后一招:分库分表
16 | 用Redis构建缓存集群的最佳实践有哪些?
17 | 大厂都是怎么做MySQL to Redis同步的?
18 | 分布式存储:你知道对象存储是如何保存图片文件的吗?
19 | 跨系统实时同步数据,分布式事务是唯一的解决方案吗?
20 | 如何在不停机的情况下,安全地更换数据库?
21 | 类似“点击流”这样的海量数据应该如何存储?
22 | 面对海量数据,如何才能查得更快?
23 | MySQL经常遇到的高可用、分片问题,NewSQL是如何解决的?
24 | RocksDB:不丢数据的高性能KV存储
结课测试 (1讲)
结课测试 | 后端存储,100分试卷等你来挑战
结束语 (1讲)
结束语 | 把奋斗当习惯
后端存储实战课
15
15
1.0x
00:00/00:00
登录|注册

15 | MySQL存储海量数据的最后一招:分库分表

李玥 2020-03-31
你好,我是李玥。
从这节课开始,我们课程将进入最后一部分“海量数据篇”,这节课也是我们最后一节主要讲 MySQL 的课程。解决海量数据的问题,必须要用到分布式的存储集群,因为 MySQL 本质上是一个单机数据库,所以很多场景下不是太适合存 TB 级别以上的数据。
但是,绝大部分的电商大厂,它的在线交易这部分的业务,比如说,订单、支付相关的系统,还是舍弃不了 MySQL,原因是,只有 MySQL 这类关系型数据库,才能提供金融级的事务保证。我们之前也讲过分布式事务,那些新的分布式数据库提供的所谓的分布式事务,多少都有点儿残血,目前还达不到这些交易类系统对数据一致性的要求。
那既然 MySQL 支持不了这么大的数据量,这么高的并发,还必须要用它,怎么解决这个问题呢?还是按照我上节课跟你说的思想,分片,也就是拆分数据。1TB 的数据,一个库撑不住,我把它拆成 100 个库,每个库就只有 10GB 的数据了,这不就可以了么?这种拆分就是所谓的 MySQL 分库分表。
不过,思路是这样没错,分库分表实践起来是非常不容易的,有很多问题需要去思考和解决。

如何规划分库分表?

还是拿咱们的“老熟人”订单表来举例子。首先需要思考的问题是,分库还是分表?分库呢,就是把数据拆分到不同的 MySQL 库中去,分表就是把数据拆分到同一个库的多张表里面。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《后端存储实战课》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(28)

  • 李玥 置顶
    Hi,我是李玥。

    这里回顾一下上节课的思考题:

    在数据持续增长的过程中,今天介绍的这种“归档历史订单”的数据拆分方法,和直接进行分库分表相比,比如说按照订单创建时间,自动拆分成每个月一张表,两种方法各有什么优点和缺点?欢迎你在留言区与我讨论。

    这个问题我在本节课中也提到了,简单的总结一下。按月自动拆分订单的好处是,不需要做数据搬运,相对实现比较简单,数据分得更碎,缺点是跨月查询比较麻烦,但好处是容量也更大(因为分片更多)。归档历史订单的方法,实现起来更复杂,容量要小一些,但是对查询更加友好。
    2020-04-01
    13
  • 每天晒白牙
    分库分表的原则
    能不拆就不拆,能少拆就少拆

    分库分表的目的
    1.数据量大查询慢的问题
    解决查询慢就是减少每次查询的数据量,即分表可以解决该问题
    2.应对高并发的问题
    一个数据库实例撑不住就分散到多个实例中去,即分库可以解决

    概括就是数据量大就分表,高并发就分库

    如何选择 sharding key?
    这是分表的依据,选择要考虑的因素取决于业务如何访问数据,让查询尽量落到一个分片中。如果分片无法兼容查询,可以把数据同步到其他存储中,供查询

    常见的分片算法
    1.范围分片
    对查询友好,适合并发量不大的场景。但容易产生热点数据
    2.哈希分片
    比较均匀
    3.查表法
    灵活,性能差因为多了一次查表

    实例案例
    订单表分库分表
    一般按用户id分,采用哈希分片算法。为了支持按订单号查询,可以把用户id的后几位放到订单号中
    2020-04-01
    13
  • 忆澜
    接“发条橙子”“用完整用户id分片还是后四位分片”对话:为什么是一样的啊,没懂……比如300个分片,用取模法,用户id分别为12000和22000,后四位相同但查找的表不同呀……我感觉这块没说清楚,我听完之后也有这个疑惑

    作者回复: 这个地方详细说一下,比如只取用户ID后四位,为了保证后四位的哈希结果和完整用户ID的哈希结果是一样的,分片的数量需要能被10000整除。300个分片是不行的,200、250这种分片数量就是可以满足要求的。

    2020-04-13
    2
    12
  • leslie
    是不是漏了另外一种拆分方式:纵向拆分?分表应当还有一个原因,早期数据量小可以几十个字段都没有关系;后期数据量大了,多列查询导致了一些性能问题。我自己在生产中就碰到了设计的不合理性,做了纵向分表-效果还不错,精度只能靠实战、学习、反思去提升。
    课程中提及的分表所引发的外键问题其实应当和DML有关:查询并无影响。个人觉得影响不大,细看是多张表,但是设计时其实还是一张;查询时对应的判断补进去就好。

    作者回复: 👍👍👍

    2020-04-02
    11
  • Mq
    关联表可以冗余用户ID字段,跟订单表的都在一个库里吗,这样用户维度的交易都在一个库事物里面,大部分的关联查询也是在一个库里。
    老师查找法有具体例子吗,我们之前也有过表按hash分后数据极度不均

    作者回复: 查表法一般可以配合哈希或者范围分片一起使用。

    比如说,我们按用户ID哈希分成10个分片,其中第8个分片数据特别多不均匀。

    那我们可以按用户ID哈希成100个逻辑分片。

    再做一个100逻辑分片和10个物理分片的映射表,这个表里面只有100条记录。

    那怎么来映射我们就可以人工分配,让10个物理分片中的数据尽量均匀。

    2020-03-31
    9
  • Loren
    老师,请教一个问题,分库分表以后,数据量大的情况下,分页一般该怎么处理?我暂时没这方面的经验,想了解一下

    作者回复: 如果需要分库分表还要跨表查询,这种情况下没有什么好的分页解决方案,业务还是要规避分库分表之后跨表查询的情况。

    如果实在规避不了,就要考虑sharding key是不是合理,或者可能要更换数据库。

    2020-04-04
    4
  • 虚竹
    老师好,订单id总共18位,10-14位放用户id的后几位,当用户要查询自己的所有订单时怎么查呢?这里没太明白

    作者回复: 直接用用户ID哈希,计算出这个用户的订单在哪个分片上,然后去查询就可以了。

    2020-03-31
    5
    4
  • 正在减肥的胖籽。
    老师您好,有几个问题需要请教你下:
    1.运营后台查询数据,肯定就是查询很多数据,不止是单个用户的数据。京东怎么去处理运营后台的数据呢?是把数据同步到ES中还是?

    作者回复: 是的,一般是同步到其它的数据库中去解决。我会在19中来讲,如何做实时同步。

    2020-03-31
    4
  • sami
    感觉Redis Cluster的分片规则有点像查表法

    作者回复: 你说的没错!

    2020-03-31
    4
  • 旅途
    老师 问几个问题
    1.用户Id的根据性别的0,1,这样分表为什么会造成热点问题,只看到了分表数据可能不均匀?
    2.使用分表映射表,这种如果要修改映射是怎么做的呢?是直接修改表记录还是修改代码,在生成的时候让他改变?

    作者回复: 1. 因为有可能用户的男女比例不同,造成分片不均衡,出现热点。
    2. 如果要修改分片映射,一般的流程是:先完成扩容和数据复制,然后直接修改分片映射表。不需要修改代码。

    2020-05-04
    1
    3
  • 请问老师,假设现在是24个分片,使用取模算法,后续发现分片后数据量还是太大,要改成扩大分片数,需要重新迁移数据吧?工作量大且复杂,该怎么设计比较方便扩容呢

    作者回复: 比较方便的方法是扩容后的分片数量是24的整数倍,这样每个分片相当于1分n。或者在设计之初就采用一致性哈希算法来分片。

    2020-04-19
    3
  • 曙光
    老师,我有个生产问题,内部管理系统,使用的是Oracle数据库,按月分表,该表每天新增近6W的数据,目前共有1亿的数据量。现在的问题是,业务每天都需要查这个表进行对账,查询速度很慢,每次慢的适合,我们就重建索引速度就快一点,过一段时间又会变慢。最要命的事,这些数据有一个归属人的字段,如果某个人换部门或离职,这部分历史数据都要归宿新人,涉及历史数据的修改。 之前通过归档历史表,处理查询慢的问题,发现还没重建索引收益高,就没修改了。但是交易归属人就比较麻烦,一次变更需要2~3分钟,体验很差。我目前想的解决方案是:重构历史功能,将交易表拆分成两张表,账户表,交易余额对账表和人员归属表,虽然每天6w笔数据,但大部分账户是一样的只是余额不一样。这样查询的话,每次需要关联3张表。如果真的这样实施,需要修改很多中间表的洗数流程。面对目前的数据量,我这种方案可行么?还有更好的修改方案么? 怕自己盲目修改后,和之前的查询修改性能差不多,就白忙活了

    作者回复: 如果一亿的数据分12个月,那实际上每个月的表中大概是一千万左右的数据,这个量级的数据,在做好索引的前提下,查询不会很慢。

    建议你先看一下查询的执行计划,找出为什么慢的原因。

    另外,你没有提到表中的数据是否会频繁删除。如果频繁插入和删除数据的这张表,它的索引会越来越大,定期重建索引是有必要的。

    2020-04-19
    2
    3
  • 闫冬
    分表分库的原则,能通过其他方式优化的就不去分库分表,一来容易出错二来增加了系统的复杂度
    根据不同的场景原则分库还是分表
    如果是数据量大则分表 如果并发量大则分库
    分表又分水平分表和垂直分表
    垂直分表主要应用于当表的字段过多时,讲常用的字段分到一个表 不常用的分到一个表

    水平分表比较复杂
    可以按时间划分 也可以哈希 取模
    时间划分比较适用于 经常按时段 热度没那么高的场景 因为如果有热点数据会造成分布不均衡
    哈希 取模主要应用于按某个字段分表 分布比较均匀 但是范围查找又会有问题 可以通过冗余表来实现

    异构表 相当于索引表 可以人为的调整 灵活 但是性能没有 哈希或取模快

    有一个小技巧 就是订单号可以隐藏一些信息 这样避免一些场景的局限性
    2020-04-17
    2
    3
  • 饭团
    老师您好,您提到的把用户id放到订单id中,是说如果用订单id去做查询,就把第10-14位取出来,之后再用这部分去查询是吗?

    作者回复: 是的

    2020-03-31
    15
    3
  • Echo
    老师您好:您文中说“范围分片特别适合那种数据量非常大,但并发访问量不大的 ToB 系统”,如果是这样的话 并发量不大的ToB 系统就没必要分库了吧?因为分库要解决的是高并发的问题。可以用分表或者归档的方式解决?

    作者回复: 是这样的。

    2020-05-16
    2
  • gfgf
    用户id和订单id关联这块,订单中取用户id的几位来做分区分表的依据,这个做法是否会造成数据量的不均衡;
    看到个人淘宝订单是嵌入了用户id的后几位,但是京东订单没有发现规律,这块能否请老师以淘宝和京东订单为例,做一个更深入的介绍

    作者回复: 订单号是怎么构成的,应该算是商业秘密了。因为如果你知道它的规律,是有可能从中获得一些信息的。所以各家都不会公布自己的订单号是如何构成的。

    2020-04-01
    2
  • cha
    老师,请教一个问题。我看网上分库分表,有的说要2的N次方,没想明白是怎么个缘故。

    作者回复: 因为取模的时候更快一些,如果是业务类的系统,这点儿差别可以忽略不计了。

    如果你是做存储系统或者中间件类产品,还是需要考虑这个因素的。

    2020-06-24
    1
    1
  • 隰有荷
    是否可以采用mycat中间件的方式去实现分表,让代码使用过程中不感知分表带来的变化呢?

    作者回复: 某些场景下是可以的,具体还要根据业务情况来权衡。mycat的优点是对业务透明,不用修改代码,缺点是加长了调用链路,增加了故障点、降低了性能。

    2020-05-10
    1
  • StopLiu
    按时间范围分片后,例如每月一个分片,但如果用户查询时想要3月15-4月15这种,就会跨月查询,这种怎么解决?

    作者回复: 这种情况使用MySQL没有太好的解决方案,你可以看一下后面的19、22二节课,尝试使用其它的数据库来解决而你的问题。

    2020-04-13
    1
  • Mr.wang
    李老师你好,我想请教一个问题,有一个数据量比较大的表,由于业务的需要,需要在表里面建一条普通索引,这张表的日并发量在三四百万左右,请问下李老师除了在业务量小的时候执行,还要其他比较好的建议去加这个索引吗?
    2020-05-30
收起评论
28
返回
顶部