【分布式理论】之 分区(1)


一、简介


面对一些海量数据集或非常高的查询压力,复制技术还不够,还需要将数据拆分成为分区,也称为分片

分区,在不同系统有着不同的称呼。
MongoDBElasticsearchSolrCloudshard
HBaseregionBigtabletabletCassandraRiaknode
CouchbasevBucket

分区通常是这样定义的,即每一条数据(或者每条记录,每行或每个文档)只属于某个特定分区。

每个分区可以视为一个完成的小型数据库。(即:每个分区基本保持独立运行)

采用数据分区的主要目的是:提高可扩展性



(1)问题


1)为什么要分区?

  1. 分区的主要目标是将数据和查询负载均匀分布在所有节点上

如果节点平均分担负载,那么理论上10个节点应该能够处理10倍的数据量和10倍于单个节点的读写吞吐量(忽略复制)


2)为什么要将分区数据库分布、扩展到多台机器上?

每个分区基本保持独立运行。



二、分区方法


如果分区不均匀,则会出现某些分区节点比其他分区承担更多的数据量或查询负载,称之为倾斜

如图:
在这里插入图片描述

避免热点,最简单的方法是将记录随机分配给所有节点上。

缺点:当试图读取特定的数据时,没有办法知道数据保存在哪个节点上,所有不得不并行查询所有节点。


(1)基于关键字区间的分区

按照一段连续的关键字或者关键字区间范围(以最小值和最大值)来分区。

分区边界可以由管理员手动确定,或者由数据库自动选择


1)缺点

缺点:某些访问模式会导致热点。

例如:分区对应一个时间范围,每天一个分区(即以时间戳为关键字)

这会导致该分区在写入时负载过高,而其他分区始终处于空闲状态

解决方案:

  1. 重选关键字

根据业务划分,需要使用时间戳以外的其他内容作为关键字的第一项。

  1. 换分区方法

(2)哈希分区

一个好的哈希函数可以处理数据倾斜并使其均匀分布。

例如,CassandraMongoDB使用MD5Voldemort使用Fowler-Noll-Vo函数

如图:
在这里插入图片描述

基于哈希的分区方法可以减轻热点,但无法做到完全避免。

一个极端情况是,所有的读/写操作都是针对同一个关键字,则最终所有请求都将被路由到同一个分区。

一些名人用户有数百万的粉丝,当其发布一些热点事件时,出现大量的对相同关键字的写操作(其中关键字可能是名人的用户ID,或者人们正在评论的事件ID)

如果某个关键字被确认为热点,一个简单的方案:在关键字的开头或结尾处添加一个随机数。

只需一个两位数的十进制随机数就可以将关键字的写操作分布到 100个 不同的关键字上,从而分配到不同的分区。
读复杂度:之后的任何读取都需要些额外的工作,必须从所有100个关键字中读取数据然后进行合并。

1)缺点

缺点:无法良好的区间查询

Tips:相关技术需要看下版本。

MongoDB中,如果开启了基于哈希的分片模式,则区间查询会发送到所有的分区上。
RiakCouchbaseVoldemort就不支持关键字上的区间查询。


(3)复合键

即:键的一部分来标识分区,而另一部分来记录排序后的顺序

Cassandra则在两种分区策略之间做了一个折中。

Cassandra中的表可以声明为由多个列组成的复合主键
复合主键只有第一部分可用于哈希分区,而其他列则用作组合索引来对Cassandra SSTable中的数据进行排序。
因此,它不支持在第一列上进行分区查询,但如果为第一列指定好了固定值,可以对其他列执行高效的区间查询

组合索引为一对多的关系提供了一个优雅的数据模型。



三、分区与二级索引


键-值模型相对简单,即都是通过关键字来访问记录,自然可以根据关键字来确定分区,并将读写请求路由到负责该关键字的分区上。

  1. 什么是二级索引?

二级索引通常不能唯一标识一条记录,而是用来加速特定值的查找。
例如:查找所有颜色为红色的汽车。

  1. 二级索引是关系数据库的必备特性

可以理解为,二级索引相当于关系型数据非主键索引
参见 MySQL Innodb。

  1. 二级索引在文档数据库中应用也非常普遍

二级索引也是SolrElasticsearch等全文索引服务器存在之根本

  1. 二级索引带来的主要挑战是它们不能规整的地映射到分区中

有两种主要的方法来支持对二级索引进行分区:基于文档的分区 和 基于词条的分区


(1)基于文档分区的二级索引

场景:
一个数据库用ID进行分区,例如: ID 0~499归分区0, 500~999划为分区1
键(ID,color,make)对应(主键,颜色,厂商)
现在分别针对 color 和 make 建立索引

如图:
在这里插入图片描述

在这种索引方法中,每个分区完全独立,各自维护自己的二级索引,且只负责自己分区内的文档而不关心其他分区中的数据。

因此文档分区索引也被称为 本地索引,而不是 全局索引


1)缺点

这种查询分区数据的方法有时也称为 分散/聚集,查询代价较高。

即使采用了并行查询,也容易导致读延迟显著放大


(2)基于词条的二级索引分区

对所有的数据构建 全局索引,而不是每个分区维护自己的本地索引。

为避免成为瓶颈,不能将全局索引存储在一个节点上,否则就破坏了设计分区均衡的目标。

全局索引也必须进行分区,且可以与数据关键字采用不同的分区策略

这种索引方案称为 词条分区,它以待查找的关键字本身作为索引。

即,索引的value 包含所有的关键字

如图:
在这里插入图片描述

同样,索引分区可以是 直接分区 和 哈希分区:

  • 直接分区:可以支持高效的区间查询
  • 哈希分区:可以更均匀的划分分区

1)缺点

写入速度较慢且非常负责。

主要因为单个文档的更新时,里面可能会涉及多个二级索引,而二级索引的分区又可能完全不同甚至在不同的节点上。

对于词条分区来讲,这需要一个跨多个相关分区的分布式事务支持,写入速度会受到极大的影响。

实践中,对全局二级索引的更新往往都是异步的。

同时,当底层设施出现故障时,也有可能需要等待很长的时间。

发布了404 篇原创文章 · 获赞 270 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/fanfan4569/article/details/102505794