# 阿爾及利亞分布式搜索網絡的體系結構
> 原文: [http://highscalability.com/blog/2015/3/9/the-architecture-of-algolias-distributed-search-network.html](http://highscalability.com/blog/2015/3/9/the-architecture-of-algolias-distributed-search-network.html)

*[Julien Lemoine](https://www.linkedin.com/in/julienlemoine) 的共同發布者的 CTO [阿爾及利亞 ]](http://www.algolia.com/) ,開發人員友好的搜索即服務 API。*
Algolia 于 2012 年作為移動設備的離線搜索引擎 SDK 開始。 目前,我們還不知道在兩年內我們將建立一個全球分布式搜索網絡。
如今,阿爾戈利亞每月在全球 12 個地區提供超過 20 億個用戶生成的查詢,我們的平均服務器響應時間為 6.7 毫秒,其中 90%的查詢在不到 15 毫秒內得到答復。 我們的搜索不可用率低于 10 <sup>-6</sup> ,這表示每月少于 3 秒。
離線移動 SDK 面臨的挑戰是移動性質帶來的技術限制。 這些挑戰迫使我們在開發算法時會采取不同的思路,因為經典的服務器端方法無法正常工作。
從那時起,我們的產品有了很大的發展。 我們想分享我們在這些算法之上構建和擴展 REST API 的經驗。
**我們將說明我們如何使用分布式共識來實現全球不同地區的數據的高可用性和同步,以及如何通過任意播 DNS** 將查詢路由到最近的位置 。
# 數據大小誤解
在設計架構之前,我們首先必須確定我們需要支持的主要用例。 在考慮我們的擴展需求時尤其如此。 我們必須知道我們的客戶是否需要索引千兆字節,太字節或 PB 的數據。 架構會有所不同,具體取決于我們需要處理多少個用例。
當人們想到搜索時,大多數人會想到非常大的用例,例如 Google 的網頁索引或 Facebook 的數萬億帖子索引。 如果停下來想一想每天看到的搜索框,則大多數搜索框都不會搜索大型數據集。 **Netflix 搜索約 10,000 種圖書,亞馬遜在美國的數據庫包含約 200,000,000 種產品。 這兩種情況下的數據都可以存儲在單臺機器** **中!** 我們并不是說擁有一臺計算機是一個很好的設置,但是要記住所有數據都可以在一臺計算機上存儲是非常重要的,因為跨計算機同步是復雜性和性能損失的主要來源。
# 高可用性之路
構建 SaaS API 時,高可用性是一個大問題,因為消除所有單點故障(SPOF)極具挑戰性。 我們花了數周的時間為我們的服務集體討論理想的搜索架構,同時牢記我們的產品將面向面向用戶的搜索。
## 主從與主從
通過將問題暫時限制為存儲在單個計算機上的每個索引,我們將高可用性設置簡化為托管在不同數據中心的多臺計算機。 通過這種設置,我們想到的第一個解決方案是進行主從設置,其中一臺主機接收所有索引操作,然后將它們復制到一個或多個從機。 使用這種方法,我們可以輕松地在所有計算機之間負載均衡搜索查詢。
這種主從方法的問題在于我們的高可用性僅適用于搜索查詢。 所有索引操作都需要轉到主服務器。 對于服務公司來說,這種架構風險太大。 要做的只是使主服務器停機,這將發生,并且客戶端將開始出現索引錯誤。
**我們必須實現主-主架構** **!** 啟用主-主設置的關鍵要素是要在一組機器之間就單個結果達成一致。 我們需要在所有機器之間共享**知識,這些知識在所有情況下**都保持一致,即使機器之間存在網絡分離。
## 引入分布式一致性
對于搜索引擎,引入此共享知識的最佳方法之一是**將寫入操作視為必須按特定順序應用的唯一操作流**。 當我們有多個操作恰好同時出現時,我們需要為其分配一個序列 ID。 然后,可以使用該 ID 來確保將序列完全相同地應用于所有副本。
為了分配序列 ID(每個作業后一個數字遞增 1),我們需要在機器之間的下一個序列 ID 上具有共享的全局狀態。 [ZooKeeper](http://zookeeper.apache.org/) 開源軟件是針對集群中分布式知識的實際解決方案,我們最初開始按以下順序使用 ZooKeeper:
1. 當機器收到作業時,它將使用臨時名稱將作業復制到所有副本。
2. 然后,該機器將獲得分布式鎖。
3. 讀取 ZooKeeper 中的最后一個序列 ID,并發送命令以在所有機器上將臨時文件復制為序列 ID + 1。 這等效于兩階段提交。
4. 如果我們從計算機(定額)中獲得大多數肯定答案,則將序列 ID +1 保存在 Zookeeper 中。
5. 然后釋放分布式鎖。
6. 最后,將結果通知發送作業的客戶端。 如果有大多數提交,這將是成功的。
不幸的是,此順序不正確,因為如果獲取鎖的機器在步驟 3 和 4 之間崩潰或重新啟動,我們可能會以作業在某些機器上提交的狀態結束,這需要更復雜的順序。
ZooKeeper 通過 TCP 連接作為外部服務打包非常困難,并且需要使用較大的超時(默認超時設置為 4 秒,表示兩個滴答聲,每個滴答聲為 2 秒)。
因此,無論是硬件還是軟件,每個失敗事件都將在此超時時間內凍結整個系統。 這似乎是可以接受的,但在我們的案例中,我們想經常在生產中測試故障(例如 Netflix 的 Monkey 測試方法)。
## 木筏共識算法
大約在我們遇到這些問題的時候, [RAFT 共識算法](https://raftconsensus.github.io/) 已發布。 顯然,該算法非常適合我們的用例。 RAFT 的狀態機是我們的索引,日志是要執行的索引作業的列表。 我已經知道 PAXOS 協議,但是對它以及所有變體的理解不夠深刻,不足以使我自己有信心實施它。 另一方面,RAFT 更清晰。 如果可以完美地滿足我們的需求,即使當時沒有穩定的開源實現,我也有足夠的信心將其實現為我們架構的基礎。
實現共識算法最困難的部分是確保系統中沒有錯誤。 為了解決這個問題,我選擇了一種猴子測試方法,即在重新啟動之前使用睡眠方式隨機殺死進程。 為了進一步測試,我模擬了通過防火墻的網絡掉線和性能下降。 這種測試有助于我們發現許多錯誤。 一旦我們運行了幾天,沒有任何問題,我非常有信心實施正確。
## 在應用程序或文件系統級別復制嗎?
我們選擇將寫操作分配給所有計算機并在本地執行,而不是在文件系統上復制最終結果。 我們做出此選擇的原因有兩個:
* 更快。 索引在所有計算機上并行完成,比復制可能很大的二進制文件要快
* 它與多個區域兼容。 如果我們在建立索引后復制文件,則需要一個將重寫整個索引的過程。 這意味著我們可能要傳輸大量數據。 如果您需要將數據傳輸到世界各地(例如紐約到新加坡),則傳輸的數據量非常低。
每臺機器將以正確的順序接收所有寫操作作業,并獨立于其他機器盡快處理它們。 **這意味著確保所有機器處于相同狀態,但不必同時處于同一狀態** 。 這是因為更改可能不會在同一時間在所有計算機上提交。
## 一致性的妥協
在分布式計算中, [CAP 定理](http://en.wikipedia.org/wiki/CAP_theorem) 指出,分布式計算系統不可能同時提供以下三個功能:
* 一致性:所有節點同時看到相同的數據。
* 可用性:確保每個請求都收到有關成功還是失敗的響應。
* 分區容限:盡管任意消息丟失或系統部分出現故障,系統仍可繼續運行。
根據該定理,我們在一致性 上折衷了 **。 我們不保證所有節點都能在同一時間看到完全相同的數據,但是它們都將收到更新。 換句話說,在少數情況下,機器不同步。 實際上,這不是問題,因為當客戶執行寫操作時,我們將該作業應用于所有主機。** **在第一臺機器和最后一臺機器上的應用時間之間相距不到一秒鐘,因此最終用戶通常看不到它。 唯一可能的矛盾是上一次收到的更新是否已經應用,這與我們客戶的用例兼容。**
# 通用體系結構
## 集群的定義
為了擁有高可用性基礎結構,必須在機器之間擁有分布式共識,但是遺憾的是存在很大的缺陷。 **此共識需要機器** **之間進行多次往返,因此每秒可能達成共識的數量與不同機器**之間的延遲直接相關。 他們需要接近才能每秒獲得大量共識。 為了能夠支持多個區域而不犧牲可能的寫入操作的數量,這意味著我們需要有多個集群,每個集群將包含三臺充當完美副本的機器。
每個區域只有一個集群是達成共識所需的最低要求,但仍遠非完美:
* 我們無法使所有客戶都適合一臺機器。
* 我們擁有的客戶越多,每個唯一客戶每秒可以執行的寫操作數量就越少。 這是因為每秒的最大共識數是固定的。
為了解決此問題,我們決定在區域級別應用相同的概念: **每個區域將具有由三個計算機組成的幾個群集** 。 一個集群可以容納一個到幾個客戶,具體取決于他們擁有的數據大小。 這個概念與虛擬化在物理機上所做的事情很接近。 我們能夠將幾個客戶放在一個集群上,但一個客戶可以動態增長并更改其使用情況。 為此,我們需要開發和自動化以下過程:
* 如果群集中的數據太多或寫入操作數量過多,則將其遷移到另一群集。
* 如果查詢量太大,則將新計算機添加到群集。
* 如果數據量太大,則更改分片的數量或將一個客戶分散在多個群集中。
如果我們擁有這些流程,則不會將客戶永久分配給集群。 分配將根據其自身的使用以及集群的使用而變化。 這意味著我們需要一種將客戶分配給集群的方法。
## 將客戶分配給集群
管理此分配的標準方法是每個客戶擁有一個唯一的 DNS 條目。 這類似于 Amazon Cloudfront 的工作方式。 每個客戶都被分配一個格式為 customerID.cloudfront.net 的唯一 DNS 條目,然后可以根據該客戶針對不同的計算機集。
我們選擇了相同的方法。 **為每個客戶分配一個唯一的應用程序 ID,該 ID 鏈接到格式為 APPID.algolia.io 的 DNS 記錄**。 該 DNS 記錄以特定群集為目標,該群集中的所有計算機都是 DNS 記錄的一部分,因此可以通過 DNS 進行負載平衡。 我們還使用運行狀況檢查機制來檢測計算機故障,并將其從 DNS 解析中刪除。
即使 DNS 記錄上的 TTL 值非常低(TTL 是允許客戶端保留 DNS 答復的時間),運行狀況檢查機制仍不足以提供良好的 SLA。 問題在于主機可能會關閉,但用戶仍將主機保留在緩存中。 用戶將繼續向其發送查詢,直到緩存過期。 更糟糕的是,因為 TTL 并不是一門精確的科學。 在某些情況下,系統不遵守 TTL。 我們已經看到一些 DNS 服務器將一分鐘 TTL 轉換為 30 分鐘 TTL 的 DNS 記錄。
為了進一步提高高可用性并避免機器故障影響用戶,我們為每個客戶生成了另一組 DNS 記錄,格式為 APPID-1.algolia.io,APPID-2.algolia.io 和 APPID- 3.algolia.io。 這些 DNS 記錄的思想是允許我們的 API 客戶端在達到 TCP 連接超時(通常設置為一秒)時重試其他記錄。 我們的標準實現是對 DNS 記錄列表進行混洗,并按順序嘗試它們。
與我們的 API 客戶端中精心控制的重試和超時邏輯相結合,這被證明是比使用專門的負載平衡器更好,更便宜的解決方案。
后來,我們發現時髦的.IO TLD 并不是性能的理想選擇。 與.NET 相比,.IO 的任意播網絡中的 DNS 服務器更少,并且那里的服務器已經飽和。 這導致大量超時,從而減慢了名稱解析的速度。 此后,我們通過切換到 algolia.net 域解決了這些性能問題,同時通過繼續支持 algolia.io 來保持向后兼容性。
# 集群的可伸縮性如何?
我們選擇使用多個集群使我們能夠添加更多客戶,而不會因為集群之間的隔離而對現有客戶造成太大的風險。 但是我們仍然擔心需要解決的一個集群的可伸縮性。
群集可伸縮性中的第一個限制因素是由于共識而導致的每秒寫入操作數。 為了緩解這一因素,我們從共識的角度出發,在 API 中引入了批處理方法,該方法將一組寫操作封裝在一個操作中。 問題在于,某些客戶仍然不分批地執行寫操作,這可能會對群集的其他客戶的索引速度產生負面影響。
為了減少對性能的影響,我們對體系結構進行了兩項更改:
* 我們從共識的角度出發,通過在一個唯一的操作中自動聚合每個客戶的所有寫操作,從而在共識存在爭議時添加了批處理策略。 在實踐中,這意味著我們正在重新排列作業的順序,但不影響操作的語義。 例如,如果有 1,000 個待達成共識的作業,而 990 個來自一個客戶,則即使有其他客戶的作業交錯在一起,我們也會將 990 個寫入操作合并為一個。
* 我們添加了一個共識調度程序,該調度程序控制每秒為每個應用程序 ID 輸入共識的寫入操作數。 這避免了一個客戶能夠使用共識的所有帶寬。
在實施這些改進之前,**我們通過返回 429 HTTP 狀態代碼**嘗試了限速策略。 很快就很明顯,這對于我們的客戶來說太痛苦了,以至于不得不等待這種響應并實施重試策略。 如今,我們最大的客戶每天在三臺計算機的單個群集上執行超過 10 億次寫操作,平均每秒執行 11,500 次操作,突發次數超過 15 萬次。
第二個問題是找到最佳的硬件設置,并避免可能影響群集可伸縮性的任何潛在瓶頸(例如 CPU 或 I / O)。 從一開始,我們就選擇使用自己的裸機服務器,以完全控制我們的服務性能并避免浪費任何資源。 選擇正確的硬件被證明是一項艱巨的任務。
在 2012 年底,我們從一個小型設置開始,包括:Intel Xeon E3 1245v2、2 個 Intel RAID 320 系列,RAID 0 中的 120GB 和 32GB RAM。 該硬件價格合理,比云平臺更強大,使我們能夠在歐洲和美國東部啟動該服務。
此設置使我們能夠調整內核的 I / O 調度和虛擬內存,這對于我們利用所有可用的物理資源至關重要。 即使這樣,我們很快發現我們的限制是 RAM 和 I / O 的數量。 我們使用了大約 10GB 的 RAM 來建立索引,而僅剩下 20GB 的 RAM 用于緩存用于執行搜索查詢的文件。 我們的目標一直是在內存中存儲客戶索引,以便針對毫秒級的響應時間優化服務。 當前的硬件設置是為 20GB 的索引數據而設計的,該數據太小了。
首次設置后,我們嘗試了具有單插槽和雙插槽 CPU,128GB 和 256GB RAM 以及不同型號/大小的 SSD 的不同硬件機器。
我們終于找到了一臺包含 Intel Xeon E5 1650v2、128GB RAM 和 2x400GB Intel S3700 SSD 的機器的最佳設置。 SSD 的型號對于耐用性非常重要。 在找到可以在生產中使用多年的正確型號之前,我們燒掉了許多 SSD。
最后,我們構建的最終體系結構使我們僅需一個條件即可在所有領域進行良好的擴展:我們需要隨時擁有免費資源。 在 2015 年,要處理必須管理裸機服務器的痛苦似乎有些瘋狂,但是我們在為客戶提供的服務質量和價格方面所獲得的收益是值得的。 我們能夠提供一個完全打包的搜索引擎,該引擎可以復制到三個不同的位置(在內存索引中),并且在比 AWS 更高的位置上具有出色的性能!
# 操作復雜嗎?
## 限制進程數
**每臺機器僅包含三個進程** 。 第一個是 Nginx 服務器,其中所有查詢解釋代碼均作為模塊嵌入其中。 為了回答查詢,我們在內存中映射了索引文件并直接在 nginx worker 中執行查詢,而無需與其他進程或機器進行通信。 唯一的例外是,當客戶數據不適合一臺機器時,這種情況很少發生。
第二個過程是 Redis 鍵/值存儲,我們使用它來檢查速率和限制以及存儲每個應用程序 ID 的實時日志和計數器。 這些計數器用于構建我們的實時信息中心,當您連接到帳戶時可以查看。 這對于可視化您的最后一個 API 調用和調試很有用。
最后一個過程是構建器。 這是負責處理所有寫入操作的過程。 當 nginx 進程接收到寫操作時,它將操作轉發給構建器以執行共識。 它還負責構建索引,并包含許多監視代碼,用于檢查我們的服務中的錯誤,例如崩潰,索引編制緩慢,索引編制錯誤等。根據問題的嚴重性,SMS 通過 Twilio 的 API 報告某些錯誤 而其他則直接報告給 PagerDuty。 每次在生產中檢測到新問題且未報告時,我們確保將來添加一個新探針以監視此類錯誤。
## 易于部署
**此堆棧的簡單性使部署變得容易** 。 在部署任何代碼之前,我們應用一堆單元測試和非回歸測試。 一旦所有這些測試通過,我們便逐漸部署到集群。
我們的部署永遠不會影響生產,也不會對最終用戶可見。 同時,我們還希望以協商一致的方式產生主機故障,以便檢查一切是否按預期進行。 為了實現這兩個目標,我們獨立部署群集的每臺計算機,并應用以下過程:
1. 獲取新的 Nginx 和生成器二進制文件。
2. [正常重啟 nginx](http://nginx.org/en/docs/control.html#upgrade) Web 服務器,并使用新的二進制文件重新啟動 nginx,而不會丟失任何用戶查詢。
3. 殺死構建器并使用新的二進制文件將其啟動。 這會觸發每臺計算機部署 RAFT 失敗,從而使我們能夠確保故障轉移按預期進行。
操作系統的簡單性是我們體系結構的重要目標。 我們既不希望也不相信部署應該受到體系結構的限制。
## 實現良好的全球覆蓋范圍
服務正在變得越來越全球化。 僅在全球一個地區提供搜索查詢遠非最佳。 例如,在美國東部地區托管搜索將在可用性方面有很大不同,具體取決于用戶從何處進行搜索。 對于美國東部用戶來說,延遲時間將從幾毫秒到亞洲用戶的數百毫秒,這還不包括飽和的海外光纖的帶寬限制。
我們已經看到一些公司在搜索引擎之上使用 CDN 來解決這些問題。 最終,這給我們帶來了比價值更大的問題,因為使緩存無效是一場噩夢,并且僅提高了很少一部分頻繁執行的查詢的速度。 我們很清楚,為了解決這個問題,我們需要將索引復制到不同的區域,并將它們加載到內存中,以便有效地回答用戶查詢。
我們需要的是在現有群集復制之上的 **區域間復制** 。 副本可以存儲在一臺機器上,因為該副本僅用于搜索查詢。 所有寫操作仍將轉到客戶的原始群集。
**每個客戶都可以選擇他們希望擁有的一組數據中心** 作為復制對象,因此特定區域中的復制計算機可以從多個群集中接收數據,并且一個群集可以 將數據發送到多個副本。
此架構的實現是基于我們基于共識的操作流建模的。 在達成共識之后,每個集群都將其自己的寫操作流轉換為每個副本的版本,以確保用無操作作業替換與此副本無關的作業。 然后,此操作流作為一批操作發送到所有副本,以避免盡可能多的延遲。 一次發送作業將導致重復的往返次數過多。
在群集上,寫操作將保留在計算機上,直到所有復制對其進行確認為止。
DSN 的最后一部分是將最終用戶直接重定向到最近的位置。 為此,我們以 APPID-dsn.algolia.net 的形式添加了另一個 DNS 記錄,該記錄負責解決最接近的數據中心的問題。 我們首先使用了 Amazon 的 Route53 DNS 服務,但很快達到了極限。
* 基于延遲的路由僅限于 AWS 區域,并且我們有印度,香港,加拿大和俄羅斯等 AWS 未覆蓋的位置。
* 基于地理位置的路由非常糟糕。 您需要為每個國家/地區指定 DNS 解析度。 這是許多托管 DNS 提供商所采用的經典方法,但是對于我們而言,這將是一個噩夢,無法提供足夠的相關性。 例如,我們在美國有幾個數據中心。
經過大量基準測試和討論,出于以下幾個原因,我們決定使用 [NSOne](http://www.nsone.net) 。
* 對我們來說,他們的 Anycast 網絡非常出色,并且比 AWS 更好的平衡。 例如,他們在印度和非洲擁有 POP。
* 他們的濾波器邏輯非常好。 對于每個客戶,我們可以指定與其關聯的機器(包括復制機器)列表,并使用地理位置過濾器按距離對它們進行排序。 這樣我們就可以保持最好的狀態。
* 它們支持 EDNS 客戶端子網。 這對我們來說很重要,以便更具針對性。 我們使用最終用戶的 IP 而不是其 DNS 服務器的 IP 進行解析。
在性能方面,我們已經能夠在第二級達到全球范圍內的全球同步。 您可以在 [Product Hunt 的搜索](http://www.producthunt.com/) (托管在美國東部,美國西部,印度,澳大利亞和歐洲)或 [Hacker News 上進行嘗試。 搜索](https://hn.algolia.com/) (托管在美國東部,美國西部,印度和歐洲)。
## 結論
我們花費了大量時間來構建我們的分布式和可伸縮體系結構,并且遇到了許多不同的問題。 我希望本文能使您更??好地了解我們如何解決這些問題,并提供有關如何設計自己的服務的有用指南。
我看到越來越多的服務目前正面臨著與我們類似的問題,全世界的受眾都擁有多區域的基礎架構,但是卻擁有一些全球一致的信息,例如登錄名或內容。 為了獲得出色的用戶體驗,如今必須擁有多區域基礎架構。 例如,可以使用這種方法來分發在全球范圍內一致的只讀數據庫副本!
如果您有任何問題或意見,我將很樂意回答。
[在 HackerNews 上](https://news.ycombinator.com/item?id=11185713)
FWIW,Raft 和 Paxos 之間的主要區別在于,如果在故障轉移期間發生寫操作,則 Raft 保證數據丟失。 Paxos 直接將寫入與主選舉過程聯系在一起,以使寫入不會丟失。 兩者還可以在部分網絡故障的情況下鎖定到位; 根據具體實施情況,Raft 傾向于留在那里并接受數據一段時間。 因此,盡管 Raft 更簡單/更輕松,但這是因為它使您能夠以非常糟糕的方式破壞 Paxos 明智地處理的事情。
這篇文章將來會發表。 可能弄亂了一些提要閱讀器。
您是否考慮過使用 Kafka 在集群中實現“狀態機”復制?
我是作者,并回復評論:
以色列:RAFT 和 Paxos 的保證是相同的:當共識成功時,就可以保證沒有數據丟失。 您能否詳細說明為什么您認為并非如此?
凱恩:由于多個地區的部署,卡夫卡不是一個選擇。 我們需要對復制的序列 ID 分配進行更底層的控制
您在搜索引擎中使用什么技術?
@Jeyendran 如簡介中所述,這是我們自己的引擎,以低級 C ++開發,并作為模塊嵌入在 nginx 中。 由于以下幾個原因,我們不是基于像 lucene / sphinx 這樣的開源引擎:
-我們處理關聯性的方式非常不同,這意味著對現有引擎
進行了巨大的重構-在即時搜索中具有非常好的性能 用例(鍵入時進行搜索),我們具有不同的數據結構。 我將嘗試寫一篇博客文章來解釋我們所有的算法/數據結構差異
可能是我讀過的最好的文章!
我很高興看到其他人考慮了“三個進程”機制,并在 nginx 和其他進程之間使用了 mmap 文件。 和強大的)集群技術。
謝謝您的出色工作。
您提到過,在使用 RAFT 協議的一致性上存在折衷。 根據我的理解,RAFT 并沒有給出分區容限,因為每個狀態機都需要互相交談以復制狀態。 因此,這是 CAP 定理的 CA 系統,在這里我們可以最終保持一致。
我喜歡你的文章。 感謝分享 :))
嗯,是的,Raft 和 Paxos 都提供了類似的一致性保證。 甚至還有自動的正確性證明:https://github.com/uwplse/verdi/pull/16
該帖子說他們使用 Raft 來協調故障轉移,并且分別決定損害一致性,而不是他們使用 Raft 損害了的一致性*。 您可以維護有關某些事物(例如,當前哪個節點是主節點)的始終一致的信息,而不能維護其他事物(例如,您正在服務的索引的實際內容)。*
也許 Raft 不一致的想法來自對 https://aphyr.com/posts/316-jepsen-etcd-and-consul 的誤解,(正確地)它說 Raft 的兩個廣泛使用的實現缺少了使 讀取速度較慢,但??有必要避免以下情況:1)您在分區的少數一方 2)先前的主機太 3)選出新的主機,并且有人在第一秒內向其中寫入新數據,或者 因此,4)您在寫完之后閱讀。
兩種系統最終都提供了沒有異常的模式,這是由于 Raft 的實現不完整所致,而不是 Raft 本身的缺陷。
非常感謝您的帖子。 我學到了很多。
- 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 內容平臺的經驗教訓