架構模式與煎餅果子

有一段時間住在花園路,最難忘的就是路邊的煎餅果子。老闆每天晚上出來,正好是我加班回去的時間。

一勺麵糊灑在鍋上,刮子轉一圈,再打一個蛋,依然刮平。然後啪的一下反過來,塗上辣醬,撒上蔥花。空出手來,剝一根火腿腸。最後放上薄脆,咔咔咔三鏟子斷成三邊直的長方形,折起來正好握在手中。燙燙的,一口咬下去,蛋香、醬辣、腸鮮,加上薄脆的聲音和蔥花的驚喜,所有的疲勞都一掃而光。

這種幸福感讓我如此迷戀,以至於會在深宅的周末,穿戴整齊跑出去,就為了吃上一個。也因為理工科的惡習,我也情不自禁地開始思考這份執迷的原因,直到最後,我發現了它的秘密。

作為街頭小吃的傑出代表,能夠經歷眾口的挑剔而長盛不衰的秘密,所有的一切全因為其模式。而這模式與大多數互聯網服務的架構如出一轍,那就是分層架構。

分層的設計意味著,每一層都獨立承擔單一的職責,這在根本上降低了製作的難度。做餅的時候專心控制火候,做醬的時候專註在味道。每層職責的單一化也讓優化變得簡單,因為它是自然可伸縮的。你要是想多吃點蛋就多加一個,你要多吃點腸就多加一根,完全取決於你的胃口。

它又是可以擴展的。你可以不要蛋,你可以加根腸,你可以不要薄脆,你可以加上辣醬。而且每一層又是可定製的。蔥花可以少一點,辣醬可以多一點,腸可以要兩根,雞蛋可以加三個。

你也可以把麵餅換成麵包,把雞蛋換成煎蛋,把辣醬換成甜醬。你已經知道這是什麼了吧?是的,你好,這裡是賽百味,請問你要什麼口味的三明治?

煎餅果子和三明治,其實本質上是相通的。而加一個蛋更香,也不是因為對蛋的追求,在根本上是因為煎餅果子模式的強大。

因為這種模式,一千個人可以有一千種煎餅果子。

而有了對模式的理解,對小吃的評估也就變得更加容易。比如肉夾饃只有饃和肉,二維切換單調不可長久;比如烤冷麵,乾脆就是滿嘴的熱烈混在一起,沒有煎餅這樣的表現層,整個面都散發著原始的不講究。

這種對比上的簡化,也讓我們有了新的選擇,可以隨時放棄對細節的追究,保存寶貴的精力。

就像在我們談論女人時(抱歉博主是男人),我們在意胸、在意腿、在意風情、在意溫柔,因為女人是有區別的。當我們欣賞電影的時候,我們在意男人、在意女人、在意老人、在意孩子,因為角色是有區別的。當我們走在路上的時候,我們在意行人、在意車輛、在意商店、在意餐廳,因為物體是有區別的。

我們在設計和優化系統的時候,其中的每個服務都是自行運轉,做著自己份內的事,但是在不同的維度里,作用卻變得不盡相同。這也是我們講優化要分層次和級別,架構、演算法、庫和OS,而講架構的時候,我們首先講的是整體的模式,然後是具體的權衡,實現的細節則是最不重要的。

架構的模式

談起這個,是因為Mark Richards寫了一本架構模式的書《Software Architecture Patterns》。總結對比了五種模式的優缺點,包括了Layered、Event-Driven、Microkernel、Microservices、Space-Based。書寫得簡單精緻,推薦大家去閱讀。Software Architecture Patterns

還有一種模式,因為在越來越多的系統中用到,是書中沒有的(與Space-Based有所區別),但我覺得也有必要專門介紹下。我們開始在群發系統中實現,後來的搶購、紅包和火車票的場景中也屢屢看到它的身影。

13年的時候,我們在微博做粉絲服務平台,一個類似微信公眾號的群發系統。然而比後者更困難的是,當時在產品設計上並沒有像微信一樣新建用戶體系,而是直接基於微博的粉絲關係,這就意味著一篇文章要能能在很短時間內支持億級的用戶推送。這個數量級的訂閱用戶,即使看今天的微信公眾號依然是難以想像的。

當時有一套老的群發系統,都是基於MySQL的收件箱設計,在更換了SSD硬碟,又批量化資料庫操作之後,整體寫入性能依然只在每秒幾萬的級別,這就意味著一億用戶只能在17分鐘內發完,我們意識到這套系統需要進行重新設計。

最終我們我們使用了一種新的架構方式,達到了每秒百萬級別的速度,而且還可以更高。這種模式就是單元化架構。

下文介紹我參照了架構模式的說明方式,希望能夠讓大家有個對比,喜歡你可一定要說好!

單元架構

如前所述,我們選擇單元化的一個重要目的是為了性能,為了極高的性能。這比起一般的分層架構來講,會獲得更經濟的結果,但也因此,犧牲了分層架構的一些特性,因為它的容量取決於單元的大小(關於單元等名詞介紹,我會在下文介紹)。

雖然它支持按照單元擴容,但在單元內基本上每層的性能都是固定的。這更適合容量可預期的場景,比如大多數已經趨於穩定的業務。像前面的粉絲服務平台,雖然他下發消息量級巨大,但是在整體層面,使用平台的用戶由於是VIP用戶,其規模基本在在數百萬級別,而粉絲量級也不太可能過億。

重要的是,基於當時的業務數據,我們已經知道平均粉絲數在什麼量級。而業務數據是架構選型的重要依據。商品秒殺、火車搶票等等都是一樣。

