1. 程式人生 > >Twitter 千萬 QPS 分散式系統的架構設計和高效運維

Twitter 千萬 QPS 分散式系統的架構設計和高效運維

個人簡介

王亞雷

清華本科,美國德州大學奧斯汀分校碩士。十多年從事網際網路服務平臺,分散式計算和資料儲存的開發和技術管理工作。先後任職微軟總部、eBay 和 Twitter 總部。

我一直從事後臺的海量分散式的資料儲存系統的設計、研發及運維。早期在微軟,剛開始的時候在 SQL Server;後來轉到微軟的 Online Service Division (OSD)。

在 OSD 研發分散式的 In-Memory 資料庫,主要是支撐微軟的整個數字廣告系統。這個系統的要求很高;5毫秒響應時間,單機的 QPS 要達十萬以上。後來去了 Twitter,主要充實 Twitter 的分散式 Key-Value 資料庫的研發、運維。

一、形形色色的資料庫

Twitter 整體儲存架構有如下四套系統:

1、NoSql,主要包括使用者資訊、比較小的數字;當時大約有三萬多節點。

2.、大檔案系統,主要是儲存圖片、video 等大資料檔案。與 NoSql 同樣,也有三萬多個節點。

3.、Hadoop 系統,主要用於後臺資料處理、分析;最多的時候有九千個節點左右。

4.、MySQL,簡單、比較複雜的關係性資料查詢

各種資料庫的 CAP

說到資料庫,不得不說的就是 CAP。CAP 是什麼呢?C就是一致性。A是可用性。P就是分割槽容錯性。

Eric Brewer 證明了在 CAP 三個訴求中,你只能滿足兩個;永遠做不到三個。所以你做資料庫設計的時候就要考慮應用場景是什麼;犧牲那個特性來取得另一外兩個特性。

事實上所有的資料庫,包括現在新興的資料庫都遵從這個 CAP 原則。它們針對某個應用場景做優化,沒有一個大而統什麼都能用的系統。

下面是不同型別資料庫對 CAP 的抉擇:

資料庫

  1. 關係型資料庫,主要應用於交易系統;例如銀行系統。因此它是強一致性的;放棄了A。
  2. NoSql 的好處在於它的高併發,能夠支撐很高的併發數;但是一致性稍差,是最終一致的。

  1. NewSQL, 如 google 的 spanner 號稱能夠同時滿足 CAP 三個;實際上是採取了一些措施來增強網路的穩定性,把網路出現 partition 的可能性降低很低。但是理論上還是 不能突破 CAP。
  2. 特殊用途的資料庫;例如時間序列型的 OpenTSDB,文件型的 mongoDB 以及圖資料庫 Neo4j 等。

二、Manhattan 的前世今生

Cassandra

Twitter 最早用的是 Cassandra。早期 cassandra 沒有虛擬節點導致不能部分的擴容;現在的 Cassandra 已經可以了。

第二個就是 Cassandra 用的是 gossip 協議。在實際應用中,當叢集變來較大時,如達到幾百個節點,gossip 協議不能夠有效的讓分散式系統保持一致性,存在一定程度不一致的問題。

 manhattan

在以上問題的驅動下,twitter 研發了自己的 NoSql 也就是 manhattan 系統。manhattan 設計實現主要關注的要素如下:

  • 可靠性;
  • 可用性;
  • 可操作性;
  • 低延時;
  • 高效;

manhattan 分散式實時海量資料庫目前有三萬多個節點,每個節點可以支撐上萬 QPS;P99延時為10毫秒。

三、Manhattan 設計之儲存引擎

首先,做一個 One Size Fit All 系統是肯定不可能的。所以我們當時特意做了模組化設計;後面的儲存結點和儲存引擎是可以接插的,可以根據不同的需求來定製資料系統。

因此,我們的後臺有下面三類常見資料引擎和一些專門用途的引擎。

