HipChat 十億級檢索和儲存架構曝光

pythontab發表於2014-01-17

本文來自Zuhaib Siddique的一次專訪,Zuhaib是群聊IM製造商HipChat的生產工程師,下面我們一起看Tod Hoff的整理。

以下為譯文:

如果從企業應用的生存率來看,選擇企業團隊資訊作為主要業務,HipChat的起點絕非主流;但是如果從賺錢的角度上看,企業市場的高收益確實值得任何公司追逐,這也正是像JIRA和Confluence這樣的智慧工具製造商Atlassian於2012年收購HipChat的原因。

同時,或許你不知道的是,在Atlassian資源和人脈的幫助下,HipChat已經進入了一個指數增長週期。12億的資訊儲存意味著他們現在每隔幾個月的資訊傳送、儲存和索引量都會翻一番。

如此快速的增長給曾經充足的基礎設施帶來了很大的壓力,HipChat給我們展示了一個通用的擴充套件思路。從簡單開始,經歷流量高峰,然後思考現在怎麼辦?使用更大的計算機通常是第一個和最好的答案,他們也是這樣做的。這給了他們一些喘息空間去考慮下一步怎麼做。在AWS上,在某一個拐點之後,你開始走向雲特性,也就是橫向擴充套件,這就是HipChat所做的事情。

然而HipChat的發展也並未是順風順水,安全性的擔憂推動了HipChat的雲(SaaS)版本之外內部部署版本的發展。

即使HipChat沒有谷歌那麼大規模,我們仍能從中學到好東西,比如他們如何及時索引和搜尋十億資訊,這也是IRC之類和HipChat之間的關鍵區別。在負載下索引和儲存資訊,丟失資訊是一個艱鉅的挑戰。

這是HipChat選擇的路,我們一起展開……

統計

  • 每秒60條訊息

  • 12億文件儲存

  • 4TB的EBS RAID

  • 在AWS上8個ElasticSearch伺服器

  • 26個前端代理伺服器,是後端應用伺服器的一倍

  • 18個人

  • 0.5TB的搜尋資料

平臺

  • 主機:AWS EC2 East上的75個例項全部使用Ubuntu 12.04 LTS 

  • 資料庫:目前用於聊天記錄的CouchDB,過渡到ElasticSearch。MySQL-RDS用於其它的一切

  • 快取:Redis

  • 搜尋:ElasticSearch

  • 佇列/Worker 伺服器:Gearman(佇列),Curler(Worker)

  • 語言:Twisted Python(XMPP Server)和PHP(Web前端)

  • 系統配置:開源Chef+Fabric

  • 程式碼部署:Capistrano

  • 監控:Sensu和monit將警告抽送至Pagerduty

  • 圖:statsd + Graphite

