1. 程式人生 > >雲端計算設計模式(二十一)——Sharding分片模式

雲端計算設計模式(二十一)——Sharding分片模式

雲端計算設計模式(二十一)——Sharding分片模式


將一個資料儲存到一組水平分割槽或碎片儲存和訪問大量資料時,這個模式可以提高可擴充套件性。

背景和問題


由一個單一的伺服器託管的資料儲存區可能會受到以下限制:
•儲存空間。一種資料儲存一個大型雲應用可以預期含有資料量巨大,可以隨著時間的推移顯著增加伺服器通常提供的磁碟儲存是有限的,但它可以是較大的取代現有的磁碟,或者新增另外的磁碟的機器作為資料量的增加然而,由此,能夠容易地增加一個給定的伺服器上的儲存容量系統最終將達到一個硬限制。
計算資源。雲應用程式可能需要支援大量併發使用者每一個執行檢索資料儲存資訊的查詢一個單一的伺服器託管

資料儲存可能無法提供所需的計算能力,以支援該負載從而延長反應時間,為使用者和故障頻作為應用程式試圖儲存和檢索資料超時。它可能會增加儲存器或升級的處理器,但是當其不能夠提高計算資源的任何進一步系統將達到極限
•網路頻寬。最後,在單個伺服器上執行的資料儲存區的效能是通過在該伺服器可以接收請求並傳送回覆的約束。這是可能的網路流量可能會超過用於連線到該伺服器,從而導致失敗的請求網路的容量。
地理。可能需要為儲存由特定的使用者在同一個區域中產生的那些使用者合法,合規性效能原因,資料減少資料訪問延滯如果使用者在不同的國家或地區的分散也未必能夠儲存整個資料在一個單一的資料儲存區中的
應用

垂直縮放通過新增更多的磁碟容量處理能力,記憶體和網路連線可能會推遲一些這些限制效果但它很可能是只是一個臨時的解決方案能夠支援大量使用者大量資料商業雲應用程式必須能夠擴充套件幾乎無限所以垂直縮放不一定是最好的解決方案

解決方案


劃分資料儲存水平分割槽或碎片每個碎片都有相同的模式儲存的資料其獨特的子集。碎片在自己的權利可以包含許多不同型別的實體資料的資料儲存器用作儲存節點的伺服器上執行

這種模式具有以下優點
您可擴充套件系統,通過新增額外的儲存節點上執行的進一步碎片
•系統可以使用現成的商品硬體,而不是專門的昂貴)的計算機為每個儲存節點。
•您可以通過平衡

跨越碎片的工作量減少爭用和改進的效能
在雲中,碎片可以位於物理上接近將要訪問資料使用者。

