野猪书读书笔记第六章
文章目录

分区(partitioning)
把一大堆数据分成一群小数据集放在不同的节点。
好处:扩展性,一次查询的负载分散在不同的节点上:每个节点分担一些子查询。
分区和副本
分区和副本通常是一起出现的。通常来说,一个分区的数据通常有多个副本。
有一种集群架构如下图所示:

键-值数据的分区
分区的基本原则:把数据均匀地分布在不同的节点上。
数据倾斜: 某些分区的数据量或者查询量比其他分区多得多。
数据量或者查询量高得不正常的分区叫做过热点。
依据键的范围来分区
一种分区方式是:每个分区存放一堆连续范围的键,就像百科全书一样。
这种方式的重点:连续键的边界。
分区的边界可以由管理人员手动选择,也可以由数据库自动选择。
在每个分区内,所有的键可以按序存储:范围查询变得容易。缺点是:负载不均衡。
依据键的哈希值来分区
如图所示:

好处:实在是很均匀。
分区的边界可以是均匀分割的,也可以是随机决定的(这种情况就是哈希一致性)。
有一个槽点:

坏处:范围查询不好做
在 MongoDB 中,如果开启了 哈希分片模式,那么任何的范围查询将会被发送到所有的分区。
在 Cassandra 中,一种中和的方式:
每个表中声明一种有多列组合成的 Compound primary key,其中第一列用于被哈希以决定数据被放在哪个分区,其他列用于构建排序的索引。因此,不能通过第一列来做范围查询,但是当知道第一列的值之后,再在其他列上做范围查询将非常有效率。
负载倾斜和热点缓和
哈希分区也有极端情况:当读写都是对同一个 Key 时,仍然有负载倾斜的情况。
这种情况也不是那么不常见: 比如 Twitter 的名人。这些名人对应的读写量非常大。而对这些 User 的 ID 的哈希没有负载均衡的意义。
一种解决办法是: 在写的时候,在这些热点 ID 前随机加上一个数字,这可以把写操作分散到 10 个节点上。但带来的问题是:读操作变得麻烦,因为需要读 10 个节点然后把数据集合到一起。
考虑到性能和数据量,决定权在你手上。
分区和二级索引
二级索引 通常作为一种搜索某个特定值的出现的方法。二级索引是关系型数据库的基础,在 NoSQL 数据库中也很常见。但是,在 Key-Value 型的数据库中不是很受欢迎,因为带来了复杂度。
另外,二级索引是搜索引擎的存在的原因。
二级索引的问题是它们不能整齐地映射到分区。
使用二级索引对数据库进行分区有两种主要方法:基于文档的分区和基于术语的分区
基于文档的二级索引分区

这种分区方法中,每个分区只维护属于自己的文档的索引。所有的写操作只在本分区进行,所以也称作 本地索引。
但是读操作就比较麻烦,每个读操作都需要应用在每个分区 —> 先找,然后合并。
这种查询方式被称作 分散/聚集(scatter/gather)。虽然这种方式的读操作很昂贵,但大多数数据库都是采用的这种方式。
基于术语的二级索引分区

相对应的,构建一个包含所有分区数据的二级索引被称作 全局索引。但是全局索引也必须要分区存放在不同的节点上,不然就会成为瓶颈。
如图所示,字母以 a ~ r 开头的颜色被放在第 0 个分区,s ~ z 的被放在 1 分区。
这种对二级索引的分区方式称作 基于术语分区。在图中,color:red就是术语。
这种方式的好处是对与读操作而言效率变高了:只需要读一个分区就好了。
但是对写操作变复杂了,有可能只改变了一个文档的情况下会更改多个索引分区。
另外,全局索引的同步机制是异步的:文档的更新不会实时反应在索引上,数据的一致性也一样。
增加分区
出于对性能和容量的考虑,分区扩展是常有的是。
几点要求:
- 分区增加后,各方面的负载(存储,读,写)都应该均匀。
- 增加的过程中不能停服;
- 在增加分区的过程中只移动需要移动的数据。
为了以后扩展考虑,不要用 hash mod N 的方式来分区,因为当 N 增加的时候,数据的转移非常昂贵。
分区数量固定

如图所示: 定义分区数量远远大于节点数量
很骚的操作。
这种方式下,分区数量一般来说是固定的。选择好的分区数量是个技术活,你懂的,不多说.
动态分区
当一个分区里数据量过大时,这个分区自动变成了两个;相反的,当一个分区的数据量太少了,会自动合并。
这个行为和 B 树 很类似。
HBase 这种 key range-partitioned 数据库就是使用动态分区。
和 固定数量分区 类似,每个节点有多个分区,当一个分区变成两个时,其中一个会跑到另一个节点上,从而均衡负载。在 HBase 中,这是通过 HDFS 来实现的。
动态分区好处多多,不用赘述。
按比例分配节点
还有一种分区方式:每个节点的分区数量相同。
当有新节点加入集群时,随机挑选固定个数的分区做分裂,然后分给新的节点。
随机二字不简单。。。
请求路由
又被称作 服务发现。
有几种方式可以解决这个问题:

关键问题:节点或者数据有更新该怎么办
有很多分布式数据系统都依赖一个单独的协作服务,比如 ZooKeeper 来跟踪数据集群的元信息。

routing tier 可以向 ZK 订阅相关的信息,当 ZK 中相关的信息有改动时会告知它。
另外也有 gossip protocol的实现,就像上面图中的方式一样,这种方式在节点中增加了复杂度,但是不必依赖第三方的服务。
并行查询执行
大规模并行处理 MPP(massively parallel processing)关系型数据库通常会处理非常复杂的查询。MPP 查询优化器会把这种大的复杂查询分成好几个阶段和分区,然后把它们并行地放在多个节点上执行。
第六章就到这儿啦,啦啦啦啦啦啦