聊聊partition的方式

本文主要聊一下開源主流產品的partition方式。html

partition

通常來講,數據庫的繁忙體如今:不一樣用戶須要訪問數據集中的不一樣部分,這種狀況下,咱們把數據的各個部分存放在不一樣的服務器/節點中,每一個服務器/節點負責自身數據的讀取與寫入操做,以此實現橫向擴展,這種技術成爲分片,即sharding。node

理想狀況下,不一樣的節點服務於不一樣的用戶,每一個用戶只須要與一個節點通訊,而且很快就能得到服務器的響應。固然理想狀況比較罕見,爲了得到近乎理想的效果,必須保證須要同時訪問的那些數據都存放在同一個節點上,並且節點必須排布好這些數據塊,使得訪問速度最優。git

分片能夠極大地提升讀取性能,但對於要頻繁寫的應用,幫助不大。另外,分片對改善故障恢復能力並無幫助,可是它減小了故障範圍,只有訪問這個節點的那些用戶纔會受影響,其他用戶能夠正常訪問。雖然數據缺失了一部分,可是仍是其他部分仍是能夠正常運轉。github

問題點

1.怎樣分片/路由

怎樣存放數據,才能保證用戶基本上只須要從一個節點獲取它。若是使用的是面向聚合的數據庫而非面向元組的數據庫,那麼就很是容易解決了。之因此設計聚合這一結構,就是爲了把那些常常須要同時訪問的數據存放在一塊兒。所以,能夠把聚合做爲分佈數據的單元。redis

另外還要考慮的是:如何保持負載均衡。即如何把聚合數據均勻地分佈在各個節點中,讓它們須要處理的負載量相等。負載分佈狀況可能隨着時間變化,所以須要一些領域特定的規則。好比有的須要按字典順序,有的須要按逆域名序列等。
不少NoSQL都提供自動分片(auto-sharding)功能,可讓數據庫本身負責把數據分佈到各個分片,而且將數據訪問請求引導到適當的分片上。算法

2.怎樣rebalance

在動態增減機器或partition的狀況下,若是從新rebalance,使數據分佈均勻或者避免熱點訪問mongodb

分片方式

這裏主要分爲兩大類,一類是哈希分片(hash based partitionning),一類是範圍分片(range based partitioning)數據庫

1.哈希分片(hash based partitionning)

經過哈希函數來進行數據分片,主要有Round Robbin、虛擬桶、一致性哈希三種算法。segmentfault

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。

一、提高單調性(經過環形算法減小增減節點時cache的遷移成本) 二、提高平衡性(經過虛擬節點,儘量減小節點增減帶來的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

相關文章
相關標籤/搜索