常見資料引擎

  • SeaDB 是隻讀優化。因為我們有很多使用者;尤其是廣告客戶,他們是定期往上面更新資料的。這個時候很適合做批量更新,但是前端是隻讀的。
  • SSTable 針對寫優化的儲存引擎。與 google 的 bigtable 機制是類似的,它對寫是非常高效的。
  • RMDBS 傳統的關係資料庫系統。有很多使用者是同時讀寫的,同時對讀是很在意的。此時 RMDBS 是可以進行 index 又可以實時的 update。

專門用途的引擎主要是從以下三個方面進行優化的措施:

  • 強一致性;
  • 時間序列服務;
  • 二級索引;

四、Manhattan 設計之架構

Manhattan 整體架構分為四部分;分別是排程、讀、寫以及一致性協調。

  • Cordinator 排程模組,它的主要功能是對請求打包,然後根據不同 key 將其分散到不同的後臺節點上;最終將節點的響應重新組裝返回給請求方。

    這些不是在 Coordinator 排程模組裡面,是在後端儲存模組裡面。bloom filter 可以快速排除分散式的表裡面不存在某個值。從而極大地提高查詢效率。

  • 讀請求,對於 SSTable 這種架構的儲存;讀的代價時非常高的。因為它要讀很多很多 SSTable。

    當然我們有很多措施可以對其進行優化。第一就是定期將小的合併成大的 SSTable。第二我們有兩級索引;一級駐記憶體,另外一級在磁碟中,第三是使用 Bloom filter,這樣能保證我們的加速。

  • 寫過程實際上是直接寫到記憶體裡的,commitlog 是非常快的;所以寫的效率很高,基本上可以看作是寫到記憶體裡的。
  • Reconciliation 就是最終把所有寫入的資料複製;通過這種 job 對它進行傳播保證它有同樣的資料。

    同時,reconciliation 有個定期的工作就是掃所有的檔案;然後把檔案的不一致進行整合達到最終一致性。

五、海量系統高效運維實戰

Twitter

Twitter 資料量非常大;大家都知道這個請求是有叫做放大特性的。例如前端要呼叫一個,後端可能有幾百個呼叫。我們最大的叢集每秒有兩三千萬請求,線上有十幾個這樣的叢集;所以運維這樣的系統非常痛苦。

曾經有個很極端的例子,有一個 SRE 經過一段時間煎熬,白天突然在辦公室昏倒。後來我們在運維方面做了成功地改進,引入 DevOps。DevOps 實際上指的是分別從組織架構、流程、工具三個方面來提高系統運營的效率

海量運維-組織架構

大家可能知道,常見的情況是研發寫了 code,結果運維出問題了。程式碼也不知道幹什麼的,半夜三更被叫起來,氣得要死;然後找研發。研發說你這個都不懂還來當運維。於是無法調和的矛盾就這樣產生了。

所以靠人是不行的;最有效的是組織架構,有了這個所有的問題引刃而解。為什麼這麼說?研發參與運維和運維全部打成一塊。這時候你寫個爛程式碼,你半夜三更被叫起來。或者你寫了一個不必要的報警,你的同事被叫起來,第二天是要被臭罵一頓的。

在專案交付流程中,運維在專案早期一定要參與研發設計。研發的設計是必須要經過運維 signoff;運維不 signoff,研發的設計不能算完成。

研發在設計之中有兩個比較的重要的 work items 必須要有。第一個是運維指標。

第二個就是告警,這些都是 要通過大家討論的。服務上線交給運維之前,運維操作手冊是必須要完成的,一定要有服務或者功能模組很完整的操作手冊。

最後在上線之前有個預上線的會議,基本上研發線、運維線的各個部門包括安全都要了解產品或功能上線的方方面面並 sign off。

上線後,研發專案組必須自己運維自己的功能模組一個月。通過一個月的產品磨合,最後再進行培訓和交割。東西要交給大家做的時候,必須要有一個面向所有研發和運維的培訓流程。

海量運維-流程

所有人都需要上崗運維,但是需要一個很好的流程。首先培訓,新人來了以後;老人開一到三次的講座,介紹產品,介紹運維經驗。

然後就是所謂的 Shadow Others,當資深運維在處理問題時你在他旁邊看著,記錄、重複他所做的所有操作活動。

