每一条数据只属于某一个特定的分区。采用数据分区的目的是提高可扩展性。不同的分区可以放在一个集群的不同节点上。一个大型数据库可以分散在更多的磁盘上,查询负载也随之分布到更多的处理器。上。
分区通常与复制结合使用。每个分区在多个节点上有副本。一个节点可能存储了多个分区的副本。一个节点可能是一个分区的主节点同时是其他分区的从节点。
二、键值数据的分区
分区的目标是把查询的负载均匀分布到所有节点上。如果不均匀,最繁忙的几个节点称为热点。把数据分配到不同的节点上时需要知道数据保存在哪个节点上,避免向所有节点发送查询。
1、基于关键字的分区
为每个分区分配一段连续的关键字区间。根据关键字所在的区间上下限可以直接向该节点发送请求。
需要调整关键字分区边界和合适地选取关键字可以避免出现热点。
2、基于关键字的哈希值分区
通过关键字的哈希函数可以更均匀地分布关键字到多个分区中。但失去了良好地区间查询特性,相邻地关键字可能分布在不同的分区中。
3、解决负载倾斜
对同一个关键字的大量读写,最终所有的请求都被路由到同一个分区。可以在应用层减轻倾斜程度。比如在关键字的后面添加两位数序号,则将关键字的写操作分配到100个不同的分区上。但合并这些数据开销大。
三、分区与二级索引
二级索引不能唯一地标识一条记录,不能规整地映射到分区中。
1、基于文档的二级索引
每个分区完全独立,各自维护自己地二级索引,不关心其他分区中的数据。当用二级索引查询数据时,需要向所有分区发送读请求,合并所有返回的结果,代价高。
2、基于词条的二级索引
对所有的数据构建全局索引。全局索引也进行分区。以二级索引中包含的词条作为关键字,向包含该词条的分区查询。缺点时写入速度慢,因为更新数据会涉及多个二级索引,存在写放大。所以所有的数据库都不支持同步更新二级索引,都是异步更新,刚刚更新的数据不会立即通过二级索引查询到。
四、分区再平衡
解决:增加cpu、磁盘、内存后,或者某些节点出现故障后,负载再平衡。再平衡过程中保持可用性。避免不必要的负载迁移。
动态再平衡策略:
1、固定数量的分区
整个集群的分区总数量不变,随着节点数量的变化,分区在不同的节点上迁移,但关键字和分区的映射关系不变,只要调整分区和节点的映射关系。
2、动态分区
根据分区中数据量的增长自动调整分区边界。当数据量增长到一个阈值时,就分裂为两个分区,并转移到其他节点来平衡负载。
3、按节点比例分区
前两种策略,分区数和节点数无关。
此策略中,每个节点有固定数量的分区。当节点数不变时,每个分区的数据量大小和数据集大小正比。当新节点加入集群时,随机选择固定数量的分区进行分裂。
五、请求路由
客户端如何知道连接哪个节点:
1、允许客户端连接任意节点,如果节点有请求的所有分区,则处理请求,否则转发给别的节点。
2、客户端请求都发送给路由层,路由层转发给对应的节点。
3、客户端感知分区和节点的分配关系,客户端可以连接到目标节点。
Zookeeper:每个节点向Zookeeper中注册自己,Zookeeper维护了分区到节点的最终映射关系。客户端向Zookeeper订阅此信息。当分区和节点发生改变时,Zookeeper主动通知路由层。