產品

  • 流量突發。在週末和假期將是安靜的。在高峰負荷期間每秒有幾百個請求。實際上佔用大部分流量的並不是聊天資訊,而是狀態資訊(away、idle、available),人們連線/斷開等。因此每秒60條訊息似乎很少,但是它只是一個平均水平。

  • 通知中心HipChat,在這裡與團隊合作,並得到來自工具和其他系統的所有資訊。有助於使每個人都在訊息圈內,特別是遠端辦公。

  • 使用HipChat而不是IRC之類,很大的原因是HipChat儲存和索引每一次對話,以便你以後搜尋它們。強調搜尋,這個特性的好處是你可以在任何時候做回溯,瞭解發生了什麼和同意了什麼。如果在傳送一條資訊時,你的裝置無法訪問,它也會將訊息路由到同一個使用者的多臺裝置中,並做臨時訊息快取/重試。

  • 更多的使用者帶來更快的增長,他們在各個方面使用產品而帶來的更多預定,也可以從他們的API整合中看到增長。

  • 儲存和搜尋資訊是系統中主要的可擴充套件性瓶頸。

  • HipChat使用XMPP協議,因此任何XMPP客戶端都可以連線到系統中,這點非常有利於採用。他們已經建立了自己的本地客戶端(Window、Linux、Mac、iOS、Android),並帶有類似PDF瀏覽、自定義表情符號、自動使用者註冊等擴充套件。

  • 在以前,將Wiki這樣的工具引入到企業文化是幾乎不可能的。現在,企業級的工具多已在企業落腳,這是為什麼?

  • 基於文字通訊已被廣泛接受。我們有簡訊、IM和Skype的形式,所以現在使用聊天工具是自然的事情。

  • 異地工作模式的崛起。團隊越來越分散,我們不能只是坐在一起進行一個講座,一切文件化的需要意味著組織通訊將有一筆巨大的財富。

  • 增強的功能。把像內嵌圖片、GIF動畫等功能做得生動有趣,會吸引更廣泛的群體。

  • HipChat有一個API,這使得它可以編寫類似IRC bots這樣的工具。例如使用Bitbucket提交——在10:08開發者X提交一些程式碼來修復一個漏洞。程式碼傳送透過HipChat直接連線到程式碼提交和提交日誌,完全的自動化。Bitbucket提交會擊中一個web hook,並使用一個addons來張貼資訊。Addons幫助編寫bots,轉入你的Bitbucket賬戶。比如我有我的API令牌,我想在每次提交發生時張貼到這個API上,工作原理類似GitHub。

  • 在客戶端Adobe Air啟動時,記憶體洩露會導致當機,因此將其移動到本地應用上。這是個麻煩,也是機遇。同一個公司中都存在許多跨平臺跨部門的使用者,你需要站在使用者的角度思考。希望使用者在所有的系統中都有很好的體驗,使用者不僅僅是技術人員。

XMPP伺服器架構

  • HipChat是基於XMPP協議的,XMPP節裡的內容就是訊息,可能是一行文字或者日誌輸出的長段等等。他們不想談論自己的XMPP架構,所以沒有很多的細節。

  • 他們沒有使用第三方的XMPP伺服器,而是利用Twisted Python和XMPP庫建立了自己的伺服器。這使得可以建立一個可擴充套件的後端、使用者管理,並輕鬆的新增功能而不用在其它程式碼庫上修改。

  • AWS上的RDS用於使用者身份驗證和其它使用事務及SQL的地方。這是一個穩定、成熟的技術。對於內部部署的產品,則使用MariaDB。

  • Redis用於快取。資訊,如哪些使用者在哪些房間,狀態資訊,誰線上等都是資訊。所以,你連線的是哪個XMPP伺服器並不重要,XMPP伺服器本身並不是一個限制。

  • 痛點是Redis(還)沒有叢集,因此使用了高可用性的hot/cold模式,所以,一個從屬節點已經準備就緒。故障轉移從主節點到從屬節點大概需要7分鐘,從屬節點的釋出是手動的,不是自動的。

  • 提高負載可以發現代理伺服器中的弱點所在,也可以清楚能支撐多少個客戶端。

  • 這是一個真正的問題,正如不丟失資訊是一個很大的優勢。顯而易見,不丟失資訊比低延遲更重要——使用者更願意晚點接收資訊,而不是根本沒有資訊。

  • 使用6個XMPP伺服器系統運作良好,然而隨著連線點的增加,他們開始看到不可接受的延遲。連線不僅來自客戶端,還來自bots支援他們的程式設計介面。

  • 在第一遍的時候,他們分離出前端伺服器和應用伺服器。代理伺服器處理連線,後端應用程式處理的stanza。前端伺服器數量由有效收聽客戶數量驅動,而不是由資訊傳送數量驅動。保持那麼多的連線開啟,同時提供及時的服務是一個挑戰。

  • 修復資料儲存問題之後的計劃是調查如何最佳化連線管理。Twisted的效果很好,但是他們有很多的連線,所以必須弄清楚如何更好地處理這些連線。

