数据拆分
- Data partitioning (Sharding)
将大型数据库DB分成许多小的部分。通过多台机器拆分DB/Table。数据分区后,当系统到达某个点之后,通过增加机器的方式进行水平扩展比添加更强大的服务器来垂直扩展更便宜,更具有可行性(水平拆分)。
目的:提高管理能力、性能、可用性、应用负载均衡能力。
数据拆分方法
将应用数据拆分成多个更小的DBs。
1.水平拆分
方式:将不同的行拆分到多张表。基于范围拆分(Range based sharding)
举例:存储地址的表,邮政编码小于10000存一张表,大于10000存另一张表. HBase 表中 Region 的分区就是用这种方法
问题:如果拆分数据范围选择不当,会导致服务器不均衡。数据和编码不一定是均匀分布的
2.垂直拆分
方式:数据根据功能相关性划分,存储到对应服务器
举例:社交类应用,需要存储用户相关数据、上传的照片、关注列表,分别将这些数据放在不同的服务器上。
好处:易于实现,对应用程序的影响小。
问题:如果应用继续增长,可能需要在不同服务器上进一步对特定功能数据库进行拆分。(单台服务器不太可能处理所有元数据查询——1.4亿用户的100亿图片)
3.基于目录拆分
解决上面问题的一种松耦合方法是创建一个查找服务。该服务知道当前的分区方案并将其从数据库访问代码中抽象出来。查询文件服务器,获取特定数据实体所在位置。该服务记录每个元组键到数据库服务的映射。
好处:松耦合,可以添加服务器到DB池,或更改分区方案,对应用程序影响小
拆分标准
1.基于key或hash拆分
方式:根据存储实体的某些属性生成hash值,并生成对应的分区号。(用户根据id存入100个DB,hash函数 ID % 100.即生成读取和写入的服务器号)。 Kafka Topic 计算分区就是用这种分区算法,理论上会将数据均匀分散到不同分区中
问题:需要确保在所有服务器间统一分配数据。该方法固定了数据库服务器总数。新增一个数据库服务就会改变原有的hash函数值(分母变了)。需要重新分配数据,并导致DB服务器停机。
办法:使用Consistent Hashing。即打散服务器,来使数据均匀。避免重新分配数据。
2.列表拆分(范围拆分)
方式:为分区分配一个值列表。如果分区键具有这些值中的一个,则选择分区.(如:将所有生活在河北、山东、内蒙的用户存储在华北的分区中)
3.Round-robin 拆分
i mod n. i是第i个记录,n个分区(比如有3个分区,第一条数据放到第一个分区;第二条放到第二个分区;第三条数据放到第三个分区;第四条放到第一个分区)
4.组合拆分
任意组合上述拆分方法。先应用列表(范围)拆分,然后应用hash拆分。一致性hash可以被认为是hash和list拆分的组合。hash减少了key空间,从而可以被list拆分。即放入列表值中。
拆分常见的问题
拆分后的数据库,对于不同操作会有一些额外的约束。因为需要跨多张表或同一个表的多行操作。执行不在同一台服务器上,拆分引入了限制和额外的复杂性:
-
join和非规范化 在一台数据库上执行join很简单,数据库被拆分到多台机器上,跨数据库拆分的join通常不可行。因为要从多台服务器编译数据,因此这类join通常并不高效。
办法:对数据库进行非规范化,从而可以从单个表执行之前需要join的查询。非规范化可能带来风险,比如数据不一致 -
引用的完整性 问题:在拆分的数据库上执行跨分配查询通常是不可行的。同样,在分片的数据库上要求数据完整性也是非常困难的。
大多数RDBMS不支持不同数据库server之间的跨数据库的外键约束。应用对数据完整性的条件要求,必须在代码中强制执行。通常,由应用程序执行常规的sql任务来清理空引用 -
rebalancing 再平衡 有很多原因会需要拆分方案
1)数据分布不一致
- 分片负载过高(处理用户图片的数据库请求过多)
创建更多的DB分片或者重新平衡,都会改变已存在的分片,拆分方案也会改变,已经存在的数据会移动到新的位置。不停机做这些是比较困难的,使用基于目录的拆分方案让再平衡体验会更好,虽然带来了系统(查找服务或数据库)复杂性的增加和单点故障的可能。