MySQL分库分表

分表是分散数据库压力的好方法。分表,最直白的意思,就是将一个表结构分为多个表,然后,可以再同一个库里,也可以放到不同的库。当然,首先要知道什么情况下,才需要分表。个人觉得单表记录条数达到百万到千万级别时就要使用分表了。

一、分库分表方式

1、纵向分表

将本来可以在同一个表的内容,人为划分为多个表。(所谓的本来,是指按照关系型数据库的第三范式要求,是应该在同一个表的。)

分表理由:根据数据的活跃度进行分离,(因为不同活跃的数据,处理方式是不同的)案例:对于一个博客系统,文章标题,作者,分类,创建时间等,是变化频率慢,查询次数多,而且最好有很好的实时性的数据,我们把它叫做冷数据。而博客的浏览量,回复数等,类似的统计信息,或者别的变化频率比较高的数据,我们把它叫做活跃数据。所以,在进行数据库结构设计的时候,就应该考虑分表,首先是纵向分表的处理。这样纵向分表后:首先存储引擎的使用不同,冷数据使用MYISAM可以有更好的查询数据。活跃数据,可以使用Innodb ,可以有更好的更新速度。其次,对冷数据进行更多的从库配置,因为更多的操作时查询,这样来加快查询速度。对热数据,可以相对有更多的主库的横向分表处理。其实,对于一些特殊的活跃数据,也可以考虑使用memcache ,redis  之类的缓存,等累计到一定量再去更新数据库。或者mongodb 一类的nosql 数据库,这里只是举例,就先不说这个。

垂直切分的长处

◆ 数据库的拆分简单明了,拆分规则明白;

◆ 应用程序模块清晰明白,整合easy。

◆ 数据维护方便易行,easy定位。

垂直切分的缺点

◆ 部分表关联无法在数据库级别完毕。须要在程序中完毕。

◆ 对于訪问极其频繁且数据量超大的表仍然存在性能平静,不一定能满足要求。

◆ 事务处理相对更为复杂;

◆ 切分达到一定程度之后,扩展性会遇到限制;

◆ 过读切分可能会带来系统过渡复杂而难以维护。

2、横向分表

字面意思,就可以看出来,是把大的表结构,横向切割为同样结构的不同表,如,用户信息表,user_1,user_2 等。表结构是完全一样,但是,根据某些特定的规则来划分的表,如根据用户ID来取模划分。

分表理由:根据数据量的规模来划分,保证单表的容量不会太大,从而来保证单表的查询等处理能力。案例:同上面的例子,博客系统。当博客的量达到很大时候,就应该采取横向分割来降低每个单表的压力,来提升性能。例如博客的冷数据表,假如分为100个表,当同时有100万个用户在浏览时,如果是单表的话,会进行100万次请求,而现在分表后,就可能是每个表进行1万个数据的请求(因为,不可能绝对的平均,只是假设),这样压力就降低了很多很多。

水平切分的长处

◆ 表关联基本能够在数据库端全部完毕;

◆ 不会存在某些超大型数据量和高负载的表遇到瓶颈的问题;

◆ 应用程序端总体架构修改相对较少;

◆ 事务处理相对简单;

◆ 仅仅要切分规则能够定义好。基本上较难遇到扩展性限制;

水平切分的缺点

◆ 切分规则相对更为复杂,非常难抽象出一个能够满足整个数据库的切分规则;

◆ 后期数据的维护难度有所添加,人为手工定位数据更困难;

◆ 应用系统各模块耦合度较高,可能会对后面数据的迁移拆分造成一定的困难。

二、分表策略

1、HASH取模

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

2、范围分片

从1-10000一个表,10001-20000一个表。

3、地理位置分片

华南区一个表,华北一个表。

4、时间分片

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

三、分表解决办法

数据的整合非常难依靠数据库本身来达到这个效果,尽管MySQL存在Federated存储引擎,能够解决部分相似的问题。可是在实际应用场景中却非常难较好的运用。那我们该怎样来整合这些分散在各个MySQL主机上面的数据源呢?

总的来说,存在两种解决思路:

1. 在每一个应用程序模块中配置管理自己须要的一个(或者多个)数据源。直接訪问各个数据库,在模块内完毕数据的整合;

2. 通过中间代理层来统一管理全部的数据源。后端数据库集群对前端应用程序透明;

可能90%以上的人在面对上面这两种解决思路的时候都会倾向于选择另外一种,尤其是系统不断变得庞大复杂的时候。确实。这是一个非常正确的选择,尽管短期内须要付出的成本可能会相对更大一些,可是对整个系统的扩展性来说,是非常有帮助的。所以,对于第一种解决思路我这里就不准备过多的分析,以下重点分析一下在另外一种解决思路中的一些解决方式。

1、自行开发中间代理层

在决定选择通过数据库的中间代理层来解决数据源整合的架构方向之后,有不少公司(或者企业)选择了通过自行开发符合自身应用特定场景的代理层应用程序。

通过自行开发中间代理层能够最大程度的应对自身应用的特定。最大化的定制非常多个性化需求,在面对变化的时候也能够灵活的应对。这应该说是自行开发代理层最大的优势了。当然,选择自行开发,享受让个性化定制最大化的乐趣的同一时候,自然也须要投入很多其它的成本来进行前期研发以及后期的持续升级改进工作。并且本身的技术门槛可能也比简单的Web应用要更高一些。所以,在决定选择自行开发之前,还是须要进行比較全面的评估为好。

2、利用MySQLProxy实现数据切分及整合

MySQLProxy是MySQL官方提供的一个数据库代理层产品,和MySQLServer一样,相同是一个基于GPL开源协议的开源产品。可用来监视、分析或者传输他们之间的通讯信息。他的灵活性同意你最大限度的使用它,眼下具备的功能主要有连接路由,Query分析,Query过滤和修改,负载均衡。以及主要的HA机制等。

实际上,MySQLProxy本身并不具有上述全部的这些功能。而是提供了实现上述功能的基础。

要实现这些功能,还须要通过我们自行编写LUA脚本来实现。

3、利用Amoeba实现数据切分及整合

Amoeba是一个基于Java开发的,专注于解决分布式数据库数据源整合Proxy程序的开源框架,基于GPL3开源协议。眼下,Amoeba已经具有Query路由,Query过滤,读写分离,负载均衡以及HA机制等相关内容。

Amoeba 主要解决的以下几个问题:

  1. 数据切分后复杂数据源整合;

  2. 提供数据切分规则并降低数据切分规则给数据库带来的影响。

  3. 降低数据库与client的连接数。

  4. 读写分离路由;

3、利用HiveDB实现数据切分及整合**

和前面的MySQLProxy以及Amoeba一样,HiveDB相同是一个基于Java针对MySQL数据库的提供数据切分及整合的开源框架,仅仅是眼下的HiveDB仅仅支持数据的水平切分。

主要解决大数据量下数据库的扩展性及数据的高性能訪问问题,同一时候支持数据的冗余及主要的HA机制。

HiveDB的实现机制与MySQLProxy和Amoeba有一定的差异,他并非借助MySQL的Replication功能来实现数据的冗余,而是自行实现了数据冗余机制,而其底层主要是基于HibernateShards来实现的数据切分工作。

###4、mycat 数据整合

具体ttp://www.songwie.com/articlelist/11

四、分库分表存在的问题

1、 事务问题。

在执行分库分表之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价;如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。

2、跨库跨表的join问题。

在执行了分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上,这时,表的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表,结果原本一次查询能够完成的业务,可能需要多次查询才能完成。

3、额外的数据管理负担和数据运算压力。

额外的数据管理负担,最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题,这些都可以通过应用程序解决,但必然引起额外的逻辑运算,例如,对于一个记录用户成绩的用户数据表userTable,业务要求查出成绩最好的100位,在进行分表之前,只需一个order by语句就可以搞定,但是在进行分表之后,将需要n个order by语句,分别查出每一个分表的前100名用户数据,然后再对这些数据进行合并计算,才能得出结果。

作者

sunct

发布于

2019-03-08

更新于

2020-12-24

许可协议


评论