儲存架構

  • 向HipChat傳送的訊息已達10億條,同時還在不停增長,他們將CouchDB和Lucene對儲存和搜尋資訊的解決方案推向極限。

  • 認為Redis將會是故障點,而Couch/Lucene會足夠好。沒有做合適的容量計劃和檢視資訊增長率。增長速度比他們想象的更快,不應該集中那麼多精力在Redis上,而應該專注於資料儲存。

  • 當時他們相信透過增加容量來擴充套件,向上移動到越來越大的亞馬遜例項。他們發現一點,隨著不斷地增長,他們利用這種方法只能再工作兩個月。所以,他們不得不採用其他的辦法。

  • Couch/Lucene超過一年沒有更新,它不能做分類。這是採用其他辦法的另一個原因。

  • 在亞馬遜上大約10億訊息的一半是一個臨界點。用一個專用的伺服器和200G的RAM,他們之前的架構可能仍能工作,但在有限資源的雲上就不能工作了。

  • 他們想留在亞馬遜。

  • 喜歡AWS的靈活性,效能的新增只需要透過租用例項完成。

  • 亞馬遜的片狀。不要把你所有的雞蛋都放到一個籃子裡,如果一個節點出現故障,你必須要處理它,否則一些使用者將會失去流量。

  • 使用動態模型。可以快速關閉一個例項,並帶來新的例項。雲原生型別的東西。可以隨時關閉節點。關閉一個Redis主節點,可以在5分鐘內恢復。目前美國東岸分割4個可用地區,但是還沒有多區域。

  • EBS只讓你擁有1TB的資料。在遇到之前,他們並不知道這個限制。使用Couch時他們遇到了EBS磁碟大小限制。HipChat的資料是0.5TB。為了壓縮,Couch必須將資料複製到有雙倍容量的壓縮檔案中。2TB的RAID在週末壓縮過程中遇到了限制,不想使用RAID解決方案。

  • 不選擇亞馬遜的DynamoDB,因為他們建立了一個HipChat伺服器,在防火牆後面的託管服務。

  • HipChat伺服器驅動技術堆疊的決定。私人版是建立在自己主機上的解決方案。某些客戶不能使用雲/SaaS解決方案,比如銀行和金融機構,國家安全域性已經嚇壞了國際客戶,因此聘請了兩名工程師建立產品的安裝版本。

  • Redis叢集可以自託管,也可以像ElasticSearch那樣工作在AWS上。在內部部署版本中他們使用MariaDB,而不是RDS。

  • 不能考慮一個完整的SaaS解決方案,因為那會是一個鎖定。

  • 現在過渡到ElasticSearch

  • 移動到ElasticSearch作為他們的儲存和搜尋後端,因為它可以儲存他們的所有資料,它是高度可用的,它可以透過簡單增加更多的節進行擴充套件,它是多使用者的,它可以透過分割槽和複製透明的處理節點損失,並且它建立在Lucene之上。

  • 並不真的需要一個MapReduce功能。看著BigCouch和Riak的搜尋(表現一般),但ES在GET上的表現是相當不錯的。喜歡壞了就扔,省去了故障檢測。 ES HA已令他們在系統的堅固性上感到非常有信心。

  • Lucene的相容是一個巨大的勝利,因為所有的查詢都已經相容Lucene,因此它是一個自然的遷移路徑。

  • 客戶資料是相當多樣的,從聊天記錄到影像響應型別的差別也隨處可見,他們需要能夠快速地直接從12億文件中查詢資料。

  • 此舉正變得越來越普遍,HipChat也使用ElasticSearch作為他們的key-value儲存,減少需要資料庫系統的數量,從而降低整體的複雜性。既然效能和響應時間都不錯,那完全沒有不用的理由。 10ms到100ms的響應時間。在沒有任何快取的情況下,某些領域仍然超過Couch。那為什麼還要用多個工具?

  • 使用ES,一個節點故障不會引起任何人的注意。在它再平衡時你會得到CPU使用率過高的警報,但是系統仍然執行。

  • 用8個ES去處理流量的增長。

  • 基於Java的產品JVM調整可能非常棘手。

  • 要使用ES,必須有堆空間容量計劃。

  • 測試快取。ES可以快取過濾結果,這是非常快速的,但是你需要很大的堆空間。雖然8個主機擁有22G的記憶體,但還會隨著快取的開啟被耗盡。所以如果不需要就關閉快取。

  • 快取有問題,因為它會遇到記憶體不足的錯誤然後失敗。叢集會在幾分鐘內恢復,只有少數使用者會注意到這個問題。

  • 因為網路的不可靠,Amazon的故障轉移也可能存在問題。在叢集中可能會引起錯誤的選舉發生。

  • 使用ElasticSearch會遇到這些問題。原本有6個ES節點作為主節點選舉執行,一個節點可能會耗盡記憶體或者遇到一個GC暫停並在網路中丟失。那麼其他人就不會看到這個主節點,進行選舉,並宣佈自己是主節點。他們選舉架構中的缺陷是他們不需要法定人數。因此就會出現Split Brain問題,從而引起很多問題。

  • 解決方案是在專用的節點上執行ElasticSearch主節點,那麼需要做的事情就是成為主節點,從而避免了後續問題。主節點處理分片的分配是完成,誰是主要的,並且完成複製分片分佈圖。實現再平衡要容易的多,因為主節點可以效能優良的處理所有的再平衡。可以查詢任何節點,並會做內部路由。

  • 使用月索引,每個月是一個單獨的索引。每個初級索引有8個分片,然後有兩個副本。如果一個節點丟失,系統仍能工作。

  • 不要把RDS移動到ES中。需要使用SQL的資料一般儲存在RDS/MariaDB中,典型的是使用者管理資料。

  • 在Redis叢集被釋放之前,Redis中大量的快取是主/從設定。有一個Redis統計伺服器,處於離線狀態。Redis歷史快取的最後75條訊息,用於防止在第一次載入對話時不間斷的訪問資料庫。也有內部狀態或快速資料的狀態,比如登入使用者數量。