下一步就是 Shadow by Others,在這個階段,由你來處理所有的問題,有資深的運維同事做後備。所有這些都通過了,你就可以獨立上崗了。

海量運維-工具

具備了正確的組織架構和有效的流程後,Devops 的第三個支柱是方便易用的運維工具。這些是以運維推動,運維和研發共同實現的工具。我們有幾個工具幫助我們極大的降低了運維的成本。

Self Service

  • Self Service,以前運維的服務80%是內部團隊的;有很多內部服務我們花了很長時間在上面。所以我們設計了一個 Self Service UI,極大的降低了溝通成本。

    只有10%很特殊的服務或者很重要的服務,我們會跟他們溝通處理。這裡面有個很重要的功能是除錯工具。因為大家服務上線了,有了除錯工具的 UI 就非常方便了,高亮批註讀寫一個 Key-Value 非常方便。

  • 部署,需要各種不同的環境,測試環境、生產環境等。對於資料服務來說,需要注意 canary 兩個節點不能在一個 replication set 上。

    部署的回滾能力特別重要。凡是不涉及到任何資料格式變化的變動一般來說都沒有什麼大問題。但是,一旦涉及到資料尤其是資料的格式的改動就要非常小心;資料格式變動後就沒有辦法回滾了。

    所以部署一定是分兩步的。第一步,先把新的程式碼部署上去,新的格式不要變;新的程式碼能夠同時處理新舊資料格式。第二部,升級一下,新的資料格式就進來了,這樣就不怕了。

  • Topology Transition,當需要線上的擴容或著嫁接節點的時候;我們需要有個所謂的狀態驅動來保證資料的一致性和統一性不受影響。

    當時老的方法痛苦在於這是一個 all or none 的過程,一個遷移過程如果失敗了,即使已經完成了90%,也還是必須重來,這個對於 SRE 來說是非常痛苦的。

    我們後來設計了一個漸進式的遷移方法,能夠記住當前狀態。這樣可以隨時從當前的狀態重新恢復。

六、運維的挑戰與機遇

日誌

儘管 Twitter 在運維方面做了很多工作,但是還是有很多問題和需要改進的地方。例如,故障排除高度手工化。

因為 twitter 所有的服務的指標種類加起來總共超過10億。一旦出問題,排查起來就是一件很痛苦的事情。

對於這麼多指標,哪些有問題、哪些沒問題;人是很難判斷的。但是機器可以通過對比歷史資料並分析是可以做到異常自動發現的。

大家可能有經驗,前端出問題往往是由於後端導致的。怎麼將前後端關聯起來,這個機器是完全可以快速完成的;這樣一來就可以節省很多人工的時間。

很多時候知道到服務指標不正常可能還不夠,這時需要檢視日誌。檢視日誌難度大,日誌資訊多,噪聲大,找到需要的資訊不容易,而且還需要關聯時間;為此我們做了日誌分析和整合的系統。下圖是日誌的整合、聚類對比的結果。

智慧運維案例分析

這是一個央企大客戶,他們業務上傳經常出現阻塞;這個點是機器自動標識出來的。通過機器標識可以建立很靈活的報警規則。

另外一個客戶 CPU 突然飆高,不知道什麼原因;通過智慧關聯排查故障根源工具發現這個是一個 hbase 寫也增加了。把這些有用的資訊推薦給客戶,客戶很快知道了是由於一個配置修改造成的問題。

這是另外一個客戶,非常重要的門戶伺服器經常出現飆高;但卻一直不知道什麼原因。後來通過我們的工具自動找出了問題;我們找道了問題程序和詳盡資訊,詳盡到包括用什麼語言寫的。

後來發現是他們的 SRE 寫的一個指令碼,後來沒有用了,但扔在那兒忘了;結果每天都在跑,浪費計算資源。導致他們服務受影響。

智慧管理

我們做這套東西對故障診斷有非常大的幫助。這也是我們建立這個智慧管理整個一站式解決方案的原因。

最後一個智慧知識庫是把大家的運維知識不斷積累放在裡面;同時機器能夠自動學習,就像一個一個機器大腦,隨時可以查詢,相當於一個運維的知乎。

原文來自微信公眾號:高效運維