序言
微博平臺(tái)第一代架構(gòu)為L(zhǎng)AMP架構(gòu),數(shù)據(jù)庫使用的是MyIsam,后臺(tái)用的是php,緩存為Memcache。
隨著應(yīng)用規(guī)模的增長(zhǎng),衍生出的第二代架構(gòu)對(duì)業(yè)務(wù)功能進(jìn)行了模塊化、服務(wù)化和組件化,后臺(tái)系統(tǒng)從php替換為Java,逐漸形成SOA架構(gòu),在很長(zhǎng)一段時(shí)間支撐了微博平臺(tái)的業(yè)務(wù)發(fā)展。
在此基礎(chǔ)上又經(jīng)過長(zhǎng)時(shí)間的重構(gòu)、線上運(yùn)行、思索與沉淀,平臺(tái)形成了第三代架構(gòu)體系。
我們先看一張微博的核心業(yè)務(wù)圖(如下),是不是非常復(fù)雜?但這已經(jīng)是一個(gè)簡(jiǎn)化的不能再簡(jiǎn)化的業(yè)務(wù)圖了,第三代技術(shù)體系就是為了保障在微博核心業(yè)務(wù)上快速、高效、可靠地發(fā)布新產(chǎn)品新功能。
第三代技術(shù)體系
微博平臺(tái)的第三代技術(shù)體系,使用正交分解法建立模型:在水平方向,采用典型的三級(jí)分層模型,即接口層、服務(wù)層與資源層;在垂直方向,進(jìn)一步細(xì)分為業(yè)務(wù)架構(gòu)、技術(shù)架構(gòu)、監(jiān)控平臺(tái)與服務(wù)治理平臺(tái)。下面是平臺(tái)的整體架構(gòu)圖:
如上圖所示,正交分解法將整個(gè)圖分解為3*4=12個(gè)區(qū)域,每個(gè)區(qū)域代表一個(gè)水平維度與一個(gè)垂直維度的交點(diǎn),相應(yīng)的定義這個(gè)區(qū)域的核心功能點(diǎn),比如區(qū)域5主要完成服務(wù)層的技術(shù)架構(gòu)。
下面詳細(xì)介紹水平方向與垂直方向的設(shè)計(jì)原則,尤其會(huì)重點(diǎn)介紹4、5、6中的技術(shù)組件及其在整個(gè)架構(gòu)體系中的作用。
水平分層
水平維度的劃分,在大中型互聯(lián)網(wǎng)后臺(tái)業(yè)務(wù)系統(tǒng)的設(shè)計(jì)中非?;A(chǔ),在平臺(tái)的每一代技術(shù)體系中都有體現(xiàn)。這里還是簡(jiǎn)單介紹一下,為后續(xù)垂直維度的延伸講解做鋪墊:
接口層主要實(shí)現(xiàn)與Web頁面、移動(dòng)客戶端的接口交互,定義統(tǒng)一的接口規(guī)范,平臺(tái)最核心的三個(gè)接口服務(wù)分別是內(nèi)容(Feed)服務(wù)、用戶關(guān)系服務(wù)及通訊服務(wù)(單發(fā)私信、群發(fā)、群聊)。
服務(wù)層主要把核心業(yè)務(wù)模塊化、服務(wù)化,這里又分為兩類服務(wù),一類為原子服務(wù),其定義是不依賴任何其他服務(wù)的服務(wù)模塊,比如常用的短鏈服務(wù)、發(fā)號(hào)器服務(wù)都屬于這一類。圖中使用泳道隔離,表示它們的獨(dú)立性。另外一類為組合服務(wù),通過各種原子服務(wù)和業(yè)務(wù)邏輯的組合來完成服務(wù),比如Feed服務(wù)、通訊服務(wù),它們除了本身的業(yè)務(wù)邏輯,還依賴短鏈、用戶及發(fā)號(hào)器服務(wù)。
資源層主要是數(shù)據(jù)模型的存儲(chǔ),包含通用的緩存資源Redis和Memcached,以及持久化數(shù)據(jù)庫存儲(chǔ)MySQL、HBase,或者分布式文件系統(tǒng)TFS以及Sina S3服務(wù)。
水平分層有一個(gè)特點(diǎn),依賴關(guān)系都是從上往下,上層的服務(wù)依賴下層,下層的服務(wù)不會(huì)依賴上層,構(gòu)建了一種簡(jiǎn)單直接的依賴關(guān)系。
與分層模型相對(duì)應(yīng),微博系統(tǒng)中的服務(wù)器主要包括三種類型:前端機(jī)(提供 API 接口服務(wù))、隊(duì)列機(jī)(處理上行業(yè)務(wù)邏輯,主要是數(shù)據(jù)寫入)和存儲(chǔ)(mc、mysql、mcq、redis、HBase等)。
垂直延伸技術(shù)架構(gòu)
隨著業(yè)務(wù)架構(gòu)的發(fā)展和優(yōu)化,平臺(tái)研發(fā)實(shí)現(xiàn)了許多卓越的中間件產(chǎn)品,用來支撐核心業(yè)務(wù),這些中間件由業(yè)務(wù)驅(qū)動(dòng)產(chǎn)生,隨著技術(shù)組件越來越豐富,形成完備的平臺(tái)技術(shù)框架,大大提升了平臺(tái)的產(chǎn)品研發(fā)效率和業(yè)務(wù)運(yùn)行穩(wěn)定性。
區(qū)別于水平方向上層依賴下層的關(guān)系,垂直方向以技術(shù)框架為地基支撐點(diǎn),向兩側(cè)驅(qū)動(dòng)影響業(yè)務(wù)架構(gòu)、監(jiān)控平臺(tái)、服務(wù)治理平臺(tái),下面介紹一下其中的核心組件。
接口層Web V4框架
接口框架簡(jiǎn)化和規(guī)范了業(yè)務(wù)接口開發(fā)工作,將通用的接口層功能打包到框架中,采用了Spring的面向切面(AOP)設(shè)計(jì)理念。接口框架基于Jersey 進(jìn)行二次開發(fā),基于annotation定義接口(url, 參數(shù)),內(nèi)置Auth、頻次控制、訪問日志、降級(jí)功能,支撐接口層監(jiān)控平臺(tái)與服務(wù)治理,同時(shí)還有自動(dòng)化的Bean-json/xml序列化。
服務(wù)層框架
服務(wù)層主要涉及RPC遠(yuǎn)程調(diào)用框架以及消息隊(duì)列框架,這是微博平臺(tái)在服務(wù)層使用最為廣泛的兩個(gè)框架。
MCQ消息隊(duì)列
消息隊(duì)列提供一種先入先出的通訊機(jī)制,在平臺(tái)內(nèi)部,最常見的場(chǎng)景是將數(shù)據(jù)的落地操作異步寫入隊(duì)列,隊(duì)列處理程序批量讀取并寫入DB,消息隊(duì)列提供的異步機(jī)制加快了前端機(jī)的響應(yīng)時(shí)間,其次,批量的DB操作也間接提高了DB操作性能,另外一個(gè)應(yīng)用場(chǎng)景,平臺(tái)通過消息隊(duì)列,向搜索、大數(shù)據(jù)、商業(yè)運(yùn)營(yíng)部門提供實(shí)時(shí)數(shù)據(jù)。
微博平臺(tái)內(nèi)部大量使用的MCQ(SimpleQueue Service Over Memcache)消息隊(duì)列服務(wù),基于MemCache協(xié)議,消息數(shù)據(jù)持久化寫入BerkeleyDB,只有g(shù)et/set兩個(gè)命令,同時(shí)也非常容易做監(jiān)控(stats queue),有豐富的client library,線上運(yùn)行多年,性能比通用的MQ高很多倍。
Motan RPC框架
微博的Motan RPC服務(wù),底層通訊引擎采用了Netty網(wǎng)絡(luò)框架,序列化協(xié)議支持Hessian和Java序列化,通訊協(xié)議支持Motan、http、tcp、mc等,Motan框架在內(nèi)部大量使用,在系統(tǒng)的健壯性和服務(wù)治理方面,有較為成熟的技術(shù)解決方案,健壯性上,基于Config配置管理服務(wù)實(shí)現(xiàn)了High Availability與Load Balance策略(支持靈活的FailOver和FailFast HA策略,以及Round Robin、LRU、Consistent Hash等Load Balance策略),服務(wù)治理方面,生成完整的服務(wù)調(diào)用鏈數(shù)據(jù),服務(wù)請(qǐng)求性能數(shù)據(jù),響應(yīng)時(shí)間(Response Time)、QPS以及標(biāo)準(zhǔn)化Error、Exception日志信息。
資源層框架
資源層的框架非常多,有封裝MySQL與HBase的Key-List DAL中間件、有定制化的計(jì)數(shù)組件,有支持分布式MC與Redis的Proxy,在這些方面業(yè)界有較多的經(jīng)驗(yàn)分享,我在這里分享一下平臺(tái)架構(gòu)的對(duì)象庫與SSD Cache組件。
對(duì)象庫
對(duì)象庫支持便捷的序列化與反序列化微博中的對(duì)象數(shù)據(jù):序列化時(shí),將JVM內(nèi)存中的對(duì)象序列化寫入在HBase中并生成唯一的ObjectID,當(dāng)需要訪問該對(duì)象時(shí),通過ObjectID讀取,對(duì)象庫支持任意類型的對(duì)象,支持PB、JSON、二進(jìn)制序列化協(xié)議,微博中最大的應(yīng)用場(chǎng)景將微博中引用的視頻、圖片、文章統(tǒng)一定義為對(duì)象,一共定義了幾十種對(duì)象類型,并抽象出標(biāo)準(zhǔn)的對(duì)象元數(shù)據(jù)Schema,對(duì)象的內(nèi)容上傳到對(duì)象存儲(chǔ)系統(tǒng)(Sina S3)中,對(duì)象元數(shù)據(jù)中保存Sina S3的下載地址。
SSDCache
隨著SSD硬盤的普及,優(yōu)越的IO性能使其被越來越多地用于替換傳統(tǒng)的SATA和SAS磁盤,常見的應(yīng)用場(chǎng)景有三種:
1)替換MySQL數(shù)據(jù)庫的硬盤,目前社區(qū)還沒有針對(duì)SSD優(yōu)化的MySQL版本,即使這樣,直接升級(jí)SSD硬盤也能帶來8倍左右的IOPS提升;
2)替換Redis的硬盤,提升其性能;
3)用在CDN中,加快靜態(tài)資源加載速度。
微博平臺(tái)將SSD應(yīng)用在分布式緩存場(chǎng)景中,將傳統(tǒng)的Redis/MC + Mysql方式,擴(kuò)展為Redis/MC + SSD Cache + Mysql方式,SSD Cache作為L(zhǎng)2緩存使用,第一降低了MC/Redis成本過高,容量小的問題,也解決了穿透DB帶來的數(shù)據(jù)庫訪問壓力。
垂直的監(jiān)控與服務(wù)治理
隨著服務(wù)規(guī)模和業(yè)務(wù)變得越來越復(fù)雜,即使業(yè)務(wù)架構(gòu)師也很難準(zhǔn)確地描述服務(wù)之間的依賴關(guān)系,服務(wù)的管理運(yùn)維變得越來難,在這個(gè)背景下,參考google的dapper和twitter的zipkin,平臺(tái)實(shí)現(xiàn)了自己的大型分布式追蹤系統(tǒng)WatchMan。
WatchMan大型分布式追蹤系統(tǒng)
如其他大中型互聯(lián)網(wǎng)應(yīng)用一樣,微博平臺(tái)由眾多的分布式組件構(gòu)成,用戶通過瀏覽器或移動(dòng)客戶端的每一個(gè)HTTP請(qǐng)求到達(dá)應(yīng)用服務(wù)器后,會(huì)經(jīng)過很多個(gè)業(yè)務(wù)系統(tǒng)或系統(tǒng)組件,并留下足跡(footprint)。但是這些分散的數(shù)據(jù)對(duì)于問題排查,或是流程優(yōu)化都幫助有限。對(duì)于這樣一種典型的跨進(jìn)程/跨線程的場(chǎng)景,匯總收集并分析這類日志就顯得尤為重要。另一方面,收集每一處足跡的性能數(shù)據(jù),并根據(jù)策略對(duì)各子系統(tǒng)做流控或降級(jí),也是確保微博平臺(tái)高可用的重要因素。要能做到追蹤每個(gè)請(qǐng)求的完整調(diào)用鏈路;收集調(diào)用鏈路上每個(gè)服務(wù)的性能數(shù)據(jù);能追蹤系統(tǒng)中所有的Error和Exception;通過計(jì)算性能數(shù)據(jù)和比對(duì)性能指標(biāo)(SLA)再回饋到控制流程(control flow)中,基于這些目標(biāo)就誕生了微博的Watchman系統(tǒng)。
該系統(tǒng)設(shè)計(jì)的一個(gè)核心原則就是低侵入性(non-invasivenss):作為非業(yè)務(wù)組件,應(yīng)當(dāng)盡可能少侵入或者不侵入其他業(yè)務(wù)系統(tǒng),保持對(duì)使用方的透明性,可以大大減少開發(fā)人員的負(fù)擔(dān)和接入門檻?;诖丝紤],所有的日志采集點(diǎn)都分布在技術(shù)框架中間件中,包括接口框架、RPC框架以及其他資源中間件。
WatchMan由技術(shù)團(tuán)隊(duì)搭建框架,應(yīng)用在所有業(yè)務(wù)場(chǎng)景中,運(yùn)維基于此系統(tǒng)完善監(jiān)控平臺(tái),業(yè)務(wù)和運(yùn)維共同使用此系統(tǒng),完成分布式服務(wù)治理,包括服務(wù)擴(kuò)容與縮容、服務(wù)降級(jí)、流量切換、服務(wù)發(fā)布與灰度。
cache設(shè)計(jì)
這里簡(jiǎn)單說一下兩個(gè)部分,一部分是Feed架構(gòu)簡(jiǎn)介,第二是cache的設(shè)計(jì)。
微博技術(shù)核心主要三個(gè),一條微博有很多關(guān)注的人,分別將你發(fā)表的微博分發(fā)到你所有關(guān)注的人,聚合就是打開微博首頁這里看到我關(guān)注人的信息,以及這個(gè)微博信息的展現(xiàn),微博在技術(shù)上也稱之為status或者Feed,下面圖就是一個(gè)典型的Feed。
Feed架構(gòu)剛才是兩種設(shè)計(jì)模式推或者拉,還有第三種方式叫做復(fù)合型。做到一定程度單純推或者拉是不夠的。推的話如果把Feed比喻成郵件,推就是inbo不惜是收到的微博,OUTPOX是已發(fā)表的微博,發(fā)表到所有的粉絲,查看就是直接訪問到。PUSH優(yōu)點(diǎn)就是實(shí)現(xiàn)簡(jiǎn)單,通常做一個(gè)種型是首選方案,缺點(diǎn)就是分發(fā)量。PULL發(fā)表是在自己的outbox,查看是所有關(guān)注對(duì)象的inbox。 優(yōu)點(diǎn)節(jié)約存儲(chǔ),缺點(diǎn)是計(jì)算大量,峰值問題。當(dāng)前訪問量比較大是不是計(jì)算得過來,服務(wù)器是不是夠用,假如說你的服務(wù)器是按照你峰值規(guī)劃你的服務(wù)器,在平時(shí)時(shí) 候是非常多的空閑,這個(gè)是不合理,不管推和拉都有一些共同的難題比如說峰值的挑戰(zhàn),比如說世界杯活動(dòng)在新浪微博每秒鐘發(fā)表量達(dá)到2500條,可以使用異步處理2500個(gè)峰值,處理速度慢一點(diǎn),你關(guān)注人不能馬上看到,峰值過后保證系統(tǒng)不會(huì)被峰值壓跨,下面就是cache,現(xiàn)在有一句話對(duì)于這種real—time就是說:傳統(tǒng)硬盤已經(jīng)不夠用,很多東西要分放在硬盤里面才能滿足需求。因此cache設(shè)計(jì)決定了一個(gè)微博系統(tǒng)的優(yōu)劣。
里面是一種復(fù)合型,不是一個(gè)簡(jiǎn)單的推或者拉的類型,因?yàn)榫褪钦f像新浪微博到這個(gè)級(jí)別要做很多優(yōu)化,從模型上就是一個(gè)推或者拉的模型,按照它的關(guān)系來說,把cache分成需要四種存儲(chǔ)的東西,這兩個(gè)里面跟索引比較類似,第三就是列表和客戶自己資料。
看一下第一部分就是inbox微博首頁開始ID列表,完全是內(nèi)存里面,但是有一個(gè)缺點(diǎn),要添加元素需要先AET再SET;第二部分outbox發(fā)出微博有存儲(chǔ)最新ID在于聚合。為了高效,通常分兩部分,第一就是說最新的一個(gè)ID列表比如說有100條內(nèi)容,這個(gè)用戶很久沒有來,這個(gè)是空要過來取就要從我工作列表用ID地址聚合起來;第三部分是關(guān)注列表,這些都是純ID,然后following,following加載開銷比較大,上百萬粉絲,越大的集合越容易變更,改變則需要deleteall減少使用followinglist場(chǎng)景;第四部分contetcache微博內(nèi)容體里面有一個(gè)很重要的內(nèi)容,熱內(nèi)容。這個(gè)用戶有200萬粉絲,這個(gè)內(nèi)容是熱內(nèi)容,在線粉絲也非常多,多分防止單點(diǎn)訪問瓶頸,最終格式預(yù)生成,apenAPI需要返回xml,json格式。
剛才說了介紹cache的架構(gòu),現(xiàn)在介紹cache的第二個(gè)方面就是使用流程。有一個(gè)典型的場(chǎng)景,比如說發(fā)表cache怎么操作,首頁展現(xiàn)怎么操作。發(fā)表需要改變?nèi)齻€(gè)內(nèi)容,首先要聲稱contentcache,對(duì)于常規(guī)contentcache也要做復(fù)制,如果對(duì)方粉絲在線會(huì)在inbox數(shù)值ID變更。
第三方面修改outbox,根據(jù)粉絲列表修改inbox數(shù)據(jù)列表,然后首頁Feed操作流程。左邊有兩個(gè):inbox,outbox。兩個(gè)是可選的,如果inbox沒有一個(gè)樹型計(jì)算,會(huì)根據(jù)ID列表聚合起來反饋給I用戶。
獲取首頁Feed的流程,首先間看inbocache是否可用,獲取關(guān)注列表,聚合內(nèi)容從following關(guān)系,根據(jù)idlist返回最終Feed聚合內(nèi)容。最常用兩個(gè)流程就是這樣。
下面介紹微博cache經(jīng)驗(yàn)談,首先說流量。打開首頁,這個(gè)時(shí)候打一個(gè)I來說,比如說contentcache為例,比如multigntn條Feed,cache大小等于N,并發(fā)清且如1000次/秒,總流量等于50,20K。假如微博機(jī)房里面有1萬并發(fā)需要800MBPS貸款,如果不改變價(jià)格這個(gè)流量是實(shí)現(xiàn)不了。再一個(gè)1G內(nèi)網(wǎng)做了很多壓力測(cè)試,一般環(huán)境跑三四百兆已經(jīng)不錯(cuò)了,你網(wǎng)內(nèi)不光是訪問cache開銷,還有很多其他流量,因此微博需要優(yōu)化帶寬訪問,可以把熱門數(shù)據(jù)加載到localcache,要用壓縮算法,可以做復(fù)制,有的時(shí)候?qū)⒁粋€(gè)內(nèi)部cache分組,不同的服務(wù)器組,訪問不同的cache減少內(nèi)網(wǎng)通信的開銷。第一個(gè)問題就是帶寬的問題,其中內(nèi)銷cache開銷訪問量大第一會(huì)碰到瓶頸。第二問題就是hotKeys,要訪問姚晨的微博,要建設(shè)一個(gè)Ilocolcache,刪除時(shí)間要把所有的都刪除。
cache規(guī)劃方面一些問題,將不同業(yè)務(wù),不同長(zhǎng)度KEY存儲(chǔ)到不同的MEMcache,不同的業(yè)務(wù)有不同的生命周期,LRUcache小量,memorystorage大部分,更高效的內(nèi)存利用。
mutex,什么情況會(huì)出現(xiàn)這個(gè)問題,比如說一個(gè)很熱的內(nèi)容,cache里面沒有了,因?yàn)閙emcache不是很可靠的東西,你放在里面可能會(huì)消失,經(jīng)常出現(xiàn)這樣的情況:一個(gè)很熱的cache沒有了,因?yàn)槲⒉┫到y(tǒng)有很多并發(fā)很熱數(shù)據(jù)沒有了,非常多的并發(fā)如果微博沒有一個(gè)很好的策略,比如說幾十個(gè),幾百個(gè)加一個(gè)內(nèi)容這會(huì)是一個(gè)悲劇。給每個(gè)KEY加載MUTEX,這個(gè)并發(fā)連接取數(shù)據(jù)庫,然后把mutex刪除成規(guī),這個(gè)時(shí)候我只需要一個(gè)連接,數(shù)據(jù)庫加載到BD里面有可以了。
因?yàn)榍懊嬉呀?jīng)介紹很多內(nèi)容,我今天介紹一個(gè)很簡(jiǎn)單的東西就是想關(guān)注更多微博平臺(tái)的技術(shù),有三個(gè)方向一個(gè)就是S2技 術(shù)沙龍,每個(gè)月舉行一次,另外就是說對(duì)很多講師光做講座不過癮,講座只是傳授別人東西,沒有能夠交流,所以微博對(duì)一線架構(gòu)師有一個(gè)自己線下交流,一些實(shí)際中遇到的問題,對(duì)這些架構(gòu)師有幫助提高,交流一下自己正在做,或者有一些東西還不成熟,不適合拿出來講的東西,可以線下交流。另外微博有各新浪微博開發(fā)大會(huì),會(huì)介紹更多微博平臺(tái)架構(gòu)分享的東西。
S2技術(shù)沙龍介紹了希望關(guān)注分享Web2.0技術(shù),下面有一個(gè)它的網(wǎng)址,另外就是說介紹一下即將舉行一個(gè)新浪微博開發(fā)者大會(huì),主要除了宣傳作用,希望更多分享新浪微博技術(shù),比如說這個(gè)平臺(tái)需要架構(gòu)與存儲(chǔ),可能到時(shí)候講比今天更深入一些,會(huì)講一些sinaappengine技術(shù),數(shù)據(jù)挖掘,合作與商業(yè)模式,開發(fā)者與平臺(tái)。目前有一個(gè)開發(fā)平臺(tái)的網(wǎng)站。