轉(zhuǎn)載:千萬級規(guī)模高性能、高并發(fā)的網(wǎng)絡(luò)架構(gòu)經(jīng)驗(yàn)分享
作者簡介:
衛(wèi)向軍,畢業(yè)后在微軟工作五年,接著去了金山云,做的金山快盤,然后去了新浪微博做平臺架構(gòu)師,現(xiàn)在在三好網(wǎng),做在線教育的創(chuàng)業(yè)公司。
主題:INTO100沙龍
時(shí)間:2015年11月21日下午
地點(diǎn):夢想加聯(lián)合辦公空間
正文:
大家下午好。感謝大家支持今天的沙龍,也感謝夢想加給我們提供場地。麥思博是一家軟件研發(fā)培訓(xùn)公司,2007年成立,我們一直專注于軟件研發(fā)快速成長,今天Into100沙龍是第14期了,我們每次主題都偏向技術(shù),每次分享是由三個(gè)嘉賓分享。這個(gè)模式實(shí)際上跟全球軟件案例峰會是一致的,用50分鐘時(shí)間給你解讀長尾價(jià)值。今天第14期主題是千萬級規(guī)模高性能,高并發(fā)的網(wǎng)絡(luò)架構(gòu)。這次請了了三位技術(shù)大咖,第一位分享嘉賓來自前新浪微博架構(gòu)師,現(xiàn)任三好網(wǎng)CTO,他為我們分享億級用戶下的高并發(fā)的網(wǎng)絡(luò)架構(gòu)。
主題演講:
大家下午好,我中午從公司過來的時(shí)候,外面一直在下雪,在這兒看到是一個(gè)又溫馨又特別的會場。大家離我的距離非常近,所以很感謝麥思博給我這個(gè)機(jī)會與大家分享探討。
我是衛(wèi)向軍,畢業(yè)后在微軟工作五年,接著去了金山云,做的金山快盤,然后去了新浪微博做平臺架構(gòu)師,現(xiàn)在在三好網(wǎng),做在線教育的創(chuàng)業(yè)公司。
第一:我會介紹一下架構(gòu)以及我理解中架構(gòu)的本質(zhì)
第二:介紹一下新浪微博整體架構(gòu)是什么樣的
第三:在 大型網(wǎng)站的系統(tǒng)架構(gòu)是如何演變的
第四:微博的技術(shù)挑 戰(zhàn)和正交分解法解析架構(gòu)
第五:微博多級雙機(jī)房緩存架 構(gòu)
第六:分布式服務(wù)追蹤系統(tǒng)
第七:今天分享的內(nèi)容 做一下總結(jié)
在開始談我對架構(gòu)本質(zhì)的理解之前,先談?wù)剬裉旒夹g(shù)沙龍主題的個(gè)人見解,千萬級規(guī)模的網(wǎng)站感覺數(shù)量級是非常大的,對這個(gè)數(shù)量級我們戰(zhàn)略上要重視它,戰(zhàn)術(shù)上又要藐視它。
先舉個(gè)例子感受一下千萬級到底是什么數(shù)量級?現(xiàn)在很流行的優(yōu)步(Uber),從媒體公布的信息看,它每天接單量平均在百萬左右,假如每天有10個(gè)小時(shí)的服務(wù)時(shí)間,平均QPS只有30左右。對于一個(gè)后臺服務(wù)器,單機(jī)的平均QPS可以到達(dá)800-1000,單獨(dú)看寫的業(yè)務(wù)量很簡單。為什么我們又不能說輕視它?第一,我們看它的數(shù)據(jù)存儲,每天一百萬的話,一年數(shù)據(jù)量的規(guī)模是多少?其次,剛才說的訂單量,每一個(gè)訂單要推送給附近的司機(jī)、司機(jī)要并發(fā)搶單,后面業(yè)務(wù)場景的訪問量往往是前者的上百倍,輕松就超過上億級別了。
今天我想從架構(gòu)的本質(zhì)談起之后,希望大家理解在做一些建構(gòu)設(shè)計(jì)的時(shí)候,它的出發(fā)點(diǎn)以及它解決的問題是什么。
架構(gòu),剛開始的解釋是我從知乎上看到的。什么是架構(gòu)?有人講,說架構(gòu)并不是一個(gè)很懸乎的東西,實(shí)際上就是一個(gè)架子,放一些業(yè)務(wù)和算法,跟我們的生活中的晾衣架很像。更抽象一點(diǎn),說架構(gòu)其實(shí)是對我們重復(fù)性業(yè)務(wù)的抽象和我們未來業(yè)務(wù)拓展的前瞻,強(qiáng)調(diào)過去的經(jīng)驗(yàn)和你對整個(gè)行業(yè)的預(yù)見。
我們要想做一個(gè)架構(gòu)的話需要哪些能力?我覺得最重要的是架構(gòu)師一個(gè)最重要的能力就是你要有戰(zhàn)略分解能力。 這個(gè)怎么來看呢,第一,你必須要有抽象的能力,抽象的能力最基本就是去重,去重在整個(gè)架構(gòu)中體現(xiàn)在方方面面,從定義一個(gè)函數(shù),到定義一個(gè)類,到提供的一個(gè)服務(wù),以及模板,背后都是要去重提高可復(fù)用率。第二,分類能力。 做軟件需要做對象的解耦,要定義對象的屬性和方法,做 分布式系統(tǒng)的時(shí)候要做服務(wù)的拆分和模塊化,要定義服務(wù) 的接口和規(guī)范。 第三,算法(性能),它的價(jià)值體現(xiàn)在提升系統(tǒng)的性能,所有性能的提升,最終都會落到CPU、內(nèi) 存、IO和網(wǎng)絡(luò)這4大塊上。

