聊聊partition的方式

本文主要聊一下开源主流产品的partition方式。

partition

一般来说,数据库的繁忙体现在:不同用户需要访问数据集中的不同部分,这种情况下,我们把数据的各个部分存放在不同的服务器/节点中,每个服务器/节点负责自身数据的读取与写入操作,以此实现横向扩展,这种技术成为分片,即sharding。

理想情况下,不同的节点服务于不同的用户,每个用户只需要与一个节点通信,并且很快就能获得服务器的响应。当然理想情况比较罕见,为了获得近乎理想的效果,必须保证需要同时访问的那些数据都存放在同一个节点上,而且节点必须排布好这些数据块,使得访问速度最优。

分片可以极大地提高读取性能,但对于要频繁写的应用,帮助不大。另外,分片对改善故障恢复能力并没有帮助,但是它减少了故障范围,只有访问这个节点的那些用户才会受影响,其余用户可以正常访问。虽然数据缺失了一部分,但是还是其余部分还是可以正常运转。

问题点

1.怎样分片/路由

怎样存放数据,才能保证用户基本上只需要从一个节点获取它。如果使用的是面向聚合的数据库而非面向元组的数据库,那么就非常容易解决了。之所以设计聚合这一结构,就是为了把那些经常需要同时访问的数据存放在一起。因此,可以把聚合作为分布数据的单元。

另外还要考虑的是:如何保持负载均衡。即如何把聚合数据均匀地分布在各个节点中,让它们需要处理的负载量相等。负载分布情况可能随着时间变化,因此需要一些领域特定的规则。比如有的需要按字典顺序,有的需要按逆域名序列等。
很多NoSQL都提供自动分片(auto-sharding)功能,可以让数据库自己负责把数据分布到各个分片,并且将数据访问请求引导到适当的分片上。

2.怎样rebalance

在动态增减机器或partition的情况下,如果重新rebalance,使数据分布均匀或者避免热点访问

分片方式

这里主要分为两大类,一类是哈希分片(hash based partitionning),一类是范围分片(range based partitioning)

1.哈希分片(hash based partitionning)

通过哈希函数来进行数据分片,主要有Round Robbin、虚拟桶、一致性哈希三种算法。

A、Round Robbin
俗称哈希取模算法,H(key) = hash(key) mode K(其中对物理机进行从0到K-1编号,key为某个记录的主键,H(key)为存储该数据的物理机编号)。好处是简单,缺点是增减机器要重新hash,缺乏灵活性。它实际上是将物理机和数据分片两个功能点合二为一了,因而缺乏灵活性。
B、虚拟桶
membase在待存储记录和物理机之间引入了虚拟桶,形成两级映射。其中key-partition映射采用哈希函数,partition-machine采用表格管理实现。新加入机器时,只需要将原来一些虚拟桶划分给新的机器,只要修改partition-machine映射即可,具有灵活性。
C、一致性哈希
一致性哈希是分布式哈希表的一种实现算法,将哈希数值空间按照大小组成一个首尾相接的环状序列,对于每台机器,可以根据IP和端口号经过哈希函数映射到哈希数值空间内。通过有向环顺序查找或路由表(Finger Table)来查找。对于一致性哈希可能造成的各个节点负载不均衡的情况,可以采用虚拟节点的方式来解决。一个物理机节点虚拟成若干虚拟节点,映射到环状结构的不同位置。

哈希分片的好处是可以使数据均匀分布,但是可能造成数据无序不方面range

mongo2.4版本+支持hash partition

2.范围分片(range based partitioning)

这个是根据key排序来分布的,比如字典按24个首字母来分,这个的好处是方便range,但是容易造成数据分布不均匀以及热点访问问题(比如个别节点的数据访问量/查询/计算量大,造成负载特别高)。

Bigtable,hbase、2.4版本之前的mongo都使用此方式。

索引分片策略(secondary indexes)

除了数据本身要分片外,索引也需要分片。比较著名的两个反向索引分片策略就是document-based partitioning以及term-based partitioning。然后再此两个基本的策略之上衍生出了hybrid的方案。

1.local index(document-based partitioning)

也称作document-based partitioning.在每个partition本地维护一份关于本地数据的反向索引。这种方式的话,主要使用的是scatter/gather模式,即每次查询需要发送请求给所有的partition,然后每个partition根据本地的索引检索返回,之后汇总得出结果。

  • 好处
    简单好维护
  • 缺点
    查询比较费劲,比如有n个partition,要查top k,则每个partition都要查top k,总共需要n*k份文档被汇总。

