<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 云計算設計模式(二十一)——Sharding 分片模式 將一個數據存儲到一組水平分區或碎片。存儲和訪問大量數據時,這個模式可以提高可擴展性。 ## 背景和問題 由一個單一的服務器托管的數據存儲區可能會受到以下限制: - 存儲空間。一種數據存儲為一個大型云應用可以預期含有數據量巨大,可以隨著時間的推移顯著增加。服務器通常提供的磁盤存儲僅是有限的,但它可以是能與較大的取代現有的磁盤,或者添加另外的磁盤的機器作為數據量的增加。然而,由此,不能夠容易地增加一個給定的服務器上的存儲容量的系統最終將達到一個硬限制。 - 計算資源。云應用程序可能需要支持大量并發用戶,每一個運行檢索的數據存儲信息的查詢。一個單一的服務器托管的數據存儲可能無法提供所需的計算能力,以支持該負載,從而延長反應時間,為用戶和故障頻作為應用程序試圖存儲和檢索數據超時。它可能會增加存儲器或升級的處理器,但是當其不能夠提高計算資源的任何進一步的系統將達到極限。 - 網絡帶寬。最后,在單個服務器上運行的數據存儲區的性能是通過在該服務器可以接收請求并發送回復率的約束。這是可能的網絡流量的量可能會超過用于連接到該服務器,從而導致失敗的請求的網絡的容量。 - 地理。可能需要為存儲由特定的用戶在同一個區域中產生的那些用戶為合法,合規性,或性能原因,數據,或減少數據訪問延滯。如果用戶在不同的國家或地區的分散,也未必能夠存儲整個數據為在一個單一的數據存儲區中的應用。 垂直縮放通過添加更多的磁盤容量,處理能力,內存和網絡連接可能會推遲一些這些限制的效果,但它很可能是只是一個臨時的解決方案。能夠支持大量用戶和大量數據的商業云應用程序必須能夠擴展幾乎無限,所以垂直縮放不一定是最好的解決方案。 ## 解決方案 劃分數據存儲到水平分區或碎片。每個碎片都有相同的模式,但保存的數據其獨特的子集。甲碎片是在自己的權利(它可以包含許多不同類型的實體的數據)的數據存儲器,用作存儲節點的服務器上運行。 這種模式具有以下優點: - 您可擴展系統,通過添加額外的存儲節點上運行的進一步碎片。 - 系統可以使用現成的商品硬件,而不是專門的(和昂貴)的計算機為每個存儲節點。 - 您可以通過平衡跨越碎片的工作量減少爭用和改進的性能。 - 在云中,碎片可以位于物理上接近將要訪問數據的用戶。 何時將一個數據存儲成碎片,決定哪些數據應該被放置在每個碎片。甲碎片通常包含倒在數據中的一個或多個屬性所確定的指定范圍內的物品。這些屬性形成的分片密鑰(有時也被稱為分區鍵)。分片的關鍵應該是靜態的。它不應該根據可能發生變化的數據。 分片身體組織的數據。何時一個應用程序存儲和檢索數據,該分片的邏輯指示應用到相應的碎片。此拆分邏輯可在應用程序中被實現為數據訪問代碼的一部分,或者它可以由數據存儲系統中實現,如果它透明地支持分片。 抽象的拆分邏輯的數據的物理位置提供了一個高層次的控制在其上的碎片包含的數據,并且使數據分片之間遷移,而再加工的應用程序的業務邏輯應該需要在碎片的數據后面將要引入的(例如,如果碎片變得不平衡)。的折衷是在確定的每個數據項的位置,因為它被檢索所需的附加數據存取的開銷。 為了確保最佳的性能和可擴展性,分裂的數據的方式,適合的查詢類型的應用程序執行是重要的。在許多情況下,這是不可能的拆分計劃將完全符合每個查詢的要求。例如,在一個多用戶系統中的應用,可能需要通過使用承租者ID來檢索租戶數據,但它也可能需要基于其它屬性這個數據查找,如承租人的名稱或位置。為了處理這些情況,實行分片策略,即支持最常用的查詢執行的一個子庫的關鍵。 如果查詢通過使用屬性值的組合來定期檢索數據,這可能是可以定義通過將屬性一起的復合分片鍵。另外,使用模式,如索引表,以提供快速的查找到未覆蓋的碎片關鍵基礎屬性數據。 ## 分片策略 選擇所述分片密鑰,并決定如何跨碎片分發數據時的三種策略是常用的。注意,并不需要成為碎片和承載它們 - 在單個服務器可以承載多個分塊中的服務器之間的一對一的對應關系。這些戰略包括: - 查找策略。在上述策略中,分片的邏輯實現了一個圖,路由對數據的請求到包含碎片,通過使用分片密鑰數據。在一個多用戶應用將租戶的所有數據可能通過使用租戶 ID 作為分片密鑰一起存儲在一個碎片。多個租戶可能共享相同的碎片,但對于單個租戶的數據將不被跨越多個碎片散布。圖1示出了這種策略的一個例子。 ![](https://box.kancloud.cn/2015-09-21_55ffa43171543.png) 圖1 - 基于租戶ID的分片租戶數據 分片鍵和物理存儲的映射關系可以基于物理分塊,每個分片鍵映射到一個物理分區。可替換地,這種技術提供了重新平衡碎片時更大的靈活性是使用虛擬分區方法,其中分片鍵映射到虛擬碎片的數量相同,這又映射到較少的物理分區。在這種方法中,一個應用程序通過使用指的是一個虛擬碎片一個碎片鍵定位數據,并在系統的虛擬分片透明地映射到物理分區。進行修改,以使用一組不同的碎片的鍵的虛擬碎片和物理分區可以改變,而不需要對應用程序代碼之間的映射。 范圍的策略。這在同一個分片相關的項目一起策略組,并把它們的訂單通過分片密鑰分片鍵是連續的。它是用于應用程序通過使用范圍查詢(即返回一組數據項的為落在給定范圍內的碎片鍵查詢)經常檢索項集有用的。例如,如果應用程序經常需要找到放置在給定月份所有的訂單,該數據可被檢索更快如果一個月的所有命令被存儲在日期和時間的順序在同一個分片。如果每個訂單被存儲在不同的碎片,它們將必須通過進行大量的點查詢(返回單個數據項的查詢)的單獨取出。圖2示出了這種策略的一個例子。 ![](https://box.kancloud.cn/2015-09-21_55ffa431815d7.png) 圖2 - 數據中的碎片存儲順序集合(范圍) 在這個例子中,分片鍵是一個組合鍵,包括訂單月作為最顯著元件,其次是為了日和時間。創建和附加到一個碎片新訂單時,訂單中的數據自然排序。一些數據存儲支持包括識別所述碎片和行密鑰唯一地標識該子庫中的項分區鍵元件的兩部分分片密鑰。數據通常是在碎片中排鍵順序舉行。該受的范圍內的查詢和需要的項目組合在一起可以使用一個分片鍵具有用于分區鍵但該行鍵的唯一值相同的值。 哈希策略。這種策略的目的是減少在數據熱點的機會。它的目的是分配在實現每個碎片的大小和平均負載,每個碎片會遇到之間的平衡的方式在整個碎片中的數據。分片的邏輯計算,其中基于所述數據的一個或多個屬性的散列來存儲中的項目的子庫。所選擇的散列函數應該均勻地分布在整個數據碎片,可能通過引入一些隨機元素插入的計算。圖2示出了這種策略的一個例子。 ![](https://box.kancloud.cn/2015-09-21_55ffa43190a6e.png) 圖3 - 基于租戶ID的哈希分片租戶數據 了解超過其他分片策略哈希策略的優勢,考慮如何依序錄取新租戶多租戶應用程序可能分配租戶碎片中的數據存儲。當使用范圍的策略,租戶1到n的數據都將存儲在分片 A 中,數據為住戶的 n+1 到 m 都將存儲在分片 B,依此類推。如果最近登記的租戶也是最活躍,最數據活動將發生在少數碎片,這可能會導致熱點。與此相反,哈希策略分配租戶基于對其租戶ID的散列碎片。這意味著順序租戶是最有可能被分配到不同的碎片,如圖 3 所示為住戶 55 和 56,這將在這些碎片分配負載。 下表列出的主要優點和考慮這三個分片策略。 **Lookup 查找** 更好地控制碎片的配置和使用方式。 重新平衡數據時,因為新的物理分區可以被添加到拉平工作量使用虛擬碎片減少的影響。可以在不影響使用一個分片鍵來存儲和檢索數據的應用程序代碼被修改的虛擬碎片和實現該分片的物理分區之間的映射。 **Range 范圍** 易于實現和使用范圍查詢工作得很好,因為它們通常可以取在單個操作中從單個分片的多個數據項。 更簡便的數據管理。例如,如果用戶在相同的區域是在相同的子庫,更新可以安排在基于本地負載和需求模式的每個時區。 **Hash 哈希** 一個甚至更多的數據和負荷分布的更好的機會。 請求路由可以直接通過使用哈希函數來實現。沒有必要來維護一個地圖。 最常見的拆分方案實現上述方法之一,但你也應該考慮你的應用程序的業務需求和他們的數據使用模式。例如,在一個多用戶應用: - 可以分片根據工作負載數據。你可以分開在不同的碎片極易揮發租戶的數據。對于其他租戶的數據訪問的速度可以提高作為結果。 - 可以分片根據租戶的位置數據。它可能會采取對租戶的數據在一個特定的地理區域離線期間在該地區非高峰期備份和維護,而對于住戶在其他地區的數據仍然在他們上班時間上網和訪問。 - 高價值的住戶能分到自己的私人高性能,輕載碎片,而價值較低的住戶可能有望分享更密集堆積,忙碎片。 - 對于需要數據隔離和隱私的高度可以存儲一個完全獨立的服務器上租戶的數據。 ## 縮放和數據移動操作 每個分片策略意味著不同的功能和復雜性管理的規模,向外擴展,數據移動,并保持水平狀態。 查找策略允許縮放和數據移動操作來進行,在用戶層面,無論是在線還是離線。該技術暫停部分或全部用戶活動(也許是在非高峰時段),移動數據到新的虛擬分區或物理碎片,改變映射,無效或刷新持有該數據的緩存,然后讓用戶活動恢復。通常這種類型的操作可以進行集中管理。查找戰略要求的狀態是高度可緩存和副本友好。 的范圍的策略規定了結垢和數據移動操作,這通常必須進行時的一部分或全部的數據存儲為脫機,因為數據必須被分割和整個碎片合并的一些限制。移動的數據,以重新平衡碎片可能無法解決不均勻負荷的問題,如果大多數的活性是對相鄰分片密鑰或數據標識符是相同的范圍之內的。范圍的策略可能也需要進行維護,以圖范圍內的物理分區的一些狀態。 哈希策略使得擴展和數據移動操作更為復雜,因為分區鍵是碎片密鑰或數據標識符的哈希值。每個碎片的新位置,必須從散列函數來確定,或者該函數修改,以提供正確的映射。然而,哈希策略不需要維護狀態。 ## 問題和注意事項 在決定如何實現這個模式時,請考慮以下幾點: - 分片是互補的其他形式的分區,如垂直分區和功能劃分。例如,單個子庫可以包含已垂直劃分實體和功能劃分可以被實現為多個碎片。有關分區的詳細信息,請參閱數據分區指導。 - 保持平衡碎片,使他們都處理的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); ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看