這一頁P(yáng)PT舉了一些例子來更深入的理解常見技術(shù)背后的架構(gòu)理念。第一個(gè)例子,在分布式系統(tǒng)我們會做MySQL分庫分表,我們要從不同的庫和表中讀取數(shù)據(jù),這樣的抽象最直觀就是使用模板,因?yàn)榻^大多數(shù)SQL語義是相同的,除了路由到哪個(gè)庫哪個(gè)表,如果不使用Proxy中間件,模板就是性價(jià)比最高的方法。第二看一下加速網(wǎng)絡(luò)的CDN,它是做速度方面的性能提升,剛才我們也提到從CPU、內(nèi)存、IO、 網(wǎng)絡(luò)四個(gè)方面來考慮,CDN本質(zhì)上一個(gè)是做網(wǎng)絡(luò)智能調(diào)度優(yōu) 化,另一個(gè)是多級緩存優(yōu)化。第三個(gè)看一下服務(wù)化,剛才已經(jīng)提到了,各個(gè)大網(wǎng)站轉(zhuǎn)型過程中一定會做服務(wù)化,其 實(shí)它就是做抽象和做服務(wù)的拆分。第四個(gè)看一下消息隊(duì)列,本質(zhì)上還是做分類,只不過不是兩個(gè)邊際清晰的類,而是把兩個(gè)邊際不清晰的子系統(tǒng)通過隊(duì)列解構(gòu)并且異步化。

接下我們看一下微博整體架構(gòu),到一定量級的系統(tǒng)整個(gè)架構(gòu)都會變成三層,客戶端包括WEB、安卓和IOS,這里就不說了。接著還都會有一個(gè)接口層,有三個(gè)主要作用:
第一個(gè)作用,要做安全隔離,因?yàn)榍岸斯?jié)點(diǎn)都是直接和用戶交互,需要防范各種惡意攻擊;
第二個(gè)還充當(dāng)著一個(gè)流量控制的作用,大家知道在2014年春節(jié)的時(shí)候,微信紅包每分鐘8億多次的請求,其實(shí)真正到它后臺的請求量, 只有十萬左右的數(shù)量級(這里的數(shù)據(jù)可能不準(zhǔn)),剩余的流量在接口層就被擋住了;
第三,我們對PC端和移動端的需求不一樣的,所以我們可以進(jìn)行拆分。接口層之后是后臺,可以看到微博后臺有三大塊:一個(gè)是平臺服務(wù),第二是搜索,第三是大數(shù)據(jù)。到了后臺的各種服務(wù)其實(shí)都是處理的數(shù)據(jù)。 像平臺的業(yè)務(wù)部門,做的就是數(shù)據(jù)存儲和讀取,對搜索來說做的是數(shù)據(jù)的檢索,對大數(shù)據(jù)來說是做的數(shù)據(jù)的挖掘。

