# 為在現代時代構建可擴展的有狀態服務提供依據
> 原文: [http://highscalability.com/blog/2015/10/12/making-the-case-for-building-scalable-stateful-services-in-t.html](http://highscalability.com/blog/2015/10/12/making-the-case-for-building-scalable-stateful-services-in-t.html)

長期以來, [無狀態服務](https://en.wikipedia.org/wiki/Service_statelessness_principle) 一直是可擴展性的皇家之路。 幾乎所有關于可伸縮性的論文都將無狀態聲明為構建可伸縮系統的最佳實踐認可方法。 無狀態架構易于水平擴展,只需要簡單的循環負載平衡即可。
什么是不愛的? 從往返到數據庫的延遲可能增加了。 或者,隱藏數據庫延遲問題所需的緩存層的復雜性。 甚至是麻煩的一致性問題。
但是有狀態服務呢? 是不是通過將功能傳遞給數據而不是將數據傳遞給功能來保留身份,是不是更好的方法? 通常是這樣,但是我們對如何構建有狀態服務知之甚少。 實際上,進行搜索后,構建狀態服務的系統方法幾乎沒有。 維基百科甚至沒有 *有狀態服務* 的條目。
[Caitie McCaffrey](https://twitter.com/caitie?lang=en) (Twitter 上的可觀察性技術負責人)正在通過 [奇怪循環](http://www.thestrangeloop.com/) 會議,關于 [構建可擴展的有狀態服務](https://www.youtube.com/watch?v=H0i_bXKwujQ) ( [幻燈片](https://speakerdeck.com/caitiem20/building-scalable-stateful-services) )。
令人耳目一新,因為我從未聽說過以 Caitie 談論構建有狀態服務的方式來構建有狀態服務。 您會認識到大多數想法-粘滯會話,數據傳送范例,功能傳送范例,數據局部性,CAP,集群成員資格,八卦協議,一致性哈希,DHT-但她將它們圍繞構建有狀態服務的主題進行了編織 以最引人注目的方式
對我來說,這次談話的亮點是,當 Caitie 將整個談話圍繞在討論她使用 Microsoft 的 [奧爾良](http://dotnet.github.io/orleans) 開發 Halo 4 的經歷時 Azure 的。 奧爾良的覆蓋面不足。 它基于固有的有狀態分布式虛擬 Actor 模型; 集群成員資格使用高度可用的八卦協議; 并使用兩層一致性哈希加上分布式哈希表的系統進行工作分配。 使用此方法,當節點發生故障,容量增加/收縮或節點變熱時,奧爾良可以重新平衡群集。 結果是 Halo 能夠在生產環境中運行有狀態的奧爾良群集,整個群集的 CPU 利用率為 90-95%。
奧爾良并不是唯一涵蓋的示例系統。 還使用 Caitie 的狀態架構框架分析了 Facebook 的 Scuba 和 Uber 的 Ringpop。 還有一個非常有趣的部分,介紹 Facebook 如何通過將內存生存期與進程生存期脫鉤,為大型內存數據庫巧妙地實現快速數據庫重啟。
因此,讓我們開始學習如何構建有狀態服務...
## 無狀態服務是浪費
* 無狀態服務運行良好。 通過在需要時添加新的無狀態服務實例,將規范的真理源存儲在數據庫中并進行水平擴展非常有效。
* 問題在于我們的應用程序確實具有狀態,并且我們達到了一個數據庫不再削減的極限。 作為回應,我們將分片關系數據庫或使用 NoSQL 數據庫。 這會放棄強大的一致性,從而導致部分數據庫抽象泄漏到服務中。
* **數據傳送范例**
* 客戶端發出服務請求。 該服務與數據庫對話,并且數據庫以一些數據答復。 該服務進行一些計算。 答復將發送到客戶端。 然后數據從服務中消失。
* 下一個請求將負載平衡到另一臺計算機,并且整個過程將再次發生。
* **對于涉及在一段時間內在會話中運行的健談客戶端的應用程序,將資源反復提取到負載平衡服務**中非常浪費。 示例:游戲,訂購產品,您要更新有關自己的信息的任何應用程序。
## 有狀態服務更易于編程
* 注意:有狀態服務不是魔術。 如果需要水平可伸縮性,那么無狀態服務仍然非常有效。 但是有狀態服務確實提供了很多好處。
* **數據位置** 。 將請求發送到保存有操作所需數據的計算機的想法。 優點:
* **低延遲** 。 不必為每個單獨的請求訪問數據庫。 僅當數據內存不足時才需要訪問數據庫。 網絡訪問的數量減少了。
* **數據密集型應用程序** 。 如果客戶需要處理一堆數據,那么所有數據都將可以訪問,因此可以快速返回響應。
* **功能傳送范例**
* 客戶端發出請求或啟動會話,一次訪問數據庫將獲取數據,然后數據移入服務。
* 處理請求后,數據留在服務上。 客戶端下一次發出請求時,請求將路由到同一臺計算機,這樣它就可以處理內存中已存在的數據。
* 避免了額外的數據庫訪問,從而減少了延遲。 即使數據庫關閉,也可以處理該請求。
* 有狀態性導致**的使用率更高[??HTG1] **,并且一致性更高** **模型**。**
* 在我們有不同級別的一致性的 CAP 世界中,某些級別比其他級別更可用。 當存在分區時,CP 系統選擇一致性而不是可用性,而 AP 系統選擇可用性而不是一致性。
* 如果我們要在 AP 下擁有更多高可用性的系統,我們將獲得“讀取讀取”,“單調讀取”,“單調寫入”。 ( [用于定義](http://www.cs.rice.edu/~druschel/comp413/lectures/replication.html) )
* 如果我們有粘性連接,其中單個用戶的數據在單臺計算機上,那么您可以擁有更強的一致性保證,例如“讀取寫入”,“流水線隨機存取存儲器”。
* [Werner Vogel 2007](http://www.allthingsdistributed.com/2007/12/eventually_consistent.html) :是否可以實現讀,寫,會話和單調一致性,通常取決于客戶端對執行服務器的“粘性” 他們的分布式協議。 如果每次都使用同一臺服務器,則保證讀取和單調讀取相對容易。 這使得管理負載平衡和容錯的難度稍大一些,但這是一個簡單的解決方案。 使用粘性的會話可以使這一點變得明確,并提供客戶可以推理的暴露水平。
* **粘性連接使客戶可以更輕松地推斷** 的模型。 不必擔心數據被拉到許多不同的計算機中,也不必擔心并發性,您只需要讓客戶端與同一臺服務器通信即可,這更容易考慮,并且在對分布式系統進行編程時會大有幫助。
## 建立粘性連接
* 客戶端向服務器集群發出請求,并且該請求始終路由到同一臺計算機。
* 最簡單的方法是 **打開持久的 HTTP 連接** 或 TCP 連接。
* 易于實現,因為連接意味著您始終在與同一臺機器通信。
* 問題:連接斷開后,粘性消失了,下一個請求將被負載平衡到另一臺服務器。
* 問題:負載平衡。 有一個隱含的假設,即所有粘性會話都將持續大約相同的時間,并產生大約相同的負載。 通常情況并非如此。 如果連接過多的單個服務器,連接持續很長時間或者每個連接都要做很多工作,那么很容易使連接過多的單個服務器不堪重負。
* **必須實現背壓** **,以便服務器在連接不堪重負時斷開連接。 這導致客戶端重新連接到希望減輕負擔的服務器。 您還可以根據自由分配的資源量進行負載均衡,以更公平地分配工作。**
* **在集群**中實現路由 **更聰明。 客戶端可以與群集中的任何服務器通信,該服務器會將客戶端路由到包含正確數據的服務器。 需要兩個功能:**
* **群集成員資格** 。 誰在我的集群中? 我們如何確定可以與哪些機器通信?
* **工作分配** 。 負載如何在整個群集中分配?
## 集群成員資格
* 群集成員資格系統共有三種常規類型:靜態,八卦協議,共識系統。
### 靜態集群成員資格-最簡單的方法
* 可以從最笨的事情開始,看看它是否滿足您的需求。
* 最簡單的方法是一個配置文件,其中包含集群中節點的所有地址。 配置文件分發到每臺計算機。
* 易于執行,但操作起來很痛苦。
* 對于必須高度可用的服務不是一個很好的選擇。
* 它不是容錯的。 如果機器出現故障,則必須更換它并更新配置。
* 很難擴展集群。 要添加計算機,必須重新啟動整個集群,以便可以在整個集群之間正確地重新平衡工作。
### 動態集群成員資格
* 可以從群集中動態添加或刪除節點。
* 要增加容量或補償故障,可以將節點添加到群集并立即開始接受負載。 也可以通過刪除節點來減少容量。
* 處理集群成員資格的兩種主要方法:八卦協議和共識系統。
### 八卦協議-強調可用性
* 八卦協議通過發送消息在整個小組中傳播知識。
* 消息中提到了他們可以與誰交談,誰還活著,誰死了。 每臺機器都將自己從數據中找出其收集集群中誰的世界視圖。
* 在穩定狀態下,集群中的所有機器將匯聚在一起,以對誰是活著還是死了的世界具有相同的世界觀。
* 在網絡故障,網絡分區或添加或刪除容量的情況下,群集中的不同計算機可以對群集的誰擁有不同的世界觀。
* 需要權衡。 您具有高可用性,因為不需要任何協調,每臺機器都可以根據自己的世界觀進行決策,但是您的代碼必須能夠處理在故障期間路由到不同節點的不確定性。
### 共識系統-強調一致性
* 群集中的所有節點將具有完全相同的世界視圖。
* 共識系統控制集群中每個人的所有權。 當配置更改時,所有節點都基于擁有真實集群成員資格的共識系統更新其世界觀。
* 問題:如果無法使用共識系統,則節點將無法路由工作,因為它們不知道集群中的成員。
* 問題:由于向系統添加了協調,因此速度會變慢。
* 如果您需要高可用性,則除非確實有必要,否則應避免使用共識系統。
## 工作分配
* 工作分配是指如何在整個集群中移動工作。
* 有三種類型的工作分配系統:隨機放置,一致哈希,分布式哈希表。
### 隨機放置
* 聽起來很傻,但是可以有效。 它適用于在集群中分布著大量數據和查詢的情況下處理大量數據的情況。
* 寫入到具有容量的任何計算機。
* 讀取操作需要查詢集群中的每臺計算機,以取回數據。
* 這不是固定連接,而是有狀態服務。 這是構建內存索引和緩存的好方法。
### 一致的哈希-確定性放置
* 基于哈希(可能是會話 ID 或用戶 ID)的確定性的對節點的放置,具體取決于工作負載的劃分方式。
* 當節點被映射到集群時,請求也被映射到環,然后您繼續向前走以找到將要執行請求的節點。
* 由于確定性的位置,像 Cassandra 這樣的數據庫經常使用這種方法。
* 問題:熱點。
* 許多請求最終可能被散列到同一節點,并且該節點被流量所淹沒。 或節點速度可能很慢,也許磁盤壞了,甚至正常數量的請求也淹沒了它。
* 哈希值不一致,因此無法移動工作以降溫熱點。
* 因此,您必須在群集中分配足夠的空間,才能以足夠的凈空運行,以容忍確定性的放置以及無法移動工作這一事實。
* 這種額外的容量是額外的成本,即使在正常情況下也必須承擔。
### 分布式哈希表(DHT)-非確定性放置
* 哈希用于在分布式哈希表中查找,以查找應將工作發送到的位置。 DHT 保留對群集中節點的引用。
* 這是不確定的,因為沒有任何事情迫使工作去到特定的節點。 重新映射客戶端很容易,以便在某個節點不可用或溫度過高時將其轉到其他節點。
## 現實世界中的三個示例狀態服務
### Facebook 的潛水-寫作時隨機散布
* Scuba 是一個快速可擴展的分布式內存數據庫,用于代碼回歸和分析,錯誤報告,收入以及性能調試。 ( [更多信息](https://research.facebook.com/publications/456106467831449/scuba-diving-into-data-at-facebook/) )
* 它必須非常快并且始終可用。
* 想法是它使用靜態集群成員身份,盡管本文沒有明確說明。
* Scuba 在寫入時使用隨機扇出。 讀取時查詢每臺機器。 所有結果均由運行查詢的計算機返回并組成,并將結果返回給用戶。
* 在現實世界中,機器不可用,因此運行查詢時會盡力而為。 如果不是所有節點都可用,則查詢將返回可用數據的結果以及有關它們處理的數據百分比的統計信息。 用戶可以決定結果是否滿足足夠高的質量閾值。
* 沒有使用粘性連接,但數據在內存中,因此查找速度非常快。
### Uber 的鈴聲-八卦協議+一致性哈希
* Ringpop 是一個 node.js 庫,用于實現應用程序層分片。 ( [更多信息](http://highscalability.com/blog/2015/9/14/how-uber-scales-their-real-time-market-platform.html) )
* Uber 有旅行的概念。 要開始旅行,用戶訂購一輛需要騎手信息和位置信息的汽車,在整個騎行過程中會更新數據,并且必須在旅行結束時處理付款。
* 對于這些更新中的每一個,每次都將負載平衡到不同的無狀態服務器將是低效率的。 數據將不斷保存到數據庫中,然后再次拉回。 這會導致大量延遲和數據庫上的額外負載。
* 該設計實現了路由邏輯,因此可以將對用戶的所有請求定向到單個計算機。
* 游泳八卦協議用于維護群集成員身份。 這是 AP 群集成員身份協議,因此不能保證始終正確。 選擇可用性而不是正確性是因為用戶始終可以訂購汽車,這一點更為重要。
* 一致性哈希用于在整個群集中路由工作。 這具有熱節點問題,并且唯一的補救措施是增加更多的容量,即使沒有充分利用其他節點。
### 微軟的奧爾良-八卦協議+一致的哈希+分布式哈希表
* Orleans 是用于基于 Actor 模型構建分布式系統的運行時和編程模型。 ( [更多信息](http://research.microsoft.com/en-us/projects/orleans/) )
* 奧爾良來自 Extreme Computing Group 的 Microsoft Research。 演示者(Caitie McCaffrey)與該小組合作,在運送 Halo 4 的過程中使 Orleans 產品化。所有 Halo 4 服務主要在 Orleans 上重建。
* Actor 是計算的核心單元。 Actor 使用整個集群中的異步消息相互通信。 當 Actor 收到消息時,它可以執行以下一項或多項操作:發送一條或多則消息,更新其內部狀態,創建新的 Actor。
* 在基于 Actor 模型的集群中,您有一堆正在運行的狀態機,因此,如果 Actor 模型在請求之間保持狀態不變,則它們固有地是有狀態的。
* 在 Halo 4 中,他們將部署一臺機器集群,而奧爾良則負責其余的工作。
* 請求將發送到群集中的任何計算機。 群集將查找 Actor 在群集中的居住位置,并將消息路由到 Actor。
* 成千上萬的 Actor 在集群中的單臺計算機上運行。
* 閑話協議用于集群成員身份,以使其具有較高的可用性。 由于 Orleans 是開源的,因此創建了 Zookeeper 實現,這比較慢。
* 對于工作分配,奧爾良使用一致哈希+分布式哈希表的組合。
* 將對 Actor 的請求發送到集群時,Orleans 運行時將在 Actor ID 上計算一致的哈希。 哈希映射到具有該 ID 的分布式哈希表的計算機。
* Actor 的分布式哈希表知道哪臺計算機包含指定 ID 的 Actor。
* 在咨詢了 DHT 之后,請求被路由到適當的機器。
* 一致性哈希用于查找 Actor DHT,因此這是確定性操作。 DHT 在群集中的位置不會更改。 而且,由于 DHT 中的數據量很小并且 Actor DHT 分布均勻,因此熱點并不是大問題。
* 演員正在做的事情不是均勻分布和平衡的。
* 奧爾良能夠自動重新平衡群集。 在以下情況下,可以更新 DHT 中的條目以指向新機器:
* 會話終止。
* 機器發生故障,因此必須分配新的機器。
* 由于沒有人在與演員交談,因此將其從記憶中逐出。
* 機器溫度過高,因此奧爾良將 Actor 移到容量更大的另一臺機器上,這樣熱機器就不會發生故障。
* Orleans 的重新平衡功能是 Orleans 群集可以在整個群集中以 90-95%的 CPU 利用率在生產中運行的核心原因。 能夠以不確定的方式移動工作,這意味著您可以使用盒子的所有容量。
* 此方法可能不適用于數據庫,但對于將狀態引入服務非常有用。
## 可能出錯的地方
### 無限數據結構
* 在有狀態系統中,無限制的數據結構是消亡的好方法。 示例:無限制的隊列,無限制的內存結構。
* 在無狀態服務中,我們無需經常考慮這一點,因為它們可以從此類短暫故障中恢復。
* 在有狀態服務中,服務可以獲取很多請求,因此必須在數據結構上放置明確的界限,否則它們可能會不斷增長。 然后,您可能會用完內存,或者您的垃圾收集器可能會使世界停止運轉,并且該節點可能看起來已經死了(我還要補充一點,隨著數據結構的增長,鎖可以保留很長時間)。
* 客戶不是您的朋友。 客戶不會做您想要他們做的事。 機器可能會死于隱性假設,即我們不會用完內存,否則客戶端只會發送合理數量的數據。 代碼必須保護自己免受客戶侵害。
### 內存管理
* 因為數據會在會話的整個生命周期內(可能是幾分鐘,幾小時甚至幾天)保持在內存中,所以內存將進入壽命最長的垃圾回收。 通常,收集該內存的成本更高,尤其是當存在跨代的引用時。
* 您必須更加了解內存在有狀態服務中的工作方式,并且實際上需要了解垃圾收集器的運行方式。
* 或者,您也可以使用非托管代碼(例如 C ++)編寫所有內容,因此您不必處理垃圾收集器問題。
* 奧爾良運行 [.NET CLR](https://en.wikipedia.org/wiki/Common_Language_Runtime) ,這是一個垃圾收集環境,確實遇到了跨代垃圾收集問題。
* 通過調整垃圾收集器來處理。
* 這也通過實現許多不必要狀態的持久化來處理。 您必須對所保留的內容保持謹慎,因為存在相關的成本。
### 重載狀態
* 通常,在無狀態服務中,必須為每個請求查詢數據庫,因此必須調整等待時間以解決與數據庫的往返行程。 或者,您可以使用緩存來使其更快。
* 在有狀態服務中,可以重新加載狀態的時間有很多不同:第一次連接,從崩潰中恢復,部署新代碼。
#### 首次連接
* 通常,這是最昂貴的連接,因為該節點上沒有數據。 必須將所有數據拉入數據庫,以便可以處理請求。
* 這可能需要很長時間,因此您要非常小心啟動時加載的內容。 您不希望遇到恰好落在第一個連接上的請求帶來高延遲。
* 在測試中使用 [百分位數](http://highscalability.com/blog/2015/10/5/your-load-generator-is-probably-lying-to-you-take-the-red-pi.html) 。 平均延遲看起來不錯,因為您不必每次都往返于數據庫。 第一次連接延遲可能會增加,您不想錯過。
* 在第一個連接上,如果客戶端由于對數據庫的訪問速度較慢而超時,則您將繼續嘗試從數據庫加載,因為您知道客戶端將重試。 客戶端的下一次訪問將很快,因為數據很可能在內存中。 在無狀態服務中,您無法進行這種優化。
* 例如,在 Halo 中,當游戲開始時,第一個連接有時會超時。 也許用戶有很多游戲狀態或連接已加載。 因此,他們會繼續輸入數據,并且在游戲箱重試時請求會成功。 用戶不會注意到延遲,特別是考慮到用戶正在觀看的漂亮動畫。
#### 從崩潰中恢復
* 如果必須從崩潰中恢復后為整個盒子補水,如果您沒有懶惰地加載所有 Actor,這可能會很昂貴。 有時您可以擺脫延遲加載,有時則無法。
#### 部署新代碼
* 要部署新代碼,您必須拆卸整個包裝箱,然后將其重新備份到另一個包裝箱中。 如果您沒有不確定的展示位置或動態集群成員身份,可能會出現問題。
#### [快速數據庫從 Facebook 重新啟動](https://research.facebook.com/publications/553456231437505/fast-database-restarts-at-facebook/)
* Facebook 的 Scuba 產品出現重新啟動問題,因為它是一個內存數據庫,其中存儲了許多保留在硬盤上的數據。
* 在崩潰或部署中,他們將關閉當前正在運行的計算機,啟動新計算機,然后從磁盤讀取所有內容。 每臺機器要花幾個小時。 而且由于他們的 SLA,Facebook 必須對其集群進行緩慢的滾動更新,這最多需要 12 個小時。
* 崩潰不會經常發生,因此緩慢的重啟并不是一個大問題。 我們希望代碼部署經常發生,以便我們可以更快地迭代,嘗試新想法,降低風險部署。
* Facebook 做出了一個關鍵的觀察,即您可以 **將內存壽命與進程壽命** 分開,尤其是在有狀態服務中。
* 當 Facebook 想部署新代碼,并且知道這是安全的關閉并且內存沒有損壞時,他們將:停止接收請求,將數據從當前運行的進程復制到共享內存,關閉舊進程,引入 啟動新進程,然后將共享內存中的數據復制回進程內存空間,然后重新啟動請求。
* 此過程需要幾分鐘,因此群集重新啟動的時間現在是 2 小時而不是 12 小時。 現在,可以比以前更頻繁地部署新代碼。
* Twitter 正在考慮為有狀態索引實施此策略,當整個計算機重新啟動時,它必須與他們的 Manhattan 數據庫通信,這與內存相比確實很慢。
## 總結
* 集群成員資格和工作分配中有很多工作和思想。
* 沒有正確的答案。
* 她偏向可用一側,因此更喜歡八卦協議。
* 對于工作分配,取決于工作量。
* 在現實世界中運行著許多成功的有狀態系統。 事實證明,您可以大規模地進行這項工作,因此盡管它是新領域,但并沒有太嚇人。
* **請謹慎** ,因為如果您以前沒有做過有狀態服務,那么這就是新領域。 經歷不同的地方,發生了什么變化,做出的假設,并確保您的假設明確。
* **閱讀論文**。 不要重新發明自己的協議。 這實際上不是新領域。 自 60 年代和 70 年代以來,人們一直在為此工作。 大部分討論來自數據庫文獻。 這些問題已經解決。 您可以根據您的應用程序挑選您關心的內容。 您不必實施整個文件,只需實施所需的文件即可。
## 相關文章
* [關于黑客新聞](https://news.ycombinator.com/item?id=10378219)
* [CaitieM.com](http://caitiem.com/) 是 Caitie McCaffrey 的博客。
* [應用英雄模式](https://www.youtube.com/watch?v=xDuwrtwYHu8)
* [暈 4:高需求,低延遲和高可用性](https://www.youtube.com/watch?v=5P4qMBXT4P8)
* [奧爾良:云計算框架](https://www.youtube.com/watch?v=pkdeXGg7D98)
* [架構和啟動 Halo 4 服務](https://www.youtube.com/watch?v=fJSnM6CWcAs)
* [重新平衡群集](https://www.google.com/search?q=rebalancing+clusters&oq=rebalancing+clusters&aqs=chrome..69i57.4116j0j7&sourceid=chrome&es_sm=119&ie=UTF-8)
* [為什么任何人都不能在沒有中斷的情況下啟動在線服務?](http://www.gamesindustry.biz/articles/2013-11-20-why-cant-anyone-launch-an-online-service-without-outages)
* [#WindowsAzure 經驗教訓:保持狀態](https://alexandrebrisebois.wordpress.com/2014/02/23/windowsazure-lessons-learned-be-stateful/)
* [使用開源奧爾良框架](http://www.gamasutra.com/blogs/AshkanSaeediMazdeh/20151008/255588/Creating_scalable_backends_for_games_using_open_source_Orleans_framework.php)創建游戲的可擴展后端
無狀態服務也很容易,以易于理解和預測的方式交易一些額外的資源,以完全消除所有類的問題(例如,升級期間長期存在的會話會發生什么情況)。
對我來說,最重要的是,如果您不是*還是*構建下一個 Halo 或 Twitter,則最初說明的構建 12Factor 應用程序的大多數原因仍然適用。 而且我們大多數人不是。 那是一件好事。
與服務滿足一個請求后,使用緩存保留數據有何不同? 只是我沒有將應用程序服務器保存數據,而是將其保存在部署在一組專用服務器上的分布式緩存中。 如果狀態保持在分布式哈希圖中,并保持從服務邏輯(服務)到分布式哈希圖(緩存)的持久連接,那它將是有狀態服務嗎?
看看 Azure Service Fabric(https://azure.microsoft.com/zh-cn/campaigns/service-fabric/)。 它帶來了奧爾良的一些概念,但是包裝得更好,并增加了更多的價值(Actor 提供無狀態和 Statefull 可靠服務)。
實際上,服務結構在哈希算法上有所不同(它們沒有 DHT),并且在某些其他方面,請謹慎選擇。
這種有狀態的應用程序架構可以通過多個緩存層架構輕松實現-緩存數據庫中的數據,緩存處理后的數據(信息,結果)以及緩存表示數據(json,xml)。
> “如果需要高可用性,除非確實需要,否則應避免使用共識系統。”
她沒有那么說。
她說,如果您需要一個高可用性系統,那么共識系統是設計動態集群成員資格的最后手段,因為共識系統本身在故障情況下可能不可用。
但是她沒有提到像 Hashicorp 的 Consul 這樣的高可用性共識系統,在該系統中,您有服務器集群來管理該狀態。 我希望她對使用此工具構建分布式系統有意見。
通過共識系統,我認為她指的是 Raft 或 Paxos 之類的東西,它們試圖變得更加一致而不是可用(來自 CAP)。 Consul 使用 SWIM 協議進行動態成員資格,另一方面,該協議可用而不是一致的。 SWIM 允許部分可用性進行操作,而 Raft 或 Paxos 等系統則不允許。 我相信她只是重新開始了 Peter Bailis 所說的,除非您確實需要,否則不要使用 CP 系統。
非常感謝您對 Caitie McCaffrey 演示文稿的寫作。 這是一個接近完美的成績單,而且是一個很好的介紹。 沒有它,我可能會錯過她的演講。
自 2000 年以來,我一直在從事 MMO 游戲服務器的開發。在大部分時間里,這一直是一個很小的利基市場。 像大多數分布式系統一樣,MMO 必須擴展。 但是,與大多數其他分布式體系結構不同,MMO 是高度有狀態的。
直到最近,我還沒有從游戲界之外找到許多解決這些問題的例子。 同樣,游戲工作室/發行商傳統上也不愿意分享他們的“商業秘密”。 結果,當開發人員在工作室之間移動時,對這些概念的了解往往會緩慢擴散。
很高興看到我們在 MMO 空間中使用的一些以這種方式驗證的技術。 看到這些想法得到改進和增強也很酷。 持久連接,是的。 背壓是必須的嗎? 嗯..很明顯,但是我們沒有這樣做。 當然,可以通過一致的哈希值進行分片。 分布式哈希表? 哦,希望我們也這樣做。 我們會探索這樣的想法,但是常常會發現,在沒有證據證明別人已經證明自己的價值的情況下,很難為進行這些工作辯護。
我很高興看到該主題在更廣泛的背景下獲得了一些“合法性”。 很高興知道我們 MMO 開發人員并不孤單。 :)
干杯!
對不起,如果我錯過了什么。 但是,這篇演講并沒有說明如果有狀態節點死亡將導致的數據丟失。 FB 的共享內存方法是一種方法,但是在這種方法中,我們是在關閉節點之前顯式復制數據/但是什么是節點/ VM / PhysicalMachine 突然崩潰。在這種情況下不會丟失數據 ?
> 但是,這篇演講并沒有說明如果有狀態節點死亡將導致的數據丟失。
如果僅將狀態保留在內存中,則只會丟失數據。 您真正要做的是主要使用內存,但也可以在外部存儲狀態,以便您可以恢復。 例如,Akka 具有持久性的“事件源”模型-參與者可以持久/發出代表其內部狀態變化的事件; 如果由于故障或重新平衡而需要重新啟動 actor,則將回放這些事件,以便 actor 可以恢復其狀態。
- LiveJournal 體系結構
- mixi.jp 體系結構
- 友誼建筑
- FeedBurner 體系結構
- GoogleTalk 架構
- ThemBid 架構
- 使用 Amazon 服務以 100 美元的價格構建無限可擴展的基礎架構
- TypePad 建筑
- 維基媒體架構
- Joost 網絡架構
- 亞馬遜建筑
- Fotolog 擴展成功的秘訣
- 普恩斯的教訓-早期
- 論文:Wikipedia 的站點內部,配置,代碼示例和管理問題
- 擴大早期創業規模
- Feedblendr 架構-使用 EC2 進行擴展
- Slashdot Architecture-互聯網的老人如何學會擴展
- Flickr 架構
- Tailrank 架構-了解如何在整個徽標范圍內跟蹤模因
- Ruby on Rails 如何在 550k 網頁瀏覽中幸存
- Mailinator 架構
- Rackspace 現在如何使用 MapReduce 和 Hadoop 查詢 TB 的數據
- Yandex 架構
- YouTube 架構
- Skype 計劃 PostgreSQL 擴展到 10 億用戶
- 易趣建筑
- FaceStat 的禍根與智慧贏得了勝利
- Flickr 的聯合會:每天進行數十億次查詢
- EVE 在線架構
- Notify.me 體系結構-同步性
- Google 架構
- 第二人生架構-網格
- MySpace 體系結構
- 擴展 Digg 和其他 Web 應用程序
- Digg 建筑
- 在 Amazon EC2 中部署大規模基礎架構的六個經驗教訓
- Wolfram | Alpha 建筑
- 為什么 Facebook,Digg 和 Twitter 很難擴展?
- 全球范圍擴展的 10 個 eBay 秘密
- BuddyPoke 如何使用 Google App Engine 在 Facebook 上擴展
- 《 FarmVille》如何擴展以每月收獲 7500 萬玩家
- Twitter 計劃分析 1000 億條推文
- MySpace 如何與 100 萬個并發用戶一起測試其實時站點
- FarmVille 如何擴展-后續
- Justin.tv 的實時視頻廣播架構
- 策略:緩存 404 在服務器時間上節省了洋蔥 66%
- Poppen.de 建筑
- MocoSpace Architecture-一個月有 30 億個移動頁面瀏覽量
- Sify.com 體系結構-每秒 3900 個請求的門戶
- 每月將 Reddit 打造為 2.7 億頁面瀏覽量時汲取的 7 個教訓
- Playfish 的社交游戲架構-每月有 5000 萬用戶并且不斷增長
- 擴展 BBC iPlayer 的 6 種策略
- Facebook 的新實時消息系統:HBase 每月可存儲 135 億條消息
- Pinboard.in Architecture-付費玩以保持系統小巧
- BankSimple 迷你架構-使用下一代工具鏈
- Riak 的 Bitcask-用于快速鍵/值數據的日志結構哈希表
- Mollom 體系結構-每秒以 100 個請求殺死超過 3.73 億個垃圾郵件
- Wordnik-MongoDB 和 Scala 上每天有 1000 萬個 API 請求
- Node.js 成為堆棧的一部分了嗎? SimpleGeo 說是的。
- 堆棧溢出體系結構更新-現在每月有 9500 萬頁面瀏覽量
- Medialets 體系結構-擊敗艱巨的移動設備數據
- Facebook 的新實時分析系統:HBase 每天處理 200 億個事件
- Microsoft Stack 是否殺死了 MySpace?
- Viddler Architecture-每天嵌入 700 萬個和 1500 Req / Sec 高峰
- Facebook:用于擴展數十億條消息的示例規范架構
- Evernote Architecture-每天有 900 萬用戶和 1.5 億個請求
- TripAdvisor 的短
- TripAdvisor 架構-4,000 萬訪客,200M 動態頁面瀏覽,30TB 數據
- ATMCash 利用虛擬化實現安全性-不變性和還原
- Google+是使用您也可以使用的工具構建的:閉包,Java Servlet,JavaScript,BigTable,Colossus,快速周轉
- 新的文物建筑-每天收集 20 億多個指標
- Peecho Architecture-鞋帶上的可擴展性
- 標記式架構-擴展到 1 億用戶,1000 臺服務器和 50 億個頁面視圖
- 論文:Akamai 網絡-70 個國家/地區的 61,000 臺服務器,1,000 個網絡
- 策略:在 S3 或 GitHub 上運行可擴展,可用且廉價的靜態站點
- Pud 是反堆棧-Windows,CFML,Dropbox,Xeround,JungleDisk,ELB
- 用于擴展 Turntable.fm 和 Labmeeting 的數百萬用戶的 17 種技術
- StackExchange 體系結構更新-平穩運行,Amazon 4x 更昂貴
- DataSift 體系結構:每秒進行 120,000 條推文的實時數據挖掘
- Instagram 架構:1400 萬用戶,1 TB 的照片,數百個實例,數十種技術
- PlentyOfFish 更新-每月 60 億次瀏覽量和 320 億張圖片
- Etsy Saga:從筒倉到開心到一個月的瀏覽量達到數十億
- 數據范圍項目-6PB 存儲,500GBytes / sec 順序 IO,20M IOPS,130TFlops
- 99designs 的設計-數以千萬計的綜合瀏覽量
- Tumblr Architecture-150 億頁面瀏覽量一個月,比 Twitter 更難擴展
- Berkeley DB 體系結構-NoSQL 很酷之前的 NoSQL
- Pixable Architecture-每天對 2000 萬張照片進行爬網,分析和排名
- LinkedIn:使用 Databus 創建低延遲更改數據捕獲系統
- 在 30 分鐘內進行 7 年的 YouTube 可擴展性課程
- YouPorn-每天定位 2 億次觀看
- Instagram 架構更新:Instagram 有何新功能?
- 搜索技術剖析:blekko 的 NoSQL 數據庫
- Pinterest 體系結構更新-1800 萬訪問者,增長 10 倍,擁有 12 名員工,410 TB 數據
- 搜索技術剖析:使用組合器爬行
- iDoneThis-從頭開始擴展基于電子郵件的應用程序
- StubHub 體系結構:全球最大的票務市場背后的驚人復雜性
- FictionPress:在網絡上發布 600 萬本小說
- Cinchcast 體系結構-每天產生 1,500 小時的音頻
- 棱柱架構-使用社交網絡上的機器學習來弄清您應該在網絡上閱讀的內容
- 棱鏡更新:基于文檔和用戶的機器學習
- Zoosk-實時通信背后的工程
- WordPress.com 使用 NGINX 服務 70,000 req / sec 和超過 15 Gbit / sec 的流量
- 史詩般的 TripAdvisor 更新:為什么不在云上運行? 盛大的實驗
- UltraDNS 如何處理數十萬個區域和數千萬條記錄
- 更簡單,更便宜,更快:Playtomic 從.NET 遷移到 Node 和 Heroku
- Spanner-關于程序員使用 NoSQL 規模的 SQL 語義構建應用程序
- BigData 使用 Erlang,C 和 Lisp 對抗移動數據海嘯
- 分析數十億筆信用卡交易并在云中提供低延遲的見解
- MongoDB 和 GridFS 用于內部和內部數據中心數據復制
- 每天處理 1 億個像素-少量競爭會導致大規模問題
- DuckDuckGo 體系結構-每天進行 100 萬次深度搜索并不斷增長
- SongPop 在 GAE 上可擴展至 100 萬活躍用戶,表明 PaaS 未通過
- Iron.io 從 Ruby 遷移到 Go:減少了 28 臺服務器并避免了巨大的 Clusterf ** ks
- 可汗學院支票簿每月在 GAE 上擴展至 600 萬用戶
- 在破壞之前先檢查自己-鱷梨的建筑演進的 5 個早期階段
- 縮放 Pinterest-兩年內每月從 0 到十億的頁面瀏覽量
- Facebook 的網絡秘密
- 神話:埃里克·布魯爾(Eric Brewer)談銀行為什么不是堿-可用性就是收入
- 一千萬個并發連接的秘密-內核是問題,而不是解決方案
- GOV.UK-不是你父親的書庫
- 縮放郵箱-在 6 周內從 0 到 100 萬用戶,每天 1 億條消息
- 在 Yelp 上利用云計算-每月訪問量為 1.02 億,評論量為 3900 萬
- 每臺服務器將 PHP 擴展到 30,000 個并發用戶的 5 條 Rockin'Tips
- Twitter 的架構用于在 5 秒內處理 1.5 億活躍用戶,300K QPS,22 MB / S Firehose 以及發送推文
- Salesforce Architecture-他們每天如何處理 13 億筆交易
- 擴大流量的設計決策
- ESPN 的架構規模-每秒以 100,000 Duh Nuh Nuhs 運行
- 如何制作無限可擴展的關系數據庫管理系統(RDBMS)
- Bazaarvoice 的架構每月發展到 500M 唯一用戶
- HipChat 如何使用 ElasticSearch 和 Redis 存儲和索引數十億條消息
- NYTimes 架構:無頭,無主控,無單點故障
- 接下來的大型聲音如何使用 Hadoop 數據版本控制系統跟蹤萬億首歌曲的播放,喜歡和更多內容
- Google 如何備份 Internet 和數十億字節的其他數據
- 從 HackerEarth 用 Apache 擴展 Python 和 Django 的 13 個簡單技巧
- AOL.com 體系結構如何發展到 99.999%的可用性,每天 800 萬的訪問者和每秒 200,000 個請求
- Facebook 以 190 億美元的價格收購了 WhatsApp 體系結構
- 使用 AWS,Scala,Akka,Play,MongoDB 和 Elasticsearch 構建社交音樂服務
- 大,小,熱還是冷-條帶,Tapad,Etsy 和 Square 的健壯數據管道示例
- WhatsApp 如何每秒吸引近 5 億用戶,11,000 內核和 7,000 萬條消息
- Disqus 如何以每秒 165K 的消息和小于 0.2 秒的延遲進行實時處理
- 關于 Disqus 的更新:它仍然是實時的,但是 Go 摧毀了 Python
- 關于 Wayback 機器如何在銀河系中存儲比明星更多的頁面的簡短說明
- 在 PagerDuty 遷移到 EC2 中的 XtraDB 群集
- 擴展世界杯-Gambify 如何與 2 人組成的團隊一起運行大型移動投注應用程序
- 一點點:建立一個可處理每月 60 億次點擊的分布式系統的經驗教訓
- StackOverflow 更新:一個月有 5.6 億次網頁瀏覽,25 臺服務器,而這一切都與性能有關
- Tumblr:哈希處理每秒 23,000 個博客請求的方式
- 使用 HAProxy,PHP,Redis 和 MySQL 處理 10 億個請求的簡便方法來構建成長型啟動架構
- MixRadio 體系結構-兼顧各種服務
- Twitter 如何使用 Redis 進行擴展-105TB RAM,39MM QPS,10,000 多個實例
- 正確處理事情:通過即時重放查看集中式系統與分散式系統
- Instagram 提高了其應用程序的性能。 這是如何做。
- Clay.io 如何使用 AWS,Docker,HAProxy 和 Lots 建立其 10 倍架構
- 英雄聯盟如何將聊天擴大到 7000 萬玩家-需要很多小兵。
- Wix 的 Nifty Architecture 技巧-大規模構建發布平臺
- Aeron:我們真的需要另一個消息傳遞系統嗎?
- 機器:惠普基于憶阻器的新型數據中心規模計算機-一切仍在變化
- AWS 的驚人規模及其對云的未來意味著什么
- Vinted 體系結構:每天部署數百次,以保持繁忙的門戶穩定
- 將 Kim Kardashian 擴展到 1 億個頁面
- HappyPancake:建立簡單可擴展基金會的回顧
- 阿爾及利亞分布式搜索網絡的體系結構
- AppLovin:通過每天處理 300 億個請求向全球移動消費者進行營銷
- Swiftype 如何以及為何從 EC2 遷移到真實硬件
- 我們如何擴展 VividCortex 的后端系統
- Appknox 架構-從 AWS 切換到 Google Cloud
- 阿爾及利亞通往全球 API 的憤怒之路
- 阿爾及利亞通往全球 API 步驟的憤怒之路第 2 部分
- 為社交產品設計后端
- 阿爾及利亞通往全球 API 第 3 部分的憤怒之路
- Google 如何創造只有他們才能創造的驚人的數據中心網絡
- Autodesk 如何在 Mesos 上實施可擴展事件
- 構建全球分布式,關鍵任務應用程序:Trenches 部分的經驗教訓 1
- 構建全球分布式,關鍵任務應用程序:Trenches 第 2 部分的經驗教訓
- 需要物聯網嗎? 這是美國一家主要公用事業公司從 550 萬米以上收集電力數據的方式
- Uber 如何擴展其實時市場平臺
- 優步變得非常規:使用司機電話作為備份數據中心
- 在不到五分鐘的時間里,Facebook 如何告訴您的朋友您在災難中很安全
- Zappos 的網站與 Amazon 集成后凍結了兩年
- 為在現代時代構建可擴展的有狀態服務提供依據
- 細分:使用 Docker,ECS 和 Terraform 重建基礎架構
- 十年 IT 失敗的五個教訓
- Shopify 如何擴展以處理來自 Kanye West 和 Superbowl 的 Flash 銷售
- 整個 Netflix 堆棧的 360 度視圖
- Wistia 如何每小時處理數百萬個請求并處理豐富的視頻分析
- Google 和 eBay 關于構建微服務生態系統的深刻教訓
- 無服務器啟動-服務器崩潰!
- 在 Amazon AWS 上擴展至 1100 萬以上用戶的入門指南
- 為 David Guetta 建立無限可擴展的在線錄制活動
- Tinder:最大的推薦引擎之一如何決定您接下來會看到誰?
- 如何使用微服務建立財產管理系統集成
- Egnyte 體系結構:構建和擴展多 PB 分布式系統的經驗教訓
- Zapier 如何自動化數十億個工作流自動化任務的旅程
- Jeff Dean 在 Google 進行大規模深度學習
- 如今 Etsy 的架構是什么樣的?
- 我們如何在 Mail.Ru Cloud 中實現視頻播放器
- Twitter 如何每秒處理 3,000 張圖像
- 每天可處理數百萬個請求的圖像優化技術
- Facebook 如何向 80 萬同時觀看者直播
- Google 如何針對行星級基礎設施進行行星級工程設計?
- 為 Mail.Ru Group 的電子郵件服務實施反垃圾郵件的貓捉老鼠的故事,以及 Tarantool 與此相關的內容
- The Dollar Shave Club Architecture Unilever 以 10 億美元的價格被收購
- Uber 如何使用 Mesos 和 Cassandra 跨多個數據中心每秒管理一百萬個寫入
- 從將 Uber 擴展到 2000 名工程師,1000 個服務和 8000 個 Git 存儲庫獲得的經驗教訓
- QuickBooks 平臺
- 美國大選期間城市飛艇如何擴展到 25 億個通知
- Probot 的體系結構-我的 Slack 和 Messenger Bot 用于回答問題
- AdStage 從 Heroku 遷移到 AWS
- 為何將 Morningstar 遷移到云端:降低 97%的成本
- ButterCMS 體系結構:關鍵任務 API 每月可處理數百萬個請求
- Netflix:按下 Play 會發生什么?
- ipdata 如何以每月 150 美元的價格為來自 10 個無限擴展的全球端點的 2500 萬個 API 調用提供服務
- 每天為 1000 億個事件賦予意義-Teads 的 Analytics(分析)管道
- Auth0 體系結構:在多個云提供商和地區中運行
- 從裸機到 Kubernetes
- Egnyte Architecture:構建和擴展多 PB 內容平臺的經驗教訓
- 縮放原理
- TripleLift 如何建立 Adtech 數據管道每天處理數十億個事件
- Tinder:最大的推薦引擎之一如何決定您接下來會看到誰?
- 如何使用微服務建立財產管理系統集成
- Egnyte 體系結構:構建和擴展多 PB 分布式系統的經驗教訓
- Zapier 如何自動化數十億個工作流自動化任務的旅程
- Jeff Dean 在 Google 進行大規模深度學習
- 如今 Etsy 的架構是什么樣的?
- 我們如何在 Mail.Ru Cloud 中實現視頻播放器
- Twitter 如何每秒處理 3,000 張圖像
- 每天可處理數百萬個請求的圖像優化技術
- Facebook 如何向 80 萬同時觀看者直播
- Google 如何針對行星級基礎設施進行行星級工程設計?
- 為 Mail.Ru Group 的電子郵件服務實施反垃圾郵件的貓捉老鼠的故事,以及 Tarantool 與此相關的內容
- The Dollar Shave Club Architecture Unilever 以 10 億美元的價格被收購
- Uber 如何使用 Mesos 和 Cassandra 跨多個數據中心每秒管理一百萬個寫入
- 從將 Uber 擴展到 2000 名工程師,1000 個服務和 8000 個 Git 存儲庫獲得的經驗教訓
- QuickBooks 平臺
- 美國大選期間城市飛艇如何擴展到 25 億條通知
- Probot 的體系結構-我的 Slack 和 Messenger Bot 用于回答問題
- AdStage 從 Heroku 遷移到 AWS
- 為何將 Morningstar 遷移到云端:降低 97%的成本
- ButterCMS 體系結構:關鍵任務 API 每月可處理數百萬個請求
- Netflix:按下 Play 會發生什么?
- ipdata 如何以每月 150 美元的價格為來自 10 個無限擴展的全球端點的 2500 萬個 API 調用提供服務
- 每天為 1000 億個事件賦予意義-Teads 的 Analytics(分析)管道
- Auth0 體系結構:在多個云提供商和地區中運行
- 從裸機到 Kubernetes
- Egnyte Architecture:構建和擴展多 PB 內容平臺的經驗教訓