MySql分库分表解决方案

为什么要进行分库分表

  1. 超大容量

  2. 性能问题

个别单表数据可能上亿,从而出现IO瓶颈,引起查询效率的问题,所以需要 分表

使用单个数据库解决所有应用节点的话,数据库所在的服务器的性能瓶颈,也会导致数据性能下降,所以需要 分库

分表分库,也叫做 数据分片

如何分表分库

  1. 垂直分表

  2. 垂直分库

  3. 水平分表

垂直分表

拆分列,就是垂直分表,比如商品表可以拆分为商品信息表、商品标签表、商品价格表… 然后通过关联关系维持他们之间的联系。

优点

  1. 解决了当单表列过多时,会造成mysql性能瓶颈的问题

解决单个表中列过多的问题。

垂直分库

根据业务模块划分数据库,比如订单数据库、用户数据库…

优点

  1. 业务拆分、解耦

  2. 每个数据库可以部署在不同的服务器上(资源利用率高)

  3. 大部分公司都是根据soa的节点去划分

解决了单个库中表数量过多的问题。

水平分表

大数据表拆为小表,当一张表的数据上亿时,IO瓶颈明显,比如订单表可以拆分为多个小的订单表,从而提高查询效率…

mysql官方性能数据:单表的查询瓶颈在500-1000万左右,超过1000万将会出现性能问题。

常见的拆分策略

垂直拆分

垂直拆分需要根据业务来决定拆分情况,最好将有关联的表放入同意库中,避免跨数据库查询。

水平拆分

一致性hash

根据某个字段的维度,进行拆分,比如,将 t_user 表拆分为10个小表,可以使用 userId%10 进行分库,根据他的只将数据保存在对应的表中。

取模的方式当模发生变化时,就会影响已经拆分的数据,从而要进行数据迁移。

字段的选择将会影响sql实现的难度。

范围切分

比如,userId在 [0, 100w)之间的数据放入到user1表中。

日期拆分

比如,将2018年注册的用户放入到 user_2018表中。

拆分的问题

跨库join

解决方案:

  1. 服务层调用:rpc先查出user信息,再给order服务使用,注意要提供批量查询接口,不可多次调用服务进行处理

  2. 使用全局表,每个应用都可以查询此表,全局表的数据应该比较固定

  3. 字段冗余(空间换时间):很多地方都需要进行id关联,但是经常需要name字段,可以将字段冗余到此表中。(新问题,如何同步name?A: 定时任务、任务通知、触发器)

跨分片数据排序分页

跨库分页查询,排序问题

解决方案:

  1. 应用层拼接(组装拼接)

  2. 改造

唯一主键问题

用自增id作为主键,而自增id只在但表中唯一,多个表之间有可能重复

解决方案:

  1. UUID,缺点:值太大,影响索引效率

  2. 算法生成:snowflke

  3. mongDB,Redis 作为主键,或者使用zookeeper

  4. 全局id表

分布式事务问题

多个数据库表之间保证原子性,事务将会导致性能问题。

一般的互联网公司使用强一致性事务比较少。

如何权衡存储优化

  1. 提前规划,比如数据量将会在半年指数增长(逐渐问题、join),进行防范

  2. 当前数据单表超过1000W,每天的增长量持续上升,此时优化迫切

水平分割

当一个表数据过多时,可以使用表分割。

分表的基本方案:

  1. 将qq用户表分为三张表:qqlogin0, qqlogin1, qqlogin2

  2. 当创建用户时,将用户id%3 得到一个 >=0 && <3 的数,分别存入不同的表中

  3. 当查询用户时,根据用户id%3得到的值,分别去不同的表查询

我们在提供检索时,应该根据业务的需求,找到分表的标准,并在检索页面,约束用户的检索方式。

根据业务需求: 会员

约束检索条件:必须输入到市级别的地址

垂直分割

表的某些字段,在查询时,并不是实时需要关心的,而且数据量又很大,建议可以将这些字段单独提取到另一张表中,保持关联关系,从而提高效率。

最后更新于