微博其實(shí)和淘寶是很類似的。一般來說,第一代架構(gòu), 基本上能支撐到用戶到百萬級別,到第二代架構(gòu)基本能支 撐到千萬級別都沒什么問題,當(dāng)業(yè)務(wù)規(guī)模到億級別時(shí),需 要第三代的架構(gòu)。
從LAMP的架構(gòu)到面向服務(wù)的架構(gòu),有幾個(gè)地方是非 常難的,首先不可能在第一代基礎(chǔ)上通過簡單的修修補(bǔ)補(bǔ) 滿足用戶量快速增長的,同時(shí)線上業(yè)務(wù)又不能停, 這是我們常說的在飛機(jī)上換引擎的問題。前兩天我有一個(gè)朋友問 我,說他在內(nèi)部推行服務(wù)化的時(shí)候,把一個(gè)模塊服務(wù)化做完了,其他部門就是不接。我建議在做服務(wù)化的時(shí)候,首先更多是偏向業(yè)務(wù)的梳理,同時(shí)要找準(zhǔn)一個(gè)很好的切入點(diǎn), 既有架構(gòu)和服務(wù)化上的提升,業(yè)務(wù)方也要有收益,比如提 升性能或者降低維護(hù)成本同時(shí)升級過程要平滑,建議開始 從原子化服務(wù)切入,比如基礎(chǔ)的用戶服務(wù), 基礎(chǔ)的短消息服務(wù),基礎(chǔ)的推送服務(wù)。 第二,就是可以做無狀態(tài)服務(wù), 后面會詳細(xì)講,還有數(shù)據(jù)量大了后需要做數(shù)據(jù)Sharding, 后面會將。第三代架構(gòu)要解決的問題,就是用戶量和業(yè)務(wù) 趨于穩(wěn)步增加(相對爆發(fā)期的指數(shù)級增長),更多考慮技術(shù)框架的穩(wěn)定性, 提升系統(tǒng)整體的性能,降低成本,還有對整個(gè)系統(tǒng)監(jiān)控的完善和升級。

我們通過通過數(shù)據(jù)看一下它的挑戰(zhàn),PV是在10億級別, QPS在百萬,數(shù)據(jù)量在千億級別。我們可用性,就是SLA要求4個(gè)9,接口響應(yīng)最多不能超過150毫秒,線上所有的故障必須得在5分鐘內(nèi)解決完。如果說5分鐘沒處理呢?那會影 響你年終的績效考核。2015年微博DAU已經(jīng)過億。我們系統(tǒng)有上百個(gè)微服務(wù),每周會有兩次的常規(guī)上線和不限次數(shù)的緊急上線。我們的挑戰(zhàn)都一樣,就是數(shù)據(jù)量,bigger and bigger,用戶體驗(yàn)是faster and faster,業(yè)務(wù)是more and more?;ヂ?lián)網(wǎng)業(yè)務(wù)更多是產(chǎn)品體驗(yàn)驅(qū)動,技術(shù)在產(chǎn)品體驗(yàn) 上最有效的貢獻(xiàn),就是你的性能越來越好。每次降低加載一個(gè)頁面的時(shí)間,都可以間接的降低這個(gè)頁面上用戶的流失率。

下面看一下第三代的架構(gòu)圖以及我們怎么用正交分 解法闡述。 我們可以看到我們從兩個(gè)維度,橫軸和縱軸可 以看到。一個(gè)維度是水平的分層拆分,第二從垂直的維 度會做拆分。水平的維度從接口層、到服務(wù)層到數(shù)據(jù)存儲 層。垂直怎么拆分,會用業(yè)務(wù)架構(gòu)、技術(shù)架構(gòu)、監(jiān)控平臺、 服務(wù)治理等等來處理。我相信到第二代的時(shí)候很多架構(gòu)已 經(jīng)有了業(yè)務(wù)架構(gòu)和技術(shù)架構(gòu)的拆分。我們看一下,接口層 有feed、用戶關(guān)系、通訊接口;服務(wù)層,SOA里有基層服務(wù)、 原子服務(wù)和組合服務(wù),在微博我們只有原子服務(wù)和組合服 務(wù)。原子服務(wù)不依賴于任何其他服務(wù),組合服務(wù)由幾個(gè)原 子服務(wù)和自己的業(yè)務(wù)邏輯構(gòu)建而成 ,資源層負(fù)責(zé)海量數(shù)據(jù) 的存儲(后面例子會詳細(xì)講)。
技術(shù)框架解決獨(dú)立于業(yè)務(wù)的海量高并發(fā)場景下的技 術(shù)難題,由眾多的技術(shù)組件共同構(gòu)建而成。在接口層, 微博使用JERSY框架,幫助你做參數(shù)的解析,參數(shù)的驗(yàn)證, 序列化和反序列化;資源層,主要是緩存、DB相關(guān)的各類 組件,比如Cache組件和對象庫組件。
監(jiān)控平臺和服務(wù)治理,完成系統(tǒng)服務(wù)的像素級監(jiān)控, 對分布式系統(tǒng)做提前診斷、預(yù)警以及治理。包含了SLA 規(guī)則的制定、服務(wù)監(jiān)控、服務(wù)調(diào)用鏈監(jiān)控、流量監(jiān)控、錯(cuò) 誤異常監(jiān)控、線上灰度發(fā)布上線系統(tǒng)、線上擴(kuò)容縮容調(diào)度
系統(tǒng)等。