mongo,cassandra,es,solr采用此方案

2.global index(term-based partitioning)

也称作term-based partitioning,这种方式的话,创建的索引不是基于partition的部分数据,而是基于所有数据来索引的。只不过这些全局索引使用range-based partitioning的方式再分布到各个节点上。

  • 好处
    读取效率高,因为索引是有序的,基于range parititioning,非常快速找到索引,而且这些索引是全局的,立马就可以定位到文档的位置。
  • 缺点
    写入成本比较高,每个文档的写入都需要维护/更新全局的索引。另外一个缺点就是range-partitioning本身的带来的缺点,容易造成数据分布不均匀,造成热点,影响吞吐量。

dynamodb,riak支持此方案

rebalance

当partition所在节点坏掉,或者新增机器的时候,这个时候就涉及到partition的rebalance。原来本应该请求这个node的,现在都需要转移请求另外一个node的过程叫做rebalancing。

rebalancing的目标

  • 均分数据存储以及读写请求,避免热点
  • rebalancing期间不影响正常读写
  • 要尽量快而且尽量少的网络及IO负载来完成

rebalance策略

直接哈希(模数固定)

即key-machine的直接映射,这个的缺点就是:增减机器要重新hash,缺乏灵活性。

两级映射(partition hashing,固定partition数目)

为了提升直接哈希的灵活性,引入了两级映射,即key-partition,partition-matchine/node这样两级,通过partition来解耦key跟machine/node的关联。对于新加入机器时,只需要将原来各个node的一些partition划分给新的机器,只要修改partition-machine映射即可,具有灵活性。

  • 好处
    相对于直接哈希来讲,节点增减的时候,只需要调整partiton-matchine的映射关系,客户端无需重新路由。

  • 缺点
    固定partition的话,需要一个合理的数目,每个partition大小需要合理确定。相当于这些固定数目的partition要均分整个数据集。如果数据集不断增长的话,如果原来partition个数太少,则每个partition大小则不断增加,造成节点恢复/rebalance相对耗时。如果原来partition个数太多,而数据集后续增长不多,则可能造成有些partition的数据量过少,无法达到均分效果。

Elasticsearch采用此方案,在创建索引的时候需指定shard/partition数目以及replication的数目
Couchbase引入了vBucket的概念在这里可以理解为虚拟的paritition。


动态partition

partition的数目是动态变化的,根据设定的partition大小的阈值,来进行动态的分裂或合并。

hbase采用的就是这种方式

一致性哈希(hash ring)

一致性哈希与前两者有些不同,因为该算法把machine/node也一起进行了hash,然后与key的哈希值一起进行区间匹配,来确定key落在哪个machine/node上面。分布式缓存用到的比较多,比如redis就是用了一致性哈希。

具体如下:

  • 将环形空间总共分成2^32个区

  • 将key跟machine采用某种哈希算法转化为一个32位的二进制数,然后落到对应的区间范围内

  • 每一个key的顺时针方向最近节点,就是key所归属的存储节点。

  • 好处
    节点增减的时候,整个环形空间的映射仍然会保持一致性哈希的顺时针规则,所以有一小部分key的归属会受到影响。当节点挂掉的时候,相当于缓存未命中,下次访问的时候重新缓存。

  • 缺点
    使用一般的hash函数的话,machine的映射分布非常不均匀,可能造成热点,对于这种情况,引入虚拟节点来解决。也就是借鉴了两级映射的模式,key-vnode,vnode-machine。将一个machine映射为多个vnode,然后分散到环形结构上,这样可以使得vnode分布均匀,然后最后每个machine的存储也相对均匀。


不过引入虚拟节点也会有问题,当新增machine的时候,也就相当于新增多个vnode分散到环上,但是这样子就会造成更多的范围的key需要rebalance。

1、提升单调性(通过环形算法减少增减节点时cache的迁移成本) 2、提升平衡性(通过虚拟节点,尽可能减少节点增减带来的cache分布不均匀问题)

小结

产品 partition方式 索引分片策略
redis 一致性哈希 -
elasticsearch 固定partition两级映射 local index
mongo 2.4版本之前是范围分片,2.4+支持hash分片 local index
kafka 固定partition -

kafka的key到partition的映射高版本支持自定义策略,如果cluster增减node,对之前创建的topic不生效,需要调用reassign-partitions重新分布,避免热点

doc

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351

推荐阅读更多精彩内容