关于数据库分片的知识分享
一、 基本概念
1 分片的定义
数据分片(sharding),有时也称切片或切分,是指当数据规模很大的时候,根据一定的规则、定义,将一个数据库中的数据分散到多个数据库中的做法。分片是把一个数据库横向扩展到多个节点的有效方式。它的主要目的是:
利用分片突破单节点数据库的性能限制,解决数据库的扩展性问题;
利用分片可以使用廉价的硬件(或云资源)获得性能上的潜在优势。
2 分表、分库、分区、分表
对于关系数据库而言,与分片类似的概念还有分表、分库、分区。
分表是指将一张大表分割成若干个结构相同的小表,以此降低单个表的数据规模。分表后,每
个小表除了结构相同以外相互之间独立,它们所涉及的数据库对象(数据、索引、约束、触发器等)、所涉及的资源(数据文件、控制文件等)实际上彼此无关。进行数据处理时,须由应用程序负责各子表之间的协助和冲突。
分库更进一步,是将大表分割为多个数据库的小表。分表只能解决单表数据过大时的性能下降,而分库可充分利用多个数据库的资源提升性能。分库的情况比较复杂,有主-从库(多见)和多主库之分,子表间有必须一致的,也有允许一定程度异构的;小表间的协助和冲突,有应用程序负责、专用软件负责等不同形式。
与上述概念均不同,分区(partition)不用将大表进行物理拆分,只是将数据存放到不同的小块。大表仍然存在,小表只是逻辑上的概念。分区对应用程序透明,不需要对代码进行修改。
3 分片形式
根据分片规则,有两种形式的分片:
垂直分片
也称为纵向分片,是指对数据的列进行分片,用于按功能划分数据库的场合。例如,将一个销售明细表拆分到用户库、销售库、收支库的相应表里。实际情况中,采用此种分片方式的情形较少。
水平分片
也称为横向分片,是指按数据的行进行分片,即不同的记录分配到不同数据库,例如将全国用户按省市区划分。在大多数情况下都使用的是水平分片,本文若无特别说明,也指的水平分片。
二、 分片的优缺点
1 分片的优点
对于分片来说,它的优点有:
以水平扩展来提高整体性能
随着数据的增长,通过增加更多服务器,将新增数据及负载放置到新增服务器即可。
更高的可用性,更好的可管理性
当某个数据分片所在的服务器出现故障时,不会使整个系统对外停止服务;同时,在进行管理和维护时,可以一个分片接一个分片地进行。
消除单库、单表的性能瓶颈
合理使用拆分规则,保证每个分片数据规模适度,不再受单库、单表的性能瓶颈限制。判断拆分规则是否合理的主要原则包括:数据尽可能分布均匀、负载尽量均衡、扩容缩容时数据迁移尽可能少。
2 分片的缺点
数据分片会对整个系统的性能和扩展性带来好处,但也增加了开发和维护的复杂度。尽管分片有多种方式,但它们拥有共同的缺点:
分布式事务
在任何一个分布式系统,最多只能时满足数据一致性(Consistency)、可用性(Availability)
、分区容错性(Partition Tolerance)三个特性中的两个,这被称为CAP原理。
对于关系数据库,最常用到的是二阶段提交(2PC)机制,它能保证各服务器间的数据强一致性,但代价是降低了整体可用性。而如果采取类似补偿事务(TCC)的机制,整体可用性得到了提升,却最多只能实现服务器间的数据弱一致性。
跨服务器多表Join
由于数据被拆分到多个服务器节点,必然涉及到跨服务器的多表Join问题。随着参与Join表的数量、服务器的数量的增加,此问题会变得越来越复杂,导致完成操作的工作量越来越大。
目前较好的做法,一方面是巧妙设计拆分规则,尽量将参与Join的分片存放在同一服务器上,另一方面是在查询时改写SQL,先将一个任务拆分成若干个子任务分配给各服务器执行,然后再整合子任务的返回结果以得到最终结果。即使如此,在运用场景上仍然存在很多限制(如只能有两个表参与Join),运行性能也难言满意。
跨服务器分页排序
本问题的核心其实是局部数据的全局定位以及重复执行问题,这会带来额外的管理和运算负担。大致情况是:全局定位的位置越靠后,额外的负担就越重。
最乐观的情形是只是取总体的top n条记录,此时m个节点只须各自返回n条记录,参与全局定位的数据是n*m。但如果要获取总体第f条后的n条记录,则理论上m个节点都需返回f+n条记录,参与全局定位的数据量是(f+n)*m。如果再涉及其它问题(如重复数据、稳定排序等),处理过程会更加复杂,额外的负担也会越重。
其它
关系数据库的一些重要特性,如全局唯一性约束、外键约束、触发器等,在处理分片时都会受到诸多限制,甚至完全不支持。
三、 PostgreSQL分片方案Citus
1 Citus简介
PostgreSQL有几种分片方案,其中最常使用的是Citus,由早期的pg_shard发展而来。Citus不是一个独立程序,而是一个插件,可以通过Create Extension进行安装。
每个citus集有多个PostgreSQL数据库实例组成,数据库实例分为两类:
master节点,通常有一台。master节点只存储分库分表的元数据,不存储实际的数据。
worker节点,通常有多台。worker节点存储实际的分片数据(shard)。
用户只连接master节点,即用户把SQL发到master节点,然后master节点解析SQL,把SQL分解成各个子SQL发送到底层的worker节点,完成SQL的处理。
2 Citus操作示例
#配置分片策略(在Master Node上创建表之后):
SELECT master_create_distributed_table('test_table', 'id', 'hash');
#进行分片操作(将表分为3片,每个分片有2个副本):
SELECT master_create_worker_shards('test_table', 3, 2);
#查看分片:
SELECT * from pg_dist_shard;
#查看分片分布:
SELECT * from pg_dist_shard_placement order by shardid, placementid;
通过Master Node对表test_table进行插入操作时,根据先前定义的分片策略,citus会根据id的哈希值自动为插入的记录选择一个分片进行写入。
当通过Master Node对表test_table进行查询时,首先master节点解析SQL,分解为各个子SQL发送到底层的worker节点;当各个worker把数据返给master之后,master再做一次整合,最后把结果返回用户。
3 Citus的限制
可以创建索引,但不支持索引自动命名;
可以创建唯一约束,但必须在定义表时进行,一旦表中已有记录再创建则报错;
不支持insert …select…,但支持copy;
不支持distinct,但支持group by;
不支持update和delete时where条件值使用in;
执行器为real-time时不支持跨节点join,修改为task-tracker后支持,速度较慢;
Master Node会成为瓶颈。
四、 Oracle分片方案
1 Oracle Sharding组成数据库应用在哪些方面
Oracle 12.2版开始支持分片,基于表分区技术,适用于OLTP场合。
Oracle Sharding主要包括以下组成部分:
Sharded database (SDB):逻辑上SDB是一个数据库,但是物理上SDB包括多个物理独立的数据库,SDB类似一个数据库池(pool),数据库池(pool)中包括多个数据库(Shard). 目前版本最大支持1000个shard。
Shards:SDB包括多个物理独立的数据库,每一个数据库都称为shard,每个shard数据库位于不同的服务器,不共享CPU、内存、存储等资源。每个shard数据库中保存表的不同数据集, 但是每个shard中都有相同的列(columns)。Shard数据库可以是Dataguard/ADG,提供高可用性,Shard数据库(单机或者ADG)可以通过GSM deploy来自动创建,也可以将一个已经通过dbca创建好的数据库add到SDB。
Shard catalog:是一个Oracle数据库,用于集中存储管理SDB配置信息,是SDB的核心。SDB配置变化,比如添加/删除shard,Global service等等,都记录在Shard catalog。如果应用查询多个shard中的数据,那么由Shard catalog统一协调分配。推荐将Shard catalog配置为dataguard环境,这样可以提供HA高可用。如果Shard catalog无法访问,那么只会影响一些维护操作和跨shard访问,而不会影响单独的shard操作。
Shard directors:Global Data Service (GDS)实现对Sharding的集中部署和管理。GSM是GDS的核心组件。GSM作为Shard director. GSM类似于,将客户端对SDB的请求路由到对应的shard,负载均衡客户端的访问。
Global service:数据库的服务(service),用于访问SDB中的数据
管理接口:通过GDSCTL (command-line utility) 接口部署管理监控Sharding。
2 Oracle Sharding方法、对象
Oracle Sharding支持3种分片方法:
System-Managed Sharding:这种方法用户不用指定数据存放在哪个shard中。Sharding通过一致性哈希(CONSISTENT HASH)方法将数据分区(partitioning),并自动分布在不同的Shard。System-managed sharding只能有一个shardspace。
Composite Sharding:这种方法用户可创建多个shards paces,每个shards paces 中存放一定范围(range)或者列表(list)的数据。
Subpartitions with Sharding:Sharding基于表分区,因此子分区(Subpartitions)技术同样适用于Sharding。