何時將一個資料儲存碎片決定哪些資料應該被放置在每個碎片。碎片通常包含倒在資料中的一個或多個屬性所確定的指定範圍內的物品。這些屬性形成分片金鑰(有時也被稱為分割槽鍵分片的關鍵應該是靜態的不應該根據可能發生變化的資料。

分片身體組織的資料。何時一個應用程式儲存檢索資料分片的邏輯指示應用到相應的碎片。拆分邏輯可在應用程式中被實現為資料訪問程式碼的一部分,或者它可以由資料儲存系統中實現,如果它透明地支援分片

抽象拆分邏輯資料的物理位置提供了一個高層次的控制在其上的碎片包含的資料並且使資料分片之間遷移,而再加工的應用程式的業務邏輯應該需要碎片資料後面將要引入的(例如,如果碎片變得不平衡的折衷在確定的每個資料項位置,因為它被檢索所需的附加資料存取的開銷。

為了確保最佳的效能可擴充套件性,分裂資料的方式,適合的查詢型別應用程式執行是重要的。在許多情況下這是不可能拆分計劃將完全符合每個查詢的要求。例如一個多使用者系統中的應用,可能需要通過使用承租者ID來檢索租戶資料,但它也可能需要基於其它屬性這個資料查詢,如承租人的名稱或位置為了處理這些情況實行分片策略,支援最常用的查詢執行的一個子庫的關鍵

如果查詢通過使用屬性值的組合來定期檢索資料,這可能是可以定義通過將屬性一起的複合分片鍵。另外使用模式,如索引表,以提供快速的查詢到未覆蓋的碎片關鍵基礎屬性資料


分片策略


選擇所述分片金鑰,並決定如何跨碎片分發資料的三種策略是常用的注意,並不需要成為碎片承載它們 - 在單個伺服器可以承載多個分塊中的伺服器之間的一對一的對應關係。這些戰略包括:
查詢策略上述策略中,分片的邏輯實現了一個圖,路由對資料的請求到包含碎片,通過使用分片金鑰資料一個多使用者應用將租戶的所有資料可能通過使用租戶ID作為分片金鑰一起儲存在一個碎片。多個租戶可能共享相同的碎片對於單個租戶資料將不被跨越多個碎片散佈圖1示出了這種策略的一個例子。

圖1 - 基於租戶ID的分片租戶資料


分片物理儲存的對映關係可以基於物理分塊,每個分片鍵對映到一個物理分割槽。可替換地,這種技術提供了重新平衡碎片更大的靈活性是使用虛擬分割槽方法,其中分片對映到虛擬碎片數量相同,這又對映到較少的物理分割槽。這種方法中,一個應用程式通過使用指的是一個虛擬碎片一個碎片定位資料在系統的虛擬分片透明地對映到物理分割槽。進行修改,以使用一組不同的碎片的鍵的虛擬碎片物理分割槽可以改變,而不需要對應用程式程式碼之間的對映。

範圍的策略在同一個分片相關的專案一起策略並把它們的訂單通過分片金鑰分片鍵是連續的。是用於應用程式通過使用範圍查詢(即返回一組資料項的落在給定範圍內的碎片查詢)經常檢索項集有用的。例如,如果應用程式經常需要找到放置在給定月份所有的訂單,該資料可被檢索更快如果一個月的所有命令被儲存在日期和時間的順序在同一個分片如果每個訂單儲存在不同的碎片它們將必須通過進行大量的點查詢返回單個資料的查詢)單獨取出。圖2示出了這種策略的一個例子。

圖2  - 資料的碎片儲存順序集合範圍)


這個例子中,分片一個組合鍵,包括訂單作為最顯著元件,其次是為了日和時間建立和附加到一個碎片新訂單時,訂單中的資料自然排序。一些資料儲存支援包括識別所述碎片行金鑰唯一地標識該子庫中的項分割槽鍵元件的兩部分分片金鑰。資料通常是在碎片鍵順序舉行。的範圍內的查詢和需要的專案組合在一起可以使用一個分片具有用於分割槽鍵該行的唯一值相同的值。

雜湊策略這種策略目的是減少在資料熱點的機會。它的目的是分配實現每個碎片的大小平均負載,每個碎片會遇到之間的平衡的方式在整個碎片中的資料。分片的邏輯計算,其中基於所述資料一個或多個屬性的雜湊來儲存中的專案子庫所選擇的雜湊函式應該均勻地分佈在整個資料碎片,可能通過引入一些隨機元素插入的計算。圖2示出了這種策略的一個例子。

圖3 - 基於租戶ID的雜湊分片租戶資料


•瞭解超過其他分片策略雜湊策略優勢考慮如何依序錄取新租戶多租戶應用程式可能分配租戶碎片中的資料儲存當使用範圍的策略,租戶1到n資料都將儲存在分片A中,資料住戶的n +1到m都將儲存在分片B,依此類推。如果最近登記的租戶也是最活躍資料活動將發生在少數碎片這可能會導致熱點與此相反,雜湊策略分配租戶基於對其租戶ID的雜湊碎片意味著順序租戶是最有可能被分配不同的碎片圖3所示住戶5556,這將在這些碎片分配負載。