下面我們講一下常見的設(shè)計(jì)原則。
首先是系統(tǒng)架構(gòu)三個(gè)利器:
一個(gè),我們RPC服務(wù)組件(這里不講了),第二個(gè),我們消息中間件 。消息中間件起的作用:可以把兩個(gè) 模塊之間的交互異步化,其次可以把不均勻請求流量輸出 為勻速的輸出流量,所以說消息中間件異步化解耦和流量 削峰的利器。第三個(gè)是配置管理,它是代碼級灰度發(fā)布 以及保障系統(tǒng)降級的利器。
第二個(gè),無狀態(tài),接口層最重要的就是無狀態(tài)。我們在電商網(wǎng)站購物,在這個(gè)過程中很多情況下是有狀態(tài)的, 比如我瀏覽了哪些商品,為什么大家又常說接口層是無狀態(tài)的,其實(shí)我們把狀態(tài)從接口層剝離到了數(shù)據(jù)層。像用戶在電商網(wǎng)站購物,選了幾件商品,到了哪一步,接口無狀態(tài)后,狀態(tài)要么放在緩存中,要么放在數(shù)據(jù)庫中,其實(shí)它并不是沒有狀態(tài),只是在這個(gè)過程中我們要把一些有狀態(tài)的東西抽離出來到了數(shù)據(jù)層。
第三個(gè),數(shù)據(jù)層比服務(wù)層更需要設(shè)計(jì),這是一條非常重要的經(jīng)驗(yàn)。對于服務(wù)層來說,可以拿PHP寫,明天你可以拿JAVA來寫,但是如果你的數(shù)據(jù)結(jié)構(gòu)開始設(shè)計(jì)不合理, 將來數(shù)據(jù)結(jié)構(gòu)的改變會花費(fèi)你數(shù)倍的代價(jià),老的數(shù)據(jù)格式向新的數(shù)據(jù)格式遷移會讓你痛不欲生,既有工作量上的,又有數(shù)據(jù)遷移跨越的時(shí)間周期,有一些甚至需要半年以上。
第四,物理結(jié)構(gòu)與邏輯結(jié)構(gòu)的映射,上一張圖看到兩個(gè)維度切成十二個(gè)區(qū)間,每個(gè)區(qū)間代表一個(gè)技術(shù)領(lǐng)域, 這個(gè)可以看做我們的邏輯結(jié)構(gòu)。另外,不論后臺還是應(yīng)用 層的開發(fā)團(tuán)隊(duì),一般都會分幾個(gè)垂直的業(yè)務(wù)組加上一個(gè)基 礎(chǔ)技術(shù)架構(gòu)組,這就是從物理組織架構(gòu)到邏輯的技術(shù)架構(gòu) 的完美的映射,精細(xì)化團(tuán)隊(duì)分工,有利于提高溝通協(xié)作的 效率。
第五,www.sanhao.com的訪問過程,我們這個(gè)架構(gòu)圖里沒有涉及到的,舉個(gè)例子,比如當(dāng)你在瀏覽器輸入 www.sanhao網(wǎng)址的時(shí)候,這個(gè)請求在接口層之前發(fā)生了什么?首先會查看你本機(jī)DNS以及DNS服務(wù),查找域名對應(yīng)的IP地址,然后發(fā)送HTTP請求過去。這個(gè)請求首先會到前端 的VIP地址(公網(wǎng)服務(wù)IP地址),VIP之后還要經(jīng)過負(fù)載均 衡器(Nginx服務(wù)器),之后才到你的應(yīng)用接口層。在接口 層之前發(fā)生了這么多事,可能有用戶報(bào)一個(gè)問題的時(shí)候, 你通過在接口層查日志根本發(fā)現(xiàn)不了問題,原因就是問題 可能發(fā)生在到達(dá)接口層之前了。
第六,我們說分布式系統(tǒng),它最終的瓶頸會落在哪里 呢?前端時(shí)間有一個(gè)網(wǎng)友跟我討論的時(shí)候,說他們的系統(tǒng)遇到了一個(gè)瓶頸, 查遍了CPU,內(nèi)存,網(wǎng)絡(luò),存儲,都沒有問題。我說你再查一遍,因?yàn)樽罱K你不論用上千臺服務(wù)器還是上萬臺服務(wù)器,最終系統(tǒng)出瓶頸的一定會落在某一 臺機(jī)(可能是葉子節(jié)點(diǎn)也可能是核心的節(jié)點(diǎn)),一定落在 CPU、內(nèi)存、存儲和網(wǎng)絡(luò)上,最后查出來問題出在一臺服務(wù) 器的網(wǎng)卡帶寬上。

