【高频java面试】关于mysql 的分库分表的实现

背景!

一、影响数据库性能的因素:

(1)、数据量

          MySQL单库数据量在5000万以内性能比较好,超过阈值后性能会随着数据量的增大而变弱。

           MySQL单表的数据量是500w-1000w之间性能比较好,超过1000w性能也会下降。

(2)、磁盘

       因为单个服务的磁盘空间是有限制的,如果并发压力下,所有的请求都访问同一个节点,肯定会对磁盘IO造成非常大的影响。

(3)、数据库连接

       海量用户同时访问同一数据库(根据不同的条件)

二、解决方法:

1、垂直拆分

2、水平拆分

垂直拆分:根据业务进行拆分,比如可以将一张表中的多个字段拆成两张表,一张是不经常更改的,一张是经常改的。

水平拆分:即根据表来进行分割:比如user表可以拆分为user0,、user1、user2、user3、user4等

2、分库分表之后如何实现联合查询?

可以使用第三方中间件来实现,比如:mycat、shading-jdbc

3、原理解析

当客户端发送一条sql查询:select * from user;此时中间件会根据有几个子表,拆分成多个语句:select * from user1;select * from user2;select * from user3等多条语句查询,然后将查询的结果返回给中间件,然后汇总给客户端。这些语句是并发执行的,所以效率会很高哦。

三、几种常用的分库分表的策略

  • HASH取模
    假设有用户表user,将其分成3个表user0,user1,user2.路由规则是对3取模,当uid=1时,对应到的是user1,uid=2时,对应的是user2.

  • 范围分片
    从1-10000一个表,10001-20000一个表。

  • 地理位置分片
    华南区一个表,华北一个表。

  • 时间分片
    按月分片,按季度分片等等,可以做到冷热数据。

四、引入分库分表后造成的影响

1、分布式事务问题

     垂直分库或者水平分库以后,就会涉及到跨库执行SQL的问题,引发了"分布式事务"。

  • 1.使用分布式事务中间件
  • 2.使用MySQL自带的针对跨库的事务一致性方案(XA),不过性能要比单库的慢10倍左右。
  • 3.能否避免掉跨库操作(比如将用户和商品放在同一个库中)

2、跨库join的问题

分库分表后表之间的关联将受到限制,将无法join位于不同分库的表,也无法join分表粒度不同的表,造成业务查询次数变多,

解决办法:

  • 1、全局表:基础数据,所有的库都拷贝一份
  • 2、字段冗余:
  • 3、系统层组装:分别查询所有,然后组装起来,较复杂

3、横向扩容问题
      当我们使用HASH取模做分表的时候,针对数据量的递增,可能需要动态的增加表,此时就需要考虑因为reHash导致数据迁移的问题。

4、结果集合并、排序的问题
因为我们是将数据分散存储到不同的库、表里的,当我们查询指定数据列表时,数据来源于不同的子库或者子表,就必然会引发结果集合并、排序的问题。如果每次查询都需要排序、合并等操作,性能肯定会受非常大的影响。可以考虑走缓存

【高频java面试】关于mysql 的分库分表的实现