下表列出的主要優點和考慮這三個分片策略。

Strategy策略

Advantages優點

Considerations考慮

Lookup 查詢

More control over the way that shards are configured and used.

Using virtual shards reduces the impact when rebalancing data because new physical partitions can be added to even out the workload. The mapping between a virtual shard and the physical partitions that implement the shard can be modified without affecting application code that uses a shard key to store and retrieve data. 

更好地控制碎片的配置和使用方式。

重新平衡資料,因為的物理分割槽可以被新增到拉平工作量使用虛擬碎片減少的影響。可以在不影響使用一個分片來儲存和檢索資料的應用程式程式碼被修改的虛擬碎片實現該分片的物理分割槽之間的對映。

Looking up shard locations can impose an additional overhead.

查詢碎片位置可以徵收額外的開銷

Range 範圍              

Easy to implement and works well with range queries because they can often fetch multiple data items from a single shard in a single operation.

Easier data management. For example, if users in the same region are in the same shard, updates can be scheduled in each time zone based on the local load and demand pattern.

易於實現使用範圍查詢工作得很好,因為它們通常可以在單個操作中從單個分片的多個資料項。

更簡便的資料管理例如,如果使用者在相同的區域在相同的子庫,更新可以安排基於本地負載需求模式的每個時區。

May not provide optimal balancing between shards.

Rebalancing shards is difficult and may not resolve the problem of uneven load if the majority of activity is for adjacent shard keys.

可能不提供碎片之間的最佳平衡

重新平衡碎片是困難的,可能不解決不均勻的負載問題,如果大多數的活性相鄰的分片金鑰。

Hash 雜湊              

Better chance of a more even data and load distribution.

Request routing can be accomplished directly by using the hash function. There is no need to maintain a map.

一個甚至更多的資料和負荷分佈更好的機會

請求路由可以直接通過使用雜湊函式來實現。沒有必要來維護一個地圖

Computing the hash may impose an additional overhead.

Rebalancing shards is difficult.

計算雜湊可能會收取額外的開銷

重新平衡碎片是困難的。

最常見的拆分方案實現上述方法之一但你也應該考慮你的應用程式業務需求和他們的資料使用模式例如一個多使用者應用
•可以分片根據工作負載資料你可以分開不同的碎片極易揮發租戶的資料。對於其他租戶的資料訪問速度可以提高作為結果。
•可以分片根據租戶的位置資料它可能會採取租戶資料在一個特定的地理區域離線期間在該地區非高峰期備份和維護而對於住戶在其他地區資料仍然在他們上班時間上網訪問。
高價值的住戶能分到自己的私人高效能,輕載碎片價值較低的住戶可能有望分享更密集堆積,忙碎片
對於需要資料隔離和隱私高度可以儲存一個完全獨立的伺服器上租戶的資料

縮放和資料移動操作


每個分片策略意味著不同的功能和複雜性管理規模向外擴充套件資料移動並保持水平狀態

查詢策略允許縮放和資料移動操作進行,在使用者層面無論是線上還是離線該技術暫停部分或全部使用者活動也許是在非高峰時段移動資料到新的虛擬分割槽或物理碎片改變對映無效或重新整理持有資料的快取,然後讓使用者活動恢復通常這種型別的操作可以進行集中管理。查詢戰略要求的狀態是高度可快取和副本友好。

範圍的策略規定了結垢和資料移動操作,這通常必須進行的一部分或全部資料儲存為離線,因為資料必須被分割和整個碎片合併的一些限制。移動資料,以重新平衡碎片可能無法解決不均勻負荷問題,如果大多數的活性相鄰分片金鑰或資料識別符號是相同的範圍之內的範圍的策略可能也需要進行維護,以圖範圍內物理分割槽的一些狀態。