常規

  • Gearman用於非同步工作,比如iOS的推送和傳遞電子郵件。

  • AWS West用於災難恢復,一切都會備份到AWS West。

  • Chef用於所有配置。ElasticSearch有一個很好的Chef手冊,輕鬆上手。像Chef,因為你可以開始寫Ruby程式碼而不是使用Puppet風格的DSL,它也有一個很好的活躍的社群。

  • 收購經驗。他們現在已經進入公司的核心資產和人才,但Atlassian不干擾工作,之所以相信,是有原因的。可以在內部要求,例如,如何擴大ElasticSearch ,當別人在Atlassian需要幫助時,他們可以加入幫忙的隊伍。良好的整體體驗。

  • 扁平的團隊結構。仍然是一個小團隊,目前大約有18人。兩個人在DEVOPS,少數平臺,IOS、Android的開發人員在伺服器端,一個Web開發工程師(在法國)。

  • Capistrano用於部署所有的主機。

  • Sensu用於監控應用程式。讓你無需監視堆空間ElasticSearch節點,然後在沒有任何通知的情況下解決OOM問題。目前堆的使用率為75%,這正是他們想要的狀態。

  • Bamboo用於持續整合。

  • 客戶端版本還不正規,開發者驅動,有一個臨時區域進行測試。

  • 集團標誌。可以控制哪些群體得到了一個功能、測試特效能及緩慢釋放特性,除此之外還能幫助控制主機的負載。

  • 功能標誌。有利於ElasticSearch部署過程中的保護。例如,如果他們發現一個漏洞,他們可以關閉一個功能,並回去找Couch。使用者不會注意到差別。在Couch和ElasticSearch之間的過渡階段,他們都有應用複製到兩個儲存。

  • 新的API版本將使用Oauth,因此,開發人員可以使用HipChat API在自己的伺服器上部署。有客戶使用自己的伺服器是一個更具擴充套件性的模式。

未來

  • 未來幾個月將會達到20億條訊息,估計ElasticSearch可以處理大約20億條訊息。不確定如何處理負載的預期增長。預計要到Amazon West以獲得資料心更多的的可用性和可能在不同的資料中心投入更多的使用者。

  • AWS自動擴充套件能力

  • 移動到語音,私人一對一影片、音訊聊天、基本的會議

  • 將來可能使用RabbitMQ來傳遞訊息

  • 與Confluence更大的整合。使用HipChat聊天,然後使用Confluence頁面來捕捉細節。