接下來我們看一下微博的Feed多級緩存。我們做業(yè)務(wù)的時(shí)候,經(jīng)常很少做業(yè)務(wù)分析,技術(shù)大會上的分享又都偏向技術(shù)架構(gòu)。其實(shí)大家更多的日常工作是需要花費(fèi)更多時(shí)間在業(yè)務(wù)優(yōu)化上。這張圖是統(tǒng)計(jì)微博的信息流前幾頁的訪 問比例,像前三頁占了97%,在做緩存設(shè)計(jì)的時(shí)候,我們最 多只存最近的M條數(shù)據(jù)。 這里強(qiáng)調(diào)的就是做系統(tǒng)設(shè)計(jì)要基 于用戶的場景,越細(xì)致越好。舉了一個(gè)例子,大家都會 用電商,電商在雙十一會做全國范圍內(nèi)的活動,他們做設(shè) 計(jì)的時(shí)候也會考慮場景的,一個(gè)就是購物車,我曾經(jīng)跟相 關(guān)開發(fā)討論過,購物車是在雙十一之前用戶的訪問量非常 大,就是不停地往里加商品。在真正到雙十一那天他不會 往購物車加?xùn)|西了,但是他會頻繁的瀏覽購物車。針對這 個(gè)場景,活動之前重點(diǎn)設(shè)計(jì)優(yōu)化購物車的寫場景, 活動開 始后優(yōu)化購物車的讀場景。


你看到的微博是由哪些部分聚合而成的呢?最右邊的是Feed,就是微博所有關(guān)注的人,他們的微博所組成的。 微博我們會按照時(shí)間順序把所有關(guān)注人的順序做一個(gè)排序。 隨著業(yè)務(wù)的發(fā)展,除了跟時(shí)間序相關(guān)的微博還有非時(shí)間序的微博,就是會有廣告的要求,增加一些廣告,還有粉絲 頭條,就是拿錢買的,熱門微博,都會插在其中。分發(fā)控制,就是說和一些推薦相關(guān)的,我推薦一些相關(guān)的好友的微博,我推薦一些你可能沒有讀過的微博,我推薦一些其他類型的微博。 當(dāng)然對非時(shí)序的微博和分發(fā)控制微博,實(shí) 際會起多個(gè)并行的程序來讀取,最后同步做統(tǒng)一的聚合。
這里稍微分享一下, 從SNS社交領(lǐng)域來看,國內(nèi)現(xiàn)在做的比較好的三個(gè)信息流:
微博是基于弱關(guān)系的媒體信息流;
朋友圈是基于強(qiáng)關(guān)系的信息流;
另外一個(gè) 做的比較好的就是今日頭條,它并不是基于關(guān)系來構(gòu) 建信息流,而是基于興趣和相關(guān)性的個(gè)性化推薦信息流。
信息流的聚合,體現(xiàn)在很多很多的產(chǎn)品之中,除了SNS, 電商里也有信息流的聚合的影子。比如搜索一個(gè)商品后出來的列表頁,它的信息流基本由幾部分組成:第一,打廣 告的;第二個(gè),做一些推薦,熱門的商品,其次,才是關(guān)鍵字相關(guān)的搜索結(jié)果。信息流開始的時(shí)候很簡單,但是到后期會發(fā)現(xiàn),你的這個(gè)流如何做控制分發(fā),非常復(fù)雜, 微博在最近一兩年一直在做這樣的工作。

剛才我們是從業(yè)務(wù)上分析,那么技術(shù)上怎么解決高并發(fā),高性能的問題?微博訪問量很大的時(shí)候,底層存儲是 用MySQL數(shù)據(jù)庫,當(dāng)然也會有其他的。對于查詢請求量大的時(shí)候,大家知道一定有緩存,可以復(fù)用可重用的計(jì)算結(jié)果。 可以看到,發(fā)一條微博,我有很多粉絲,他們都會來看我
發(fā)的內(nèi)容,所以微博是最適合使用緩存的系統(tǒng),微博的讀寫比例基本在幾十比一。
微博使用了雙層緩存,上面是L1,每個(gè)L1上都是一組 (包含4-6臺機(jī)器),左邊的框相當(dāng)于一個(gè)機(jī)房,右邊又是一個(gè)機(jī)房。在這個(gè)系統(tǒng)中L1緩存所起的作用是什么?首先, L1緩存增加整個(gè)系統(tǒng)的QPS,其次以低成本靈活擴(kuò)容的方式增加系統(tǒng)的帶寬。想象一個(gè)極端場景,只有一篇博文, 但是它的訪問量無限增長,其實(shí)我們不需要影響L2緩存, 因?yàn)樗膬?nèi)容存儲的量小,但它就是訪問量大。這種場景下,你就需要使用L1來擴(kuò)容提升QPS和帶寬瓶頸。另外一個(gè)場景,就是L2級緩存發(fā)生作用,比如我有一千萬個(gè)用戶, 去訪問的是一百萬個(gè)用戶的微博 ,這個(gè)時(shí)候,他不只是說 你的吞吐量和訪問帶寬,就是你要緩存的博文的內(nèi)容也很 多了,這個(gè)時(shí)候你要考慮緩存的容量,第二級緩存更多的是從容量上來規(guī)劃,保證請求以較小的比例穿透到后端的數(shù)據(jù)庫中,根據(jù)你的用戶模型你可以估出來,到底有百分之多少的請求不能穿透到DB, 評估這個(gè)容量之后,才能更好的評估DB需要多少庫,需要承擔(dān)多大的訪問的壓力。
另外,我們看雙機(jī)房的話,左邊一個(gè),右邊一個(gè)。兩個(gè)機(jī)房是互為主備,或者互為熱備 。如果兩個(gè)用戶在不 同地域,他們訪問兩個(gè)不同機(jī)房的時(shí)候,假設(shè)用戶從IDC1過來,因?yàn)榫徒?,他會訪問L1,沒有的話才會跑到 Master,當(dāng)在IDC1沒找到的時(shí)候才會跑到IDC2來找。同時(shí) 有用戶從IDC2訪問,也會有請求從L1和Master返回或者到 IDC1去查找。 IDC1和IDC2,兩個(gè)機(jī)房都有全量的用戶 數(shù)據(jù),同時(shí)在線提供服務(wù),但是緩存查詢又遵循最近 訪問原理。

還有哪些多級緩存的例子呢?CDN是典型的多級緩存。 CDN在國內(nèi)各個(gè)地區(qū)做了很多節(jié)點(diǎn),比如在杭州市部署一個(gè)節(jié)點(diǎn)時(shí),在機(jī)房里肯定不止一臺機(jī)器,那么對于一個(gè)地區(qū) 來說,只有幾臺服務(wù)器到源站回源,其他節(jié)點(diǎn)都到這幾臺服務(wù)器回源即可,這么看CDN至少也有兩級。
Local Cache+分布式緩存,這也是常見的一種策略。 有一種場景,分布式緩存并不適用,比如單點(diǎn)資源的爆發(fā) 性峰值流量,這個(gè)時(shí)候使用Local Cache + 分布式緩存, Local Cache在應(yīng)用服務(wù)器上用很小的內(nèi)存資源擋住少量的極端峰值流量,長尾的流量仍然訪問分布式緩存,這樣的Hybrid緩存架構(gòu)通過復(fù)用眾多的應(yīng)用服務(wù)器節(jié)點(diǎn),降低 了系統(tǒng)的整體成本。
我們來看一下Feed的存儲架構(gòu),微博的博文主要存在 MySQL中。首先來看內(nèi)容表,這個(gè)比較簡單,每條內(nèi)容一個(gè)索引,每天建一張表,其次看索引表,一共建了兩級索引。 首先想象一下用戶場景,大部分用戶刷微博的時(shí)候,看的 是他關(guān)注所有人的微博,然后按時(shí)間來排序。仔細(xì)分析發(fā) 現(xiàn)在這個(gè)場景下, 跟一個(gè)用戶的自己的相關(guān)性很小了。 所以在一級索引的時(shí)候會先根據(jù)關(guān)注的用戶,取他們的前條微博ID,然后聚合排序。我們在做哈希(分庫分表)的 時(shí)候,同時(shí)考慮了按照UID哈希和按照時(shí)間維度。很業(yè)務(wù)和時(shí)間相關(guān)性很高的,今天的熱點(diǎn)新聞,明天就沒熱度了, 數(shù)據(jù)的冷熱非常明顯,這種場景就需要按照時(shí)間維度做分表,首先冷熱數(shù)據(jù)做了分離(可以對冷熱數(shù)據(jù)采用不同的 存儲方案來降低成本),其次, 很容止控制我數(shù)據(jù)庫表的爆炸。像微博如果只按照用戶維度區(qū)分,那么這個(gè)用戶所有數(shù)據(jù)都在一張表里,這張表就是無限增長的,時(shí)間長了 查詢會越來越慢。二級索引,是我們里面一個(gè)比較特殊的場景,就是我要快速找到這個(gè)人所要發(fā)布的某一時(shí)段的微博時(shí),通過二級索引快速定位。

分布式追蹤服務(wù)系統(tǒng),當(dāng)系統(tǒng)到千萬級以后的時(shí)候, 越來越龐雜,所解決的問題更偏向穩(wěn)定性,性能和監(jiān)控。 剛才說用戶只要有一個(gè)請求過來,你可以依賴你的服務(wù) RPC1、RPC2,你會發(fā)現(xiàn)RPC2又依賴RPC3、RPC4。分布式服 務(wù)的時(shí)候一個(gè)痛點(diǎn),就是說一個(gè)請求從用戶過來之后,在 后臺不同的機(jī)器之間不停的調(diào)用并返回。

當(dāng)你發(fā)現(xiàn)一個(gè)問題的時(shí)候,這些日志落在不同的機(jī)器 上,你也不知道問題到底出在哪兒,各個(gè)服務(wù)之間互相隔 離,互相之間沒有建立關(guān)聯(lián)。所以導(dǎo)致排查問題基本沒有 任何手段,就是出了問題沒法兒解決。
我們要解決的問題,我們剛才說日志互相隔離,我們 就要把它建立聯(lián)系。建立聯(lián)系我們就有一個(gè)請求ID,然后結(jié)合RPC框架, 服務(wù)治理功能。假設(shè)請求從客戶端過來, 其中包含一個(gè)ID 101,到服務(wù)A時(shí)仍然帶有ID 101,然后調(diào) 用RPC1的時(shí)候也會標(biāo)識這是101 ,所以需要一個(gè)唯一的請求ID標(biāo)識遞歸迭代的傳遞到每一個(gè)相關(guān)節(jié)點(diǎn)。第二個(gè), 你做的時(shí)候,你不能說每個(gè)地方都加,對業(yè)務(wù)系統(tǒng)來說需 要一個(gè)框架來完成這個(gè)工作,這個(gè)框架要對業(yè)務(wù)系統(tǒng)是最低侵入原則,用JAVA的話就可以用AOP,要做到零侵入的原則,就是對所有相關(guān)的中間件打點(diǎn),從接口層組件 (HTTP Client、HTTP Server)至到服務(wù)層組件(RPC Client、RPC Server),還有數(shù)據(jù)訪問中間件的,這樣業(yè) 務(wù)系統(tǒng)只需要少量的配置信息就可以實(shí)現(xiàn)全鏈路監(jiān)控 。為什么要用日志?服務(wù)化以后,每個(gè)服務(wù)可以用不同的開發(fā) 語言,考慮多種開發(fā)語言的兼容性,內(nèi)部定義標(biāo)準(zhǔn)化的日志是唯一且有效的辦法。