雜湊策略使得擴充套件和資料移動操作更為複雜,因為分割槽鍵是碎片金鑰或資料識別符號雜湊值每個碎片的新位置,必須從雜湊函式來確定或者該函式修改,以提供正確的對映。然而,雜湊策略不需要維護狀態

問題和注意事項


在決定如何實現這個模式時,請考慮以下幾點
分片互補的其他形式的分割槽,如垂直分割槽功能劃分例如,單個子庫可以包含垂直劃分實體功能劃分可以被實現為多個碎片有關分割槽的詳細資訊,請參閱資料分割槽指導
•保持平衡碎片,使他們都處理I / O相似的體積作為資料被插入刪除,它可能有必要定期地重新平衡碎片,以保證均勻分佈,並減少熱點的機會。再平衡可能是一個昂貴的操作為了降低頻率再平衡成為必要,你應該確保每個碎片中含有足夠的可用空間來處理變化的預期貨量計劃增長。你還應該制定戰略和指令碼,你可以用它來快速重新平衡碎片應該成為必要
•使用穩定的資料分片的關鍵如果分片的變化,相應的資料可能需要碎片之間移動,增加工作通過更新操作執行的工作量出於這個原因避免立足於潛在的波動資訊碎片關鍵相反,尋找那些不變的自然形成的關鍵屬性。
•確保碎片鑰匙都是獨一無二的例如,應避免使用自動遞增的欄位作為分片的關鍵一些系統中,自動遞增欄位可以不橫跨碎片協調,從而可能導致在具有相同分片不同的碎片的專案。

注意:

在不包括分片也可能導致問題欄位自動遞增值。例如,如果您使用自增欄位來生成唯一標識,並分佈在不同的碎片兩個不同的專案可能被分配相同的ID


•它可能無法設計出符合針對資料的每個可能的查詢要求一個分片鍵。分片資料,以支援最經常進行的查詢並在必要時建立二級索引表,以支援通過使用基於不屬於分片鍵的一部分的屬性標準檢索資料的查詢。欲瞭解更多資訊,請參見索引表模式
•查詢訪問僅單個碎片會比那些來自多個分塊中檢索資料的效率,從而避免執行一個分片方案,該方案導致在執行該連線不同碎片保持的資料的查詢的大量應用程式。請記住,碎瓷片可以包含的資料為多個型別的實體考慮非規範化的資料保持相同的碎片常常被認為是一起查詢如客戶詳細資訊和訂單,他們已經把相關實體,以減少單獨讀取數的應用程式執行

注意:

如果在一個子庫的實體引用儲存在另一個分片的一個實體包括分片用於第二實體,作為第一實體的架構的一部分。這可以幫助提高引用碎片相關資料查詢的效能


如果應用程式必須執行檢索來自多個分塊資料的查詢有可能通過使用並行任務來獲取這些資料。例子包括扇出查詢,其中來自多個分片的資料檢索平行,然後彙總到一個結果然而,這種方法不可避免地增加了一些複雜性的溶液的資料訪問邏輯
對於許多應用來說,產生碎片更大數目可以比具有少量碎片,因為它們可以提供用於負載平衡的機會增加更加有效。如果預計需要碎片從一個物理位置移動到另一個這樣的方法可以是有用的移動碎片比移動一個大的更快
•確保提供給每個分片儲存節點資源足以處理資料的規模和吞吐量方面可擴充套件性要求欲瞭解更多資訊,請參閱資料分割槽引導部分“設計分割槽可擴充套件性
•考慮複製參考資料所有碎片如果一個子庫中檢索資料的操作還引用靜態或緩慢移動的資料作為同一查詢的一部分這個資料新增到碎片。然後,應用程式可以讀取所有用於容易地查詢中的資料,而無需進行額外的往返行程一個單獨的資料儲存中。

注意:

如果在多個分塊的變化保持的基準資料,該系統必須同步所有碎片這些變化。此同步發生時,系統可能會出現一定程度的混亂。如果你按照這種方法,你應該設計自己的應用程式能夠處理這個矛盾


