高性能架构-高性能数据库集群:分库分表

高性能数据库集群:分库分表

01 | 导读

1、读写分离分散了数据库读写操作的压力,但是没有分散存储压力。

2、数据量达到千万甚至上亿条时,单台数据库服务器的存储能力会成为系统的瓶颈,主要体现在:

1)数据量太大,读写的性能会下降,即使有索引,索引也会变得很大,性能同样会下降。
2)数据文件变大,备份和恢复需要耗费很长时间。
3)数据文件越大,丢失数据的风险越高。

3、常见的分散存储的方法“分库分表”,其中包括“分库”和“分表”两大类。

02 | 业务分库

1、业务分库指的是按照业务模块将数据分散到不同的数据库服务器
高性能架构-高性能数据库集群:分库分表_第1张图片

2、业务分库能够分散存储和访问压力,同时也带来了新的问题:

	1)join 操作问题
		1. 业务分库后,原来在同一个数据库中的表分散到不同的数据库中,导致无法使用SQL的join查询。
		2. 例如查询购买了新奥产品的女性用户列表,需要查两次,再匹配。
	2)事务问题
		1. 原来在同一个数据库中不同的表可以在同一个事物中修改,业务分库后,表分散到不同的数据库中,无法通过事务统一修改。
		2. 例如下单扣库存(减库存和生成订单)可以一同成功或失败,现在,分库后需要分两次进行,事后需要事务补偿的机制(如通过日志)来解决减库存和生成订单的匹配性问题。
	3)成本问题
		1. 业务分库同时也带来了成本的代价,本来1台服务器搞定的事情,现在需要3台,如果考虑备份,就需要6台。

03 | 分表

1、分表的条件

1)将不同业务分散存储到不同的数据库服务器,能够支撑百万甚至千万用户规模的业务。
2)业务继续发展,同一业务的单表数据也会达到单台数据库服务器的处理瓶颈。如淘宝几亿用户数据,存在在一张表中,无法满足性能要求,需要对单表数据进行拆分。

2、单表数据拆分的两种方式:垂直分表和水平分表。

1)从上往下切就是垂直切分,对应到表的切分就是表记录数相同但包含不同的列。例如图中一个表包含ID、name、age、sex列,另一个表包含ID、nickname、description列。
2)从左往右切就是水平切分,对应到表的切分就是表的列相同但包含不同的行数据。例如图中一个表包含1到999999的行数据,另一个表包含1000000到9999999的行数据。
3)实际架构中并不局限切分的次数,可以切多次。
4)单表切分后,可以根据实际的切分效果确定,并不强制要求单表切分为多表后一定要分散到不同的数据库中。新的表即使在同一个数据库中,也可能带来可观的性能提升,如果性能满足业务要求,是可以不拆分到多台数据库服务器的。

高性能架构-高性能数据库集群:分库分表_第2张图片

3、垂直分表

1)垂直分表适合将表中某些不常用,且占了大量空间的列拆分出去。例如婚恋网,筛选时多按年龄和性别,其他昵称和介绍可以放到另外一个表中。
2)垂直分表引入的复杂性主要体现在表操作的数据量要增加。原来的一次查询就可以,现在需要两次才能获得结果(一次查年龄和性别,一次查昵称和介绍)。

4、水平分表

1)水平分表适合行数特别大的表,一般来说当表的数据量达到千万级别时,就要警觉起来,这很可能是架构的性能瓶颈或者隐患。
2)引入的复杂性:路由、join操作、count() 操作、order by 操作
3)路由:范围路由、Hash路由、配置路由

	1. 范围路由:选取有序的数据序列(例如,整形、时间戳等)作为路由的条件,不同分段分散到不同的数据库表中。
		a. 复杂点在分段大小的选取上,分段太小,子表数量多,维护困难;分段太大,可能依然存在性能问题。一般建议分段大小在100万到2000万之间,具体根据业务选取分段大小。
		b. 优点:可以随着数据增加平滑地扩充新的表。
		c. 缺点:分布不均匀,可能某个表只存在几条数据。
	2. Hash路由:选取某个列(或者某几个列组合也可以)的值进行Hash运算,然后根据Hash结果分散到不同的数据库表中。
		a. 复杂点在初始表数量的选取上,太多维护麻烦,太少存在性能问题。而且当增加子表数量时,所有数据需要重新分布。
		b. 优缺点和范围分布相反。
	3. 配置路由:就是路由表,用一张独立的表来记录路由信息。例如以用户id为例,新增一张user_router表,表包含user_id 和 table_id两列,根据user_id 查询table_id。
		a. 缺点:必须多查一次,会影响性能。此外,如果路由表太大,性能同样可能成为瓶颈,需要再次分库分表,这样就陷入死循环。

4)join操作

	1. 水平分表后,数据分散在多个表中,如果需要与其他表进行join查询,需要在业务代码或者数据库中间件中进行多次join查询,然后将结果合并。

5)count() 操作

	1. 水平分表后,虽然物理上数据分散到多个表中,但某些业务逻辑上还是会将这些表当作一个表来处理。
	2. 处理方法:count()相加和记录数表。

6)order by 操作

	1. 水平分表后,数据分散到多个子表中,排序操作无法在数据库中完成,只能有业务代码或者数据库中间件分别查询每个子表中的数据,然后汇总进行排序。

04 | 实现

1、和数据库读写分离类似,

1)分库分表具体的实现方式也是“程序代码封装”和“中间件封装”,但是实现会更复杂。

2、读写分离:

1)需要识别SQL是读操作还是写操作,通过简单的判断SELECT、UPDATE、INSERT、DELETE几个关键字就可以了。

3、分库分表:

1)除了要判断操作类型外,还要判断SQL中具体需要操作的表、操作函数(例如count()函数)、order by、group by操作等,然后根据不同的操作进行不同的处理。

05 | 小结

1、分库分表前需要先尝试下列操作

1)做硬件优化,例如从机械硬盘改成使用固态硬盘,当然固态硬盘不适合服务器使用,只是举个例子
2)先做数据库服务器的调优操作,例如增加索引,oracle有很多的参数调整;
3)引入缓存技术,例如Redis,减少数据库压力
4)程序与数据库表优化,重构,例如根据业务逻辑对程序逻辑做优化,减少不必要的查询;
5)在这些操作都不能大幅度优化性能的情况下,不能满足将来的发展,再考虑分库分表,也要有预估性。

参考文献:

[1] 李运华. 从0开始学架构[M]. 极客时间, 2018.
[2]图片取自【从0开始学架构】专栏

你可能感兴趣的:(#,架构专题,#,网络和数据库专题,mysql,数据库,分库分表)