最后,如何構(gòu)建基于GPS導(dǎo)航的路況監(jiān)控?我們剛才講分布式服務(wù)追蹤。分布式服務(wù)追蹤能解決的問題,如果單一用戶發(fā)現(xiàn)問題后,可以通過請求ID快速找到發(fā)生問 題的節(jié)點(diǎn)在什么,但是并沒有解決如何發(fā)現(xiàn)問題。我們看 現(xiàn)實(shí)中比較容易理解的道路監(jiān)控,每輛車有GPS定位,我想 看北京哪兒擁堵的時(shí)候,怎么做? 第一個(gè),你肯定要知 道每個(gè)車在什么位置,它走到哪兒了。其實(shí)可以說每個(gè)車 上只要有一個(gè)標(biāo)識,加上每一次流動的信息,就可以看到 每個(gè)車流的位置和方向。其次如何做監(jiān)控和報(bào)警,我們怎 么能了解道路的流量狀況和負(fù)載,并及時(shí)報(bào)警。我們要定 義這條街道多寬多高,單位時(shí)間可以通行多少輛車,這就 是道路的容量。有了道路容量,再有道路的實(shí)時(shí)流量,我 們就可以基于實(shí)習(xí)路況做預(yù)警?
對應(yīng)于分布式系統(tǒng)的話如何構(gòu)建? 第一,你要定 義每個(gè)服務(wù)節(jié)點(diǎn)它的SLA是多少?SLA可以從系統(tǒng)的CPU占 用率、內(nèi)存占用率、磁盤占用率、QPS請求數(shù)等來定義,相 當(dāng)于定義系統(tǒng)的容量。 第二個(gè),統(tǒng)計(jì)線上動態(tài)的流量, 你要知道服務(wù)的平均QPS、最低QPS和最大QPS,有了流量和 容量,就可以對系統(tǒng)做全面的監(jiān)控和報(bào)警。
剛才講的是理論,實(shí)際情況肯定比這個(gè)復(fù)雜。微博在 春節(jié)的時(shí)候做許多活動,必須保障系統(tǒng)穩(wěn)定,理論上你只要定義容量和流量就可以。但實(shí)際遠(yuǎn)遠(yuǎn)不行,為什么?有 技術(shù)的因素,有人為的因素,因?yàn)椴煌拈_發(fā)定義的流量 和容量指標(biāo)有主觀性,很難全局量化標(biāo)準(zhǔn),所以真正流量 來了以后,你預(yù)先評估的系統(tǒng)瓶頸往往不正確。實(shí)際中我 們在春節(jié)前主要采取了三個(gè)措施:
第一,最簡單的就是有 降級的預(yù)案,流量超過系統(tǒng)容量后,先把哪些功能砍掉, 需要有明確的優(yōu)先級 。
第二個(gè),線上全鏈路壓測,就是把 現(xiàn)在的流量放大到我們平常流量的五倍甚至十倍(比如下 線一半的服務(wù)器,縮容而不是擴(kuò)容),看看系統(tǒng)瓶頸最先 發(fā)生在哪里。我們之前有一些例子,推測系統(tǒng)數(shù)據(jù)庫會先 出現(xiàn)瓶頸,但是實(shí)測發(fā)現(xiàn)是前端的程序先遇到瓶頸。
第三, 搭建在線Docker集群, 所有業(yè)務(wù)共享備用的Docker 集群資源,這樣可以極大的避免每個(gè)業(yè)務(wù)都預(yù)留資源,但 是實(shí)際上流量沒有增長造成的浪費(fèi)。
接下來說的是如何不停的學(xué)習(xí)和提升,這里以Java語 言為例,首先,一定要理解JAVA;第二步,JAVA完了以后, 一定要理解JVM;其次,還要理解操作系統(tǒng);再次還是要 了解一下Design Pattern,這將告訴你怎么把過去的經(jīng) 驗(yàn)抽象沉淀供將來借鑒;還要學(xué)習(xí)TCP/IP、分布式系統(tǒng)、 數(shù)據(jù)結(jié)構(gòu)和算法。
最后就是我想說的就是今天我所說的可能一切都是錯(cuò)的! 大家通過不停的學(xué)習(xí)、練習(xí)和總結(jié), 形成自己的一套架構(gòu) 設(shè)計(jì)原則和方法,謝謝大家。
加入運(yùn)維幫
運(yùn)維幫已開通多個(gè)微信群供大家交流學(xué)習(xí),需要先加南非蜘蛛微信 (yunweibang008)后拉你入群。
會員討論群:總?cè)?、總?cè)?、總?cè)?
地方討論群:北京、上海、廣州、深圳、杭州、成都
軟件討論群:Nginx、Zabbix
QQ討論群:186356564
點(diǎn)擊最下方{閱讀原文}注冊運(yùn)維幫會員,享受會員專屬禮遇