大型网站架构设计-mysql分表与分库

2014-11-23 13:17:32     7,252 人阅读    

对于大型的互联网应用来说,数据库单表的记录行数可能达到千万级别甚至是亿级,并且数据库面临着极高的并发访问。采用Master-Slave复制模式的MySQL架构,只能够对数据库的 读进行扩展,而对数据的写入操作还是集中在Master上,并且单个Master挂载的Slave也不可能无限制多,Slave的数量受到Master能力和负载的限制。因此,需要对数据库的吞吐能力进行进一步的扩展,以满足高并发访问与海量数据存储的需要。

对于访问极为频繁且数据量巨大的单表来说,我们首先要做的就是减少单表的记录条数,以便减少数据查询所需要的时间,提高数据库的吞吐,这就是所谓的分表。在分表之前,首先 需要选择适当的分表策略,使得数据能够较为均衡地分布到多张表中,并且不影响正常的查询。

对于互联网企业来说,大部分数据都是与用户关联的,因此,用户id是最常用的分表字段。因为大部分查询都需要带上用户id,这样既不影响查询,又能够使数据较为均衡地分布到各个 表中12,如图2-9所示。

 

user表按照user_id%256的策略进行分表

2-9user表按照user_id%256的策略进行分表

 

假设有一张记录用户购买信息的订单表order,由于order表记录条数太多,将被拆分成256 张表13。拆分的记录根据user_id%256取得对应的表进行存储,前台应用则根据对应的 user_idQ%256,找到对应订单存储的表进行访问。这样一来user_id便成为一个必需的查询条件,否则将会由于无法定位数据存储的表而无法对数据进行访问。

假设user表的结构如下:

create table order(

order_id bigint(20) primary key auto_increment,

12当然,有的场景也可能会出现冷热数据分布不均衡的情况。 13拆分后表的数量一般为2的《次方。

user_id bigint(20), user_nick varchar(50), auction_id bigint(20), auction_title bigint(20), price bigint(20), auction_cat varchar(200), seller_id bigint(20), seller_nick varchar(50)

);

那么分表以后,假设user_id=257,并且auction_id=100,需要根据auction_id来查询对应的

订单信息,则对应的SQL语句如下:

select * from order_1 where user_id = 257 and auction_id = 100;

其中,order_1根据257%256计算得出,表示分表之后的第1order表。

分表能够解决单表数据量过大带来的查询效率下降的问题,但是,却无法给数据库的并发处理能力带来质的提升。面对高并发的读写访问,当数据库Master服务器无法承载写操作压力 时,不管如何扩展Slave服务器,此时都没有意义了。因此,我们必须换一种思路,对数据库 进行拆分,从而提高数据库写入能力,这就是所谓的分库。

与分表策略相似,分库也可以采用通过一个关键字段取模的方式,来对数据访问进行路由,如图2-10所示。

multi database

MySQL分库策略

2-10MySQL分库策略

 

还是之前的订单表,假设user_id字段的值为257,将原有的单库分为256个库,那么应用

程序对数据库的访问请求将被路由到第1个库(257%256=1)

有时数据库可能既面临着高并发访问的压力,又需要面对海量数据的存储问题,这时需要对数据库即采用分库策略,又采用分表策略,以便同时扩展系统的并发处理能力,以及提升单 表的查询性能,这就是所谓的分库分表。

分库分表的策略比前面的仅分库或者仅分表的策略要更为复杂,一种分库分表的路由策略如下:

           中间变量=user_id% (库数量X每个库的表数量)

           =取整(中间变量/每个库的表数量)

           =中间变量%每个库的表数量。

同样采用user_id作为路由字段,首先使用user_id对库数量X每个库表的数量取模,得到 一个中间变量;然后使用中间变量除以每个库表的数量,取整,便得到对应的库;而中间变量对每个库表的数量取模,即得到对应的表。分库分表策略如图2-11所示。

multi database and table

single table

分痄分表策略
temp user_id%(256xl24)

order

2-11 MySQL分库分表策略

假设将原来的单库单表order拆分成256个库,每个库包含1024个表,那么按照前面所提到的路由策略,对于user_id=262145的访问,路由的计算过程如下:

中间变量=262145% (256X1024) =1;

=取整(1/1024) =0;

=1%1024=1

这意味着,对于user_id=262145的订单记录的查询和修改,将被路由到第0个库的第1个 表中执行。

数据库经过业务拆分及分库分表之后,虽然查询性能和并发处理能力提高了,但也会带来一系列的问题。比如,原本跨表的事务上升为分布式事务;由于记录被切分到不同的库与不同 的表当中,难以进行多表关联查询,并且不能不指定路由字段对数据进行查询。分库分表以后,如果需要对系统进行进一步扩容(路由策略变更),将变得非常不方便,需要重新进行数据迁移。

相较于MySQL的分库分表策略,后面要提到的HBase天生就能够很好地支持海量数据的存储,能够以更友好、更方便的方式支持表的分区,并且HBase还支持多个Region Server同时 写入,能够较为方便地扩展系统的并发写入能力。而通过后面章节所提到的搜索引擎技术,能够解决采用业务拆分及分库分表策略后,系统无法进行多表关联查询,以及查询时必须带路由 字段的问题。搜索引擎能够很好地支持复杂条件的组合查询,通过搜索引擎构建的一张大表,能够弥补一部分数据库拆分所带来的问题。

 

本文出自   《大型分布式网站架构设计与实践试读样章》 试读,如果感觉到对你有帮助可以去购买该书


原文地址:http://www.itmmd.com/201411/208.html
该文章由 萌萌的IT人 整理发布,转载须标明出处。

java Rest学习-第一个Java REST 服务(1)-开发环境搭建   上一篇
下一篇  大型网站架构设计-MySQL 大数据大并发支持

精彩回复
#1楼    ; [评论人]:耗子   [发表时间]:2016-9-29 17:31:30

这篇文章让我对分库分表有了一个大致的了解,谢谢

发表评论
姓名: