在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ 大數(shù)據(jù)/ Sharding 分片模式
索引表模式
Sharding 分片模式
外部配置存儲模式
命令和查詢職責(zé)分離(CQRS)模式
靜態(tài)內(nèi)容托管模式
運行重構(gòu)模式
計算資源整合模式
Throttling 節(jié)流模式
斷路器模式
事件獲取模式
實體化視圖模式
緩存預(yù)留模式
守門員模式
聯(lián)合身份模式
補償交易模式
重試模式
領(lǐng)導(dǎo)人選舉模式
優(yōu)先級隊列模式
健康端點監(jiān)控模式
消費者的競爭模式
基于隊列的負載均衡模式
仆人鍵模式
管道和過濾器模式
調(diào)度程序代理管理者模式

Sharding 分片模式

將一個數(shù)據(jù)存儲到一組水平分區(qū)或碎片。存儲和訪問大量數(shù)據(jù)時,這個模式可以提高可擴展性。

背景和問題

由一個單一的服務(wù)器托管的數(shù)據(jù)存儲區(qū)可能會受到以下限制:

  • 存儲空間。一種數(shù)據(jù)存儲為一個大型云應(yīng)用可以預(yù)期含有數(shù)據(jù)量巨大,可以隨著時間的推移顯著增加。服務(wù)器通常提供的磁盤存儲僅是有限的,但它可以是能與較大的取代現(xiàn)有的磁盤,或者添加另外的磁盤的機器作為數(shù)據(jù)量的增加。然而,由此,不能夠容易地增加一個給定的服務(wù)器上的存儲容量的系統(tǒng)最終將達到一個硬限制。
  • 計算資源。云應(yīng)用程序可能需要支持大量并發(fā)用戶,每一個運行檢索的數(shù)據(jù)存儲信息的查詢。一個單一的服務(wù)器托管的數(shù)據(jù)存儲可能無法提供所需的計算能力,以支持該負載,從而延長反應(yīng)時間,為用戶和故障頻作為應(yīng)用程序試圖存儲和檢索數(shù)據(jù)超時。它可能會增加存儲器或升級的處理器,但是當(dāng)其不能夠提高計算資源的任何進一步的系統(tǒng)將達到極限。
  • 網(wǎng)絡(luò)帶寬。最后,在單個服務(wù)器上運行的數(shù)據(jù)存儲區(qū)的性能是通過在該服務(wù)器可以接收請求并發(fā)送回復(fù)率的約束。這是可能的網(wǎng)絡(luò)流量的量可能會超過用于連接到該服務(wù)器,從而導(dǎo)致失敗的請求的網(wǎng)絡(luò)的容量。
  • 地理??赡苄枰獮榇鎯τ商囟ǖ挠脩粼谕粋€區(qū)域中產(chǎn)生的那些用戶為合法,合規(guī)性,或性能原因,數(shù)據(jù),或減少數(shù)據(jù)訪問延滯。如果用戶在不同的國家或地區(qū)的分散,也未必能夠存儲整個數(shù)據(jù)為在一個單一的數(shù)據(jù)存儲區(qū)中的應(yīng)用。

垂直縮放通過添加更多的磁盤容量,處理能力,內(nèi)存和網(wǎng)絡(luò)連接可能會推遲一些這些限制的效果,但它很可能是只是一個臨時的解決方案。能夠支持大量用戶和大量數(shù)據(jù)的商業(yè)云應(yīng)用程序必須能夠擴展幾乎無限,所以垂直縮放不一定是最好的解決方案。

解決方案

劃分數(shù)據(jù)存儲到水平分區(qū)或碎片。每個碎片都有相同的模式,但保存的數(shù)據(jù)其獨特的子集。甲碎片是在自己的權(quán)利(它可以包含許多不同類型的實體的數(shù)據(jù))的數(shù)據(jù)存儲器,用作存儲節(jié)點的服務(wù)器上運行。

這種模式具有以下優(yōu)點:

  • 您可擴展系統(tǒng),通過添加額外的存儲節(jié)點上運行的進一步碎片。
  • 系統(tǒng)可以使用現(xiàn)成的商品硬件,而不是專門的(和昂貴)的計算機為每個存儲節(jié)點。
  • 您可以通過平衡跨越碎片的工作量減少爭用和改進的性能。
  • 在云中,碎片可以位于物理上接近將要訪問數(shù)據(jù)的用戶。

何時將一個數(shù)據(jù)存儲成碎片,決定哪些數(shù)據(jù)應(yīng)該被放置在每個碎片。甲碎片通常包含倒在數(shù)據(jù)中的一個或多個屬性所確定的指定范圍內(nèi)的物品。這些屬性形成的分片密鑰(有時也被稱為分區(qū)鍵)。分片的關(guān)鍵應(yīng)該是靜態(tài)的。它不應(yīng)該根據(jù)可能發(fā)生變化的數(shù)據(jù)。

分片身體組織的數(shù)據(jù)。何時一個應(yīng)用程序存儲和檢索數(shù)據(jù),該分片的邏輯指示應(yīng)用到相應(yīng)的碎片。此拆分邏輯可在應(yīng)用程序中被實現(xiàn)為數(shù)據(jù)訪問代碼的一部分,或者它可以由數(shù)據(jù)存儲系統(tǒng)中實現(xiàn),如果它透明地支持分片。

抽象的拆分邏輯的數(shù)據(jù)的物理位置提供了一個高層次的控制在其上的碎片包含的數(shù)據(jù),并且使數(shù)據(jù)分片之間遷移,而再加工的應(yīng)用程序的業(yè)務(wù)邏輯應(yīng)該需要在碎片的數(shù)據(jù)后面將要引入的(例如,如果碎片變得不平衡)。的折衷是在確定的每個數(shù)據(jù)項的位置,因為它被檢索所需的附加數(shù)據(jù)存取的開銷。

為了確保最佳的性能和可擴展性,分裂的數(shù)據(jù)的方式,適合的查詢類型的應(yīng)用程序執(zhí)行是重要的。在許多情況下,這是不可能的拆分計劃將完全符合每個查詢的要求。例如,在一個多用戶系統(tǒng)中的應(yīng)用,可能需要通過使用承租者ID來檢索租戶數(shù)據(jù),但它也可能需要基于其它屬性這個數(shù)據(jù)查找,如承租人的名稱或位置。為了處理這些情況,實行分片策略,即支持最常用的查詢執(zhí)行的一個子庫的關(guān)鍵。

如果查詢通過使用屬性值的組合來定期檢索數(shù)據(jù),這可能是可以定義通過將屬性一起的復(fù)合分片鍵。另外,使用模式,如索引表,以提供快速的查找到未覆蓋的碎片關(guān)鍵基礎(chǔ)屬性數(shù)據(jù)。

分片策略

選擇所述分片密鑰,并決定如何跨碎片分發(fā)數(shù)據(jù)時的三種策略是常用的。注意,并不需要成為碎片和承載它們 - 在單個服務(wù)器可以承載多個分塊中的服務(wù)器之間的一對一的對應(yīng)關(guān)系。這些戰(zhàn)略包括:

  • 查找策略。在上述策略中,分片的邏輯實現(xiàn)了一個圖,路由對數(shù)據(jù)的請求到包含碎片,通過使用分片密鑰數(shù)據(jù)。在一個多用戶應(yīng)用將租戶的所有數(shù)據(jù)可能通過使用租戶 ID 作為分片密鑰一起存儲在一個碎片。多個租戶可能共享相同的碎片,但對于單個租戶的數(shù)據(jù)將不被跨越多個碎片散布。圖1示出了這種策略的一個例子。

http://wiki.jikexueyuan.com/project/cloud-design-patterns/images/s.png" alt="" />

圖1 - 基于租戶ID的分片租戶數(shù)據(jù)

分片鍵和物理存儲的映射關(guān)系可以基于物理分塊,每個分片鍵映射到一個物理分區(qū)??商鎿Q地,這種技術(shù)提供了重新平衡碎片時更大的靈活性是使用虛擬分區(qū)方法,其中分片鍵映射到虛擬碎片的數(shù)量相同,這又映射到較少的物理分區(qū)。在這種方法中,一個應(yīng)用程序通過使用指的是一個虛擬碎片一個碎片鍵定位數(shù)據(jù),并在系統(tǒng)的虛擬分片透明地映射到物理分區(qū)。進行修改,以使用一組不同的碎片的鍵的虛擬碎片和物理分區(qū)可以改變,而不需要對應(yīng)用程序代碼之間的映射。

范圍的策略。這在同一個分片相關(guān)的項目一起策略組,并把它們的訂單通過分片密鑰分片鍵是連續(xù)的。它是用于應(yīng)用程序通過使用范圍查詢(即返回一組數(shù)據(jù)項的為落在給定范圍內(nèi)的碎片鍵查詢)經(jīng)常檢索項集有用的。例如,如果應(yīng)用程序經(jīng)常需要找到放置在給定月份所有的訂單,該數(shù)據(jù)可被檢索更快如果一個月的所有命令被存儲在日期和時間的順序在同一個分片。如果每個訂單被存儲在不同的碎片,它們將必須通過進行大量的點查詢(返回單個數(shù)據(jù)項的查詢)的單獨取出。圖2示出了這種策略的一個例子。

http://wiki.jikexueyuan.com/project/cloud-design-patterns/images/s1.png" alt="" />

圖2 - 數(shù)據(jù)中的碎片存儲順序集合(范圍)

在這個例子中,分片鍵是一個組合鍵,包括訂單月作為最顯著元件,其次是為了日和時間。創(chuàng)建和附加到一個碎片新訂單時,訂單中的數(shù)據(jù)自然排序。一些數(shù)據(jù)存儲支持包括識別所述碎片和行密鑰唯一地標(biāo)識該子庫中的項分區(qū)鍵元件的兩部分分片密鑰。數(shù)據(jù)通常是在碎片中排鍵順序舉行。該受的范圍內(nèi)的查詢和需要的項目組合在一起可以使用一個分片鍵具有用于分區(qū)鍵但該行鍵的唯一值相同的值。

哈希策略。這種策略的目的是減少在數(shù)據(jù)熱點的機會。它的目的是分配在實現(xiàn)每個碎片的大小和平均負載,每個碎片會遇到之間的平衡的方式在整個碎片中的數(shù)據(jù)。分片的邏輯計算,其中基于所述數(shù)據(jù)的一個或多個屬性的散列來存儲中的項目的子庫。所選擇的散列函數(shù)應(yīng)該均勻地分布在整個數(shù)據(jù)碎片,可能通過引入一些隨機元素插入的計算。圖2示出了這種策略的一個例子。

http://wiki.jikexueyuan.com/project/cloud-design-patterns/images/s2.png" alt="" />

圖3 - 基于租戶ID的哈希分片租戶數(shù)據(jù)

了解超過其他分片策略哈希策略的優(yōu)勢,考慮如何依序錄取新租戶多租戶應(yīng)用程序可能分配租戶碎片中的數(shù)據(jù)存儲。當(dāng)使用范圍的策略,租戶1到n的數(shù)據(jù)都將存儲在分片 A 中,數(shù)據(jù)為住戶的 n+1 到 m 都將存儲在分片 B,依此類推。如果最近登記的租戶也是最活躍,最數(shù)據(jù)活動將發(fā)生在少數(shù)碎片,這可能會導(dǎo)致熱點。與此相反,哈希策略分配租戶基于對其租戶ID的散列碎片。這意味著順序租戶是最有可能被分配到不同的碎片,如圖 3 所示為住戶 55 和 56,這將在這些碎片分配負載。

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

Lookup 查找

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

重新平衡數(shù)據(jù)時,因為新的物理分區(qū)可以被添加到拉平工作量使用虛擬碎片減少的影響??梢栽诓挥绊懯褂靡粋€分片鍵來存儲和檢索數(shù)據(jù)的應(yīng)用程序代碼被修改的虛擬碎片和實現(xiàn)該分片的物理分區(qū)之間的映射。

Range 范圍

易于實現(xiàn)和使用范圍查詢工作得很好,因為它們通??梢匀≡趩蝹€操作中從單個分片的多個數(shù)據(jù)項。

更簡便的數(shù)據(jù)管理。例如,如果用戶在相同的區(qū)域是在相同的子庫,更新可以安排在基于本地負載和需求模式的每個時區(qū)。

Hash 哈希

一個甚至更多的數(shù)據(jù)和負荷分布的更好的機會。

請求路由可以直接通過使用哈希函數(shù)來實現(xiàn)。沒有必要來維護一個地圖。

最常見的拆分方案實現(xiàn)上述方法之一,但你也應(yīng)該考慮你的應(yīng)用程序的業(yè)務(wù)需求和他們的數(shù)據(jù)使用模式。例如,在一個多用戶應(yīng)用:

  • 可以分片根據(jù)工作負載數(shù)據(jù)。你可以分開在不同的碎片極易揮發(fā)租戶的數(shù)據(jù)。對于其他租戶的數(shù)據(jù)訪問的速度可以提高作為結(jié)果。
  • 可以分片根據(jù)租戶的位置數(shù)據(jù)。它可能會采取對租戶的數(shù)據(jù)在一個特定的地理區(qū)域離線期間在該地區(qū)非高峰期備份和維護,而對于住戶在其他地區(qū)的數(shù)據(jù)仍然在他們上班時間上網(wǎng)和訪問。
  • 高價值的住戶能分到自己的私人高性能,輕載碎片,而價值較低的住戶可能有望分享更密集堆積,忙碎片。
  • 對于需要數(shù)據(jù)隔離和隱私的高度可以存儲一個完全獨立的服務(wù)器上租戶的數(shù)據(jù)。

縮放和數(shù)據(jù)移動操作

每個分片策略意味著不同的功能和復(fù)雜性管理的規(guī)模,向外擴展,數(shù)據(jù)移動,并保持水平狀態(tài)。

查找策略允許縮放和數(shù)據(jù)移動操作來進行,在用戶層面,無論是在線還是離線。該技術(shù)暫停部分或全部用戶活動(也許是在非高峰時段),移動數(shù)據(jù)到新的虛擬分區(qū)或物理碎片,改變映射,無效或刷新持有該數(shù)據(jù)的緩存,然后讓用戶活動恢復(fù)。通常這種類型的操作可以進行集中管理。查找戰(zhàn)略要求的狀態(tài)是高度可緩存和副本友好。

的范圍的策略規(guī)定了結(jié)垢和數(shù)據(jù)移動操作,這通常必須進行時的一部分或全部的數(shù)據(jù)存儲為脫機,因為數(shù)據(jù)必須被分割和整個碎片合并的一些限制。移動的數(shù)據(jù),以重新平衡碎片可能無法解決不均勻負荷的問題,如果大多數(shù)的活性是對相鄰分片密鑰或數(shù)據(jù)標(biāo)識符是相同的范圍之內(nèi)的。范圍的策略可能也需要進行維護,以圖范圍內(nèi)的物理分區(qū)的一些狀態(tài)。

哈希策略使得擴展和數(shù)據(jù)移動操作更為復(fù)雜,因為分區(qū)鍵是碎片密鑰或數(shù)據(jù)標(biāo)識符的哈希值。每個碎片的新位置,必須從散列函數(shù)來確定,或者該函數(shù)修改,以提供正確的映射。然而,哈希策略不需要維護狀態(tài)。

問題和注意事項

在決定如何實現(xiàn)這個模式時,請考慮以下幾點:

  • 分片是互補的其他形式的分區(qū),如垂直分區(qū)和功能劃分。例如,單個子庫可以包含已垂直劃分實體和功能劃分可以被實現(xiàn)為多個碎片。有關(guān)分區(qū)的詳細信息,請參閱數(shù)據(jù)分區(qū)指導(dǎo)。
  • 保持平衡碎片,使他們都處理的I / O相似的體積。作為數(shù)據(jù)被插入和刪除,它可能有必要定期地重新平衡的碎片,以保證均勻分布,并減少熱點的機會。再平衡可能是一個昂貴的操作。為了降低頻率與再平衡成為必要,你應(yīng)該確保每個碎片中含有足夠的可用空間來處理變化的預(yù)期貨量計劃增長。你還應(yīng)該制定戰(zhàn)略和腳本,你可以用它來快速重新平衡碎片這應(yīng)該成為必要。
  • 使用穩(wěn)定的數(shù)據(jù)分片的關(guān)鍵。如果分片鍵的變化,相應(yīng)的數(shù)據(jù)項可能需要碎片之間移動,增加工作通過更新操作執(zhí)行的工作量。出于這個原因,避免立足于潛在的波動信息的碎片關(guān)鍵。相反,尋找那些不變的或自然形成的關(guān)鍵屬性。
  • 確保碎片鑰匙都是獨一無二的。例如,應(yīng)避免使用自動遞增的字段作為分片的關(guān)鍵。在一些系統(tǒng)中,自動遞增字段可以不橫跨碎片協(xié)調(diào),從而可能導(dǎo)致在具有相同分片鍵不同的碎片的項目。

注意: 在不包括分片鍵也可能導(dǎo)致問題字段自動遞增值。例如,如果您使用自增字段來生成唯一標(biāo)識,并分布在不同的碎片兩個不同的項目可能被分配相同的ID。

  • 它可能無法設(shè)計出符合針對數(shù)據(jù)的每個可能的查詢要求一個分片鍵。分片的數(shù)據(jù),以支持最經(jīng)常進行的查詢,并在必要時創(chuàng)建二級索引表,以支持通過使用基于不屬于分片鍵的一部分的屬性標(biāo)準(zhǔn)檢索數(shù)據(jù)的查詢。欲了解更多信息,請參見索引表模式。
  • 查詢訪問僅單個碎片會比那些來自多個分塊中檢索數(shù)據(jù)的效率,從而避免執(zhí)行一個分片方案,該方案導(dǎo)致在執(zhí)行該連接在不同碎片保持的數(shù)據(jù)的查詢的大量應(yīng)用程序。請記住,碎瓷片可以包含的數(shù)據(jù)為多個類型的實體??紤]非規(guī)范化的數(shù)據(jù)保持相同的碎片常常被認為是一起查詢(如客戶的詳細信息和訂單,他們已經(jīng)把)相關(guān)實體,以減少單獨讀取數(shù)的應(yīng)用程序執(zhí)行。

注意: 如果在一個子庫的實體引用存儲在另一個分片的一個實體,包括分片鍵用于第二實體,作為第一實體的架構(gòu)的一部分。這可以幫助提高引用跨碎片相關(guān)數(shù)據(jù)查詢的性能。

  • 如果應(yīng)用程序必須執(zhí)行檢索來自多個分塊數(shù)據(jù)的查詢,有可能通過使用并行任務(wù)來獲取這些數(shù)據(jù)。例子包括扇出查詢,其中來自多個分片的數(shù)據(jù)檢索平行,然后匯總到一個結(jié)果。然而,這種方法不可避免地增加了一些復(fù)雜性的溶液的數(shù)據(jù)訪問邏輯。
  • 對于許多應(yīng)用來說,產(chǎn)生的小碎片更大數(shù)目可以比具有少量的大碎片,因為它們可以提供用于負載平衡的機會增加更加有效。如果預(yù)計需要碎片從一個物理位置移動到另一個這樣的方法也可以是有用的。移動小碎片比移動一個大的更快。
  • 確保提供給每個分片存儲節(jié)點的資源足以處理數(shù)據(jù)的規(guī)模和吞吐量方面的可擴展性要求。欲了解更多信息,請參閱數(shù)據(jù)分區(qū)引導(dǎo)部分“設(shè)計分區(qū)的可擴展性”。
  • 考慮復(fù)制參考數(shù)據(jù)所有碎片。如果從一個子庫中檢索數(shù)據(jù)的操作還引用靜態(tài)或緩慢移動的數(shù)據(jù)作為同一查詢的一部分,這個數(shù)據(jù)添加到碎片。然后,應(yīng)用程序可以讀取所有用于容易地查詢中的數(shù)據(jù),而無需進行額外的往返行程到一個單獨的數(shù)據(jù)存儲中。

注意: 如果在多個分塊的變化保持的基準(zhǔn)數(shù)據(jù),該系統(tǒng)必須同步所有碎片這些變化。而此同步發(fā)生時,系統(tǒng)可能會出現(xiàn)一定程度的混亂。如果你按照這種方法,你應(yīng)該設(shè)計自己的應(yīng)用程序能夠處理這個矛盾。

  • 它可以是難以維持的碎片之間的參照完整性和一致性,所以你應(yīng)該盡量減少影響在多個碎片數(shù)據(jù)操作。如果應(yīng)用程序必須通過碎片修改數(shù)據(jù),評估完整的數(shù)據(jù)一致性是否實際上是一個要求。相反,在云中一個常用的方法是實現(xiàn)最終一致性。每個分區(qū)中的數(shù)據(jù)分別進行更新,并在應(yīng)用程序邏輯必須承擔(dān)保證責(zé)任的更新都成功完成,以及處理,可以從查詢數(shù)據(jù)的最終一致的運行操作時產(chǎn)生的不一致。有關(guān)實現(xiàn)最終一致性的更多信息,請參閱數(shù)據(jù)一致性底漆。
  • 配置和管理大量碎片可能是一個挑戰(zhàn)。任務(wù),例如監(jiān)控,備份,檢查一致性,并記錄或?qū)徲嫳仨毻瓿蓪Χ鄠€碎片和服務(wù)器,在多個位置有可能保持。這些任務(wù)可能會通過使用腳本或其他自動化解決方案,但腳本和自動化可能無法完全消除額外的行政要求執(zhí)行。
  • 碎片可以是地理定位的,使得它們包含的數(shù)據(jù)是靠近使用它的應(yīng)用程序的實例。這種方法可以顯著改善的性能,但是需要額外考慮為必須訪問多個分塊中的不同位置的任務(wù)。

何時使用這個模式

使用這種模式:

  • 當(dāng)數(shù)據(jù)存儲可能需要擴展超越了一單個存儲節(jié)點的資源的限制。
  • 通過減少爭用的數(shù)據(jù)存儲來提高性能。

注意: 分片的主要焦點是改進系統(tǒng)的性能和可擴展性,而作為副產(chǎn)物,也可以借助于其中數(shù)據(jù)被劃分成單獨的分區(qū)的方式提高可用性。在一個分區(qū)中的故障不一定阻止應(yīng)用程序訪問的其他分區(qū)中保存的數(shù)據(jù),并且操作者無需使得整個數(shù)據(jù)為應(yīng)用程序無法訪問的可以執(zhí)行的一個或多個分區(qū)的維護或復(fù)原。欲了解更多信息,請參閱數(shù)據(jù)分區(qū)指導(dǎo)。

例子

下面的示例使用了一組充當(dāng)碎片的 SQL Server 數(shù)據(jù)庫。每個數(shù)據(jù)庫包含一個應(yīng)用程序使用的數(shù)據(jù)的一個子集。應(yīng)用程序檢索該被分布在整個碎片通過使用它自己的分片邏輯(這是一個扇出查詢的一個例子)的數(shù)據(jù)。將位于每個子庫中的數(shù)據(jù)的細節(jié)是通過這樣的方法稱為 GetShards 返回。此方法返回 ShardInformation 對象,其中 ShardInformation 類型包含一個標(biāo)識符為每個碎片和 SQL Server 的連接字符串,應(yīng)用程序應(yīng)該使用連接到碎片的枚舉列表(在連接字符串中沒有代碼示例所示)。

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 = ...  
    }  
  };  
}  

下面的代碼顯示了如何在應(yīng)用程序使用 ShardInformation 對象名單進行了從并行每個碎片獲取數(shù)據(jù)的查詢。查詢的細節(jié)沒有示出,但在本實施例中所檢索的數(shù)據(jù)包括可以存放信息,如客戶的名稱,如果碎片包含客戶的細節(jié)的字符串。該結(jié)果由應(yīng)用聚集成 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);  
上一篇:補償交易模式