當然也有例外。因為單元化架構作為一種思想,它不會局限在一台機器,一個機架,它也適用一個機房。當它的層次變大時,單元內自然就可以有變化的空間。每一層服務都可以分開伸縮。而到了這個層面,它的追求可能就完全不一樣了。像阿里的雙十一服務改造,會為了流量的分離,像QQ的聊天,會為了接入的速度。它們的基本思想是一致的。

至於單元化架構和煎餅果子的關係,我會在文後回答。

核心概念 Key Concepts

分區(Shard)是整體數據集的一個子集。如果你用尾號來劃分用戶,那麼相同尾號的用戶可以認為是同一分區。

單元(Cell)是滿足某個分區所有業務操作的自包含的安裝。我們從並行計算領域裡借鑒了這個思想,也就是計算機體系結構里的Celluar Architecture,在那裡一個Cell是一個包含了線程部件、內存以及通訊組件的計算節點。Cellular architecture

單元化(Cellize)這是我的自造詞,描述一個服務改造成單元架構的過程。

模式描述 Pattern Description

單元架構最重要的概念,就是單元和單元的自治。

你可以將其想像成細胞,如之前所述,每個細胞都是自成一體,功能明確。你也可以將其想像成小隔間,就像你去了一個按摩院,每個隔間里都有技師和所有設備。我沒有用前面那個名字,因為其有太強的生物學含義,也沒有用後者,因為其有太多的服務性暗示。但是如果你有足夠的想像力,其實什麼名字都可以的。

說到單元的自治,即單元的自我協調和之間的隔離。單元既然做到了自包含,那麼其中的所有組件,不管是否在物理上分離成了獨立的服務,都是在一個單元內互相支持的,也就是跟其他單元內的同類和非同類組件都不會有任何交流。這也是跟基於空間的架構的重要區別,後者的處理單元之間還是會互相通信並同步信息。

這裡的挑戰就在於分區的演算法。一個單元內的組件會很多,如果業務複雜,涉及到的數據也會很多,為了隔離,每一個組件都要能按照同樣的演算法進行分區。

本質上每個單元都是相似的,單元之間的區別或者取決於請求,或者取決於數據。而且越到大的層面,區分度越低,用戶甚至是可以在不同單元間漫遊的。

模式動力學 Pattern Dynamics

單元架構的最典型目的,還是為了極高的性能,為了獲得經濟的高速度。這裡一方面,是因為我們發現其他架構實際上是浪費了很多資源,每一層服務都運行在單獨的操作系統上,而且都要通過區域網或者城域網中轉。

與此同時,傳統的互聯網服務還是希望用一堆計算能力普通的節點來服務大量用戶,而隨著摩爾定律的推進,單機性能越來越高,網路通訊的成本隨之變得耗費顯著。這使得我們有機會也有動力在垂直方向進行擴展。

當你把更多的組件放在同一個地方的時候,你也在物理上獲得了計算本地化的優勢。這是我們獲得性能提升的根本原因。

服務分成了很多單元,但總要跟外界通訊,這個事情是交給協調者Coordinator的。你可以在內部增加存儲、緩存,增加隊列和處理機,這些所有不交互的組件,理論上都不是外部資源可以訪問的。

前面我們提到,單元化過程也是分區演算法的應用過程。而這個分區演算法放在哪裡就是個問題。

我們可以封裝運行庫交給客戶端,也可以做個代理層,內置演算法。也有一些服務因為業務需要,請求需要複製到每個單元去。這就是典型的Scatter-Gatter模型,那麼你還可能需要一個作業管理系統。這些都是可選擇的使用方式。

模式分析 Pattern Analysis

總體敏捷度低,易部署性低,可測試性高,性能高,伸縮性高,易開發性低。

基於篇幅原因,不再詳述每一個方面,相信大家都能自行分析。唯一需要強調的是運維要求比較高。

單元化之後,所有的服務放在一起,在請求失敗的情況下需要快速定位某個單元,這跟分層排除的思路是不一樣的。如果運維團隊不夠高效,面對這樣集群數量的暴漲(每個單元的服務數量相當於原來一個集群的服務數量),有可能是會被大量的工作壓垮;如果運維團隊分離比較明顯,每種組件都是專門的團隊來維護(這是我們在微博遇到的),那就會有排異反應的風險,因為每一個團隊都有自己的許可權和服務管理習慣,這裡需要相當的協調工作來防止相互干擾。

後記

前面留的一個問題,煎餅果子跟單元化架構的關係。答案說起來很簡單,你問問煎餅攤怎麼看就知道了。

煎餅是分層的,煎餅攤是單元的。消息發送服務是單元的,但是索引維護是分層的。看模式要確定系統的範疇,從不同角度看,同樣的東西是有不同意義的。這也是架構師要做的思考。

其實IT系統千百萬,模式肯定不會止於這幾種。但有了基礎的模式,了解它們之間的相似和區別,對於我們設計自己的系統,思考其中的權衡都是有幫助的。

祝一切順利。

PS:本文已經在高可用架構發表,這裡僅作收錄。

封面圖片來源:ADIEU CRêPE – Nǐ HǎO JIANBING

weixin.qq.com/r/qT8TC8H (二維碼自動識別)


推薦閱讀:

高可用架構
藍圖系列(一):高並發、高可用、高性能、分散式系統架構
調用第三方介面的架構優化
秒殺系統優化思路

TAG:架構 | 系統架構 |