經驗教訓

1. 企業應用程式是搖錢樹。賣入一個企業是很痛苦的,銷售週期長意味著太多的不確定性。但是如果你成功賣出,那就會獲得豐厚的利潤,所以你應該考慮企業市場。時代在變,企業卻可能是滯後的,但是他們仍然採用新工具和新的做事方式,這其中就有機會。

2. 隱私在產品給企業推銷時變得越來越重要,它會直接影響到產品的選擇與否。HipChat正在做他們產品的備用版本,以使那些不相信公共網路的客戶滿意。對於一個程式設計師來說,雲作為一個平臺非常有意義。對於一個企業來說,雲可以是魔鬼。這意味著你必須做出靈活的技術堆疊選擇。如果你在服務上100%依靠AWS,那你的系統移動到另一個資料中心將變得幾乎不可能。這對Netfix也許並不重要,但是如果你想賣入企業市場,它就很重要了。

3. 縱向擴充套件以獲得喘息的空間。當你等待弄清楚架構中下一步要做什麼的時候,可以花很少的錢去縱向擴充套件,給自己幾個月的喘息之機。

4. 選擇不會失敗的。HipChat做出了不會丟失使用者聊天記錄優先順序,所以他們的架構將這個優先順序反映給儲存聊天記錄到磁碟,在宕掉後系統恢復時會重新載入。

5. 進入本地。你的客戶在許多不同的平臺上,一個本地的應用將會提供最好的體驗。對於一個初創公司,那是很多的資源,太多了。所以,賣給擁有更多資源的公司在某種程度上是說得通的,這樣你可以建立更好的產品。

6. 功能和群組標誌做出更好地釋出慣例。如果你可以選擇哪些組看到一個功能,如果你能在生產和測試中關閉功能,那麼你就不用擔心釋出新的構建專案了。

7. 選擇你真正自信的技術。ElasticSearch應對增長的橫向擴充套件能力讓HipChat很放心,同樣也會有一個很好的使用者體驗,這才是最重要的。

8. 成為該流程的一部分,你變得更有價值,難以消除。HipChat作為人和工具之間的天然契合點,也是來編寫實現各種有用工作流bots的天然點。這使得HipChat在企業中有發揮的平臺,它使本來不可建造的功能得以實現。如果你能做到同樣的事情,那麼大家都會很需要你。

9. AWS需要在匯流排上存在一個單獨的節點,這個要求看起來有點荒謬,但是在雲環境下卻非常重要,因為機器可用資訊在第三方目的源中並不可見。如果著眼機架就會發現它經常有一個單獨存在的匯流排插槽,如果其他插槽可用,他就會知道。這樣,你就不必去猜測。在雲中,軟體採用基於原始TCP的連線技術和心跳,去猜測另一個節點是否發生故障,從而導致Split Brain問題及啟用備庫時產生資料丟失。這需要時間去演變,到達完全可靠還需要邁一大步。

10. 產品決策驅動堆疊的決定,HipChat伺服器驅動技術堆疊的決定:Redis叢集可以自託管;不選擇亞馬遜的DynamoDB,是因為HipChat在防火牆的後面建立一個託管服務。

11. 你需要開啟視野。你需要容量規劃,即使是在雲中。除非你的架構從一開始就完全是原生雲,否則任何架構都會有負荷的拐點,在拐點他們的架構將不再能夠處理負載。看看增長速度,專案出來了。會打破什麼?你將會做什麼?而且不要再犯同樣的錯誤。HipChat將如何處理40億條訊息?當下還無法知曉。

12. 瞭解系統的限制。EBS有1TB的儲存限制,這是很大的限制,但如果你的儲存已接近那個限制,就需要有一個計劃了。同樣,如果你的資料庫,例如Couch,在壓縮階段要使用雙倍的磁碟空間,那將會影響你的系統限制。

13. 這個世界會令你大吃一驚。六個月前HipChat認為Redis將會是最弱的環節,但現在它依舊很強壯,而Couch和EBS才是最薄弱的環節。


相關文章