它可以是難以維持的碎片之間的參照完整性和一致性所以你應該儘量減少影響在多個碎片資料操作如果應用程式必須通過碎片修改資料評估完整的資料一致性是否實際上是一個要求。相反,在雲中一個常用的方法是實現最終一致性每個分割槽中的資料分別進行更新在應用程式邏輯必須承擔保證責任的更新成功完成以及處理,可以從查詢資料最終一致的執行操作時產生的不一致有關實現最終一致性的更多資訊,請參閱資料一致性底漆
配置和管理大量碎片可能是一個挑戰任務,例如監控,備份,檢查一致性記錄或審計必須完成對多個碎片伺服器,在多個位置有可能保持。這些任務可能會通過使用指令碼或其他自動化解決方案指令碼和自動化可能無法完全消除額外的行政要求執行。
碎片可以是地理定位的,使得它們包含的資料靠近使用的應用程式的例項。這種方法可以顯著改善的效能,但是需要額外考慮為必須訪問多個分塊的不同位置的任務。

何時使用這個模式


使用這種模式
•當資料儲存可能需要擴充套件超越了一單個儲存節點資源限制。
通過減少爭用的資料儲存來提高效能。

注意:

分片的主要焦點是改進系統的效能可擴充套件性,作為副產物,也可以藉助於其中資料被劃分成單獨的分割槽的方式提高可用性。在一個分割槽中的故障不一定阻止應用程式訪問其他分割槽中儲存的資料並且操作者無需使得整個資料為應用程式無法訪問的可以執行一個或多個分割槽的維護復原欲瞭解更多資訊,請參閱資料分割槽指導

例子


下面的示例使用了一組充當碎片的SQL Server資料庫每個資料庫包含一個應用程式使用資料的一個子集應用程式檢索分佈在整個碎片通過使用它自己的分片邏輯一個扇出查詢的一個例子)的資料。將位於每個子庫中的資料的細節通過這樣的方法稱為GetShards返回。此方法返回ShardInformation物件,其中ShardInformation型別包含一個識別符號為每個碎片和SQL Server的連線字串,應用程式應該使用連線到碎片列舉列表連線字串中沒有程式碼示例所示

private IEnumerable<ShardInformation> GetShards()
{
  // This retrieves the connection information from a shard store 
  // (commonly a root database).
  return new[]
  {
    new ShardInformation
    {
      Id = 1,
      ConnectionString = ...
    },
    new ShardInformation
    {
      Id = 2,
      ConnectionString = ...
    }
  };
}

下面的程式碼顯示瞭如何應用程式使用ShardInformation物件名單進行並行每個碎片獲取資料的查詢。查詢的細節沒有示出,本實施例中所檢索的資料包括可以存放資訊,如客戶的名稱,如果碎片包含客戶的細節的字串。結果由應用聚整合ConcurrentBag集合進行處理。

// Retrieve the shards as a ShardInformation[] instance. 
var shards = GetShards();

var results = new ConcurrentBag<string>();

// Execute the query against each shard in the shard list.
// This list would typically be retrieved from configuration 
// or from a root/master shard store.
Parallel.ForEach(shards, shard =>
{
  // NOTE: Transient fault handling is not included, 
  // but should be incorporated when used in a real world application.
  using (var con = new SqlConnection(shard.ConnectionString))
  {
    con.Open();
    var cmd = new SqlCommand("SELECT ... FROM ...", con);

    Trace.TraceInformation("Executing command against shard: {0}", shard.Id);
                    
    var reader = cmd.ExecuteReader();
    // Read the results in to a thread-safe data structure.
    while (reader.Read())
    {
      results.Add(reader.GetString(0));
    }
  }
});

Trace.TraceInformation("Fanout query complete - Record Count: {0}", 
                        results.Count);
本文翻譯自MSDN:http://msdn.microsoft.com/en-us/library/dn589797.aspx