6. 分区
我们必须跳出电脑指令序列的窠臼。 叙述定义、描述元数据、梳理关系,而不是编写过程。
—— Grace Murray Hopper,未来的计算机及其管理(1962)
在第5章中,我们讨论了复制——即数据在不同节点上的副本,对于非常大的数据集,或非常高的吞吐量,仅仅进行复制是不够的:我们需要将数据进行分区(partitions),也称为分片(sharding)[^i]
[^i]: 正如本章所讨论的,分区是一种有意将大型数据库分解成小型数据库的方式。它与网络分区(net splits)无关,这是节点之间网络中的一种故障类型。我们将在第8章讨论这些错误。
术语澄清
上文中的分区(partition),在MongoDB,Elasticsearch和Solr Cloud中被称为分片(shard),在HBase中称之为区域(Region),Bigtable中则是 表块(tablet),Cassandra和Riak中是虚节点(vnode), Couchbase中叫做虚桶(vBucket).但是分区(partition) 是约定俗成的叫法。
通常情况下,每条数据(每条记录,每行或每个文档)属于且仅属于一个分区。有很多方法可以实现这一点,本章将进行深入讨论。实际上,每个分区都是自己的小型数据库,尽管数据库可能支持同时进行多个分区的操作。
分区主要是为了可扩展性。不同的分区可以放在不共享集群中的不同节点上(参阅第二部分关于无共享架构的定义)。因此,大数据集可以分布在多个磁盘上,并且查询负载可以分布在多个处理器上。
对于在单个分区上运行的查询,每个节点可以独立执行对自己的查询,因此可以通过添加更多的节点来扩大查询吞吐量。大型,复杂的查询可能会跨越多个节点并行处理,尽管这也带来了新的困难。
分区数据库在20世纪80年代由Teradata和NonStop SQL【1】等产品率先推出,最近因为NoSQL数据库和基于Hadoop的数据仓库重新被关注。有些系统是为事务性工作设计的,有些系统则用于分析(参阅“[事务处理或分析]”):这种差异会影响系统的运作方式,但是分区的基本原理均适用于这两种工作方式。
在本章中,我们将首先介绍分割大型数据集的不同方法,并观察索引如何与分区配合。然后我们将讨论重新平衡分区,如果想要添加或删除群集中的节点,则必须进行再平衡。最后,我们将概述数据库如何将请求路由到正确的分区并执行查询。