做爲國內微博市場的絕對領軍者,新浪微博公佈一系列針對開發者的扶持政策,以期與第三方開發者聯手推進微博行業的總體發展。前端
如下爲演講實錄:java
你們下午好,在座的大部分都是技術開發者,技術開發者每每對微博這個產品很是關心。最晚的一次,是12點多收到一個郵件說想了解一下微博底層是怎麼構架的。不少技術人員對微博的構架很是感興趣,就是一個明星他有300萬粉絲,這個技術怎麼來實現?今天在這裏跟你們分享一下微博的底層機構,讓你們對微博的底層技術有更好的瞭解。另外無論是作客戶端、Web 1.0、Web 2.0、論壇、博客都要考慮架構的問題,架構其實是有一些共性的。今天我經過講解微博裏面的一些架構,分析一下架構裏面哪些共性你們能夠參考。node
首先給你們介紹一下微博架構發展的歷程。新浪微博在短短一年時間內從零發展到五千萬用戶,咱們的基層架構也發展了3個大的版本。初版就LAMP架構,優勢是能夠很是快的實現咱們的系統。咱們看一下技術特色,微博這個產品從架構上來分析,它須要解決的是發表和訂閱的問題。咱們初版採用的是推消息模式,假如說咱們一個明星用戶他有10萬個粉絲,那就是說用戶發表一條微博的時候,咱們把這個微博消息存成10萬份,這樣就是很簡單了,初版的架構實際上就是這兩行字。初版的技術細節,典型的LAMP架構,是使用MyISAM搜索引擎,它的優勢就是速度很是快。數據庫
另一個是MPSS,就是多個端口能夠佈置在同一服務器上。爲何使用MPSS?假如說咱們作一個互聯網應用,這個應用裏面有三個單元,咱們能夠由2種部署方式。咱們能夠把三個單元分別部署在三臺服務器上,另一種部署模式就是這三個單元部署在每一個服務器上都有。我推薦第2種方法。這個方法解決了兩個問題,一個是負載均衡,由於每個單元都有多個節點處理,另一個是能夠防止單點故障。若是咱們按照模式1來作的話,任何一個節點有故障就會影響咱們系統服務,若是模式二的話,任何一個結點發生故障咱們的總體都不會受到影響的。安全
咱們微博初版上線以後,用戶很是喜歡這個產品,用戶數增加很是迅速。咱們技術上碰到幾個問題。第一個問題是發表會出現延遲現象,尤爲是明星用戶他的粉絲多系統須要處理很長時間。另外系統在處理明星用戶發表時系統繁忙可能會影響到其餘的用戶,由於其餘的用戶同一時間發表的話,也會受到這個系統的影響。咱們就考慮這個系統怎麼改進。首先是推模式,這確定是延遲的首要緣由,咱們要把這個問題解決掉。其次咱們的用戶愈來愈多,這個數據庫表從一百萬到一億,數據規模不同處理方式是有差異的。咱們初版單庫單表的模式,當用戶數量增多的時候,它不能知足就須要進行拆分。第二個是鎖表的問題,咱們考慮的是更改引擎。另一個是發表過慢,咱們考慮的是異步模式。服務器
第二版咱們進行了模塊化,咱們首先作了一個分層,最底層叫基礎層,首先對數據作了拆分,圖上最右邊是發表作了異步模式。第二個服務層,咱們把微博基礎的單元設計成服務層一個一個模塊,最大改進是對推模式進行了改進。首先看一下投遞模式的優化,首先咱們要思考推模式,若是咱們作一下改進把用戶分紅有效和無效的用戶。咱們一個用戶好比說有一百個粉絲,我發一條微博的時候不須要推給一百個粉絲,由於可能有50個粉絲不會立刻來看,這樣同步推送給他們,至關於作無用功。咱們把用戶分紅有效和無效以後,咱們把他們作一下區分,好比說當天登錄過的人咱們分紅有效用戶的話,只須要發送給當天登錄過的粉絲,這樣壓力立刻就減輕了,另外投遞的延遲也減少了。網絡
咱們再看數據的拆分,數據拆分有不少方式,不少互聯網產品最經常使用的方法,好比說如能夠按照用戶的UID來拆分。可是微博用戶的一個特色就是說你們訪問的都是最近的數據,因此咱們考慮微博的數據咱們按照時間拆分,好比說一個月放一張表,這樣就解決了咱們不一樣時間的維度能夠有不一樣的拆分方式。第二個考慮就是要把內容和索引分開存放。假如說一條微博發表的uid,微博id是索引數據,140個字的內容是內容數據。假如咱們分開的話,內容就簡單的變成了一種key-value的方式,key-value是最容易擴展的一種數據。索引數據的拆分具備挑戰,好比說一個用戶發表了一千條微博,這一千條微博咱們接口前端要分頁訪問,好比說用戶須要訪問第五頁,那咱們須要迅速定位到這個記錄。架構
假如說咱們把這個索引拆分紅一個月一張表,咱們記錄上很難判斷第五頁在哪張表裏,咱們須要加載全部的索引表。若是這個地方不能拆分,那咱們系統上就會有一個很是大的瓶頸。最後咱們想了一個方法,就是索引上作了一個二次索引,把每月記錄的偏移記下來,就是一個月這個用戶發表了多少條,ID是哪裏,就是按照這些數據迅速把記錄找出來。併發
異步處理,發表是一個很是繁重的操做,它要入庫、統計索引、進入後臺,若是咱們要把全部的索引都作完用戶須要前端等待很長的時間,若是有一個環節失敗的話,用戶獲得的提示是發表失敗,可是入庫已經成功,這樣會帶來數據不一致問題。因此咱們作了一個異步操做,就是發表成功咱們就提示成功,而後在後臺慢慢的消息隊列慢慢的作完。另外新浪發表了一個很重要的產品叫作MemcacheQ,咱們去年作了一個對大規模部署很是有利的指令,就是statsqueue,適合大規模運維。負載均衡
第二版咱們作了這些改進以後,微博的用戶和訪問量並無中止,還有不少新的問題出現。好比說系統問題,單點故障致使的雪崩,第二個是訪問速度問題由於國內網絡環境複雜,會有用戶反映說在不一樣地區訪問圖片、js這些速度會有問題。另一個是數據壓力以及峯值,MySql複製延遲、慢查詢,另外就是熱門事件,好比說世界盃,可能會致使用戶每秒發表的內容達到幾千條。咱們考慮如何改進,首先系統方面容許任意模塊失敗。另外靜態內容,第一步咱們用CDN來加速,另外數據的壓力以及峯值,咱們須要將數據、功能、部署儘量的拆分,而後提早進行容量規劃。
另外一方面咱們還有平臺化的需求,去年11月咱們就說要作開放平臺,開放平臺的需求是有差別的,Web系統它有用戶行爲纔有請求,可是API系統特別是客戶端的應用,只要用戶一開機就會有請求,直到他關閉電腦這種請求一直會不間斷的過來,另外用戶行爲很難預測。
系統規模在持續的增大,另外也有平臺化的需求,咱們新架構應該怎麼作才能知足這些須要?咱們看一下同行,好比說Google怎麼樣考慮這個問題的?Google首席科學家講過一句話,就是一個大的複雜的系統,應該要分解成不少小的服務。好比說咱們在Google.com執行一個搜索查詢的話,實際上這個操做會調動內部一百多個服務。所以,咱們第三版的考慮就是先有服務纔有接口最後纔有應用,咱們才能把這個系統作大。
如今咱們看一下第三版,首先咱們把底層的東西分紅基礎服務,基礎服務裏面有分佈式的存儲,咱們作了一些去中心化、自動化的操做。在基礎服務之上有平臺服務,咱們把微博經常使用的應用作成各類小的服務。而後咱們還有應用服務,這個是專門考慮平臺各類應用的需求。最上面咱們有API,API就是新浪微博各類第三方應用都在上面跑。
平臺服務和應用服務是分開的,這樣實現了模塊隔離,即便應用服務訪問量過大的話,平臺服務不會首先影響。另外咱們把微博的引擎進行了改進,實現了一個分層關係。用戶的關注關係,咱們改爲一個多唯度的索引結構,性能極大的提升。第四個層面就是計數器的改進,新版咱們改爲了基於偏移的思路,就是一個用戶他原來讀的一個ID好比說是10000,系統最系的ID是10002的話,咱們很清楚他有兩條未讀。原來的版本是採用絕對計數的,這個用戶有幾條未讀都是用一個存儲結構的話,就容易產生一致性的問題,採用這種偏移的技術基本上不會出錯。
另外基礎服務DB冷熱分離多維度拆分,在微博裏面咱們是按照時間拆分的,可是一個大型的系統裏面有不少業務須要有不一樣的考慮。好比說私信這個就不能按照時間來拆分,這個按照UID來拆分可能更簡單。而後咱們突出存儲還作了一個去中心化,就是用戶上傳圖片的速度會極大的提升,另外察看其餘用戶的圖片速度也會極大的提升。另外是動態內容支持多IDC同時更新,這個是在國內比較新穎的。
下面給你們介紹一下新浪微博怎麼樣打造一個高性能架構。到目前爲止有五千萬用戶使用新浪微博,最高發表3000條以上每秒,而後一個明星用戶發表的話,會被幾百萬用戶同時讀到。這些問題的本質是咱們架構須要考慮高訪問量、海量數據的狀況下三個問題。易於擴展、低延遲、高可用和異地分佈。咱們天天有數十億次外部網頁以及API接口的需求,咱們知道微博的特色是用戶請求是沒法cache的。所以面對這個需求咱們怎麼樣擴展?幾點思路。第一咱們的模塊設計上要去狀態,咱們任意一個單元能夠支持任意節點。另外是去中心化,避免單點及瓶頸。另外是可線性擴展。最後一個是減小模塊。
咱們要作一個高性能的系統,要具有一個低延遲、高實時性,微博要作到高實時性這是核心的價值,實時性的核心就是讓數據離CPU最近,避免磁盤的
IO。咱們看淘寶核心系統專家餘鋒說過的一句話「CPU訪問L1就像從書桌拿一本書,L2是從書架拿一本書,L3是從客廳桌子上拿一本書,訪問主存就像騎車去社區圖書館拿一書」。咱們微博若是要作到很是實時的話,咱們就須要把數據儘可能離CPU節點最近。因此咱們看一下cache設計裏面怎麼達到這個目標。首先INBOX,這個數據咱們須要放再一個最快的地方,由於用戶隨時訪問。OutBOX裏面的最近發表就是L1cache,還有一個是中期的,這個由於訪問少一點,它能夠被踢。最後一部份內容體有三部分。L0是本地的,咱們須要把一些常常訪問的,好比說明星發表微博的內容體本地化,由於它被訪問的機率很是大。而後L1裏面存放着最近發表的,還有一個是中期的。咱們一般用L2就能夠了,L1咱們能夠理解成它就是一個RAM存儲。
一個好的架構還須要舉行高可用性。咱們看一下業界的指標,S3是99.9%,EC2是99.5%,咱們另一個同行Facebook在這方面它是沒有承諾的,就是接口可用寫。微博平臺目前承諾的是99.95%,就是說一天365天故障率應該小於9小時。這個怎麼達到?第一咱們要作容量規劃,要作好監控以及入口的管理,就是說有些服務若是訪問量過了的話,咱們要有一個開關能夠攔住他。咱們經過這個圖表能夠清楚的看到,好比說咱們要作L1的cache,咱們剩餘空間有多少,好比說80%,就說明這個數據有可能會丟失,有可能會對咱們的系統形成影響。
另一個層面就是接口監控,咱們目前有Google維度的接口監控,包括訪問錯誤失敗率。而後要作架構,給你們一個很重要的經驗分享,就是說監控的指標儘可能量化。好比說他延遲30秒是小問題,若是是延遲10分鐘咱們就要當即採起措施了,就是全部能夠量化的指標都要量化。
而後咱們看監控怎麼樣更好的作?咱們看亞馬遜的VP說過的一句話,就是說監控系統確實特別好,能夠當即告訴咱們哪裏有故障,可是有20%的機率咱們人是會出錯的。因此咱們一個大型系統就應該要爲自動化設計,就是說盡量的將一些運做自動化。好比說發佈安裝、服務、啓用、中止。咱們再看另一句,Google的工程師是怎麼作的。他是這麼作的,好比說第一週是處理線上的業務,這一週他處理了不少事情,處理了不少系統的狀況,剩下幾周時間沒有別的工做,他只要把這一週碰到的狀況用程序的方法來解決,下次再碰到這種狀況很簡單的一個按鈕就能夠處理了。咱們目前也在向自動化這方面努力,就是咱們的工具在持續增長。
另一個異地分佈,在國內網絡環境下,好比說IDC災難,機房檢修甚至是機房掉電,咱們也碰到過中國最好的機房也會掉電,因此要每一個服務單元都能支持多機房部署。另外作多機房部署有一個好處,就是用戶的訪問速度會提升。多IDC分佈靜態內容就不說了,基本上大的互聯網公司都會作,它很是成熟基本上沒有什麼問題,好比說圖片等等的靜態內容。動態內容的CDN分佈是業內的難點,國內不多有公司可以作到很是成熟的多機房動態內容發佈的成熟方案,它的核心就是分佈式存儲。一款理想的分佈式存儲產品它有哪些需求呢?首先它要支持海量規模、可擴展、高性能、低延遲、高可用。第二個是須要多機房分佈,可以知足國內負責的網絡環境,還要具有異地容災能力。第三個就是要調用簡單,具有豐富數據庫特性。所以分佈式存儲須要解決一個多對多的數據複製。
若是要作複製無非是三種策略,第一個是Master/Slave,可是它也兩個缺點,第一個是Master是中心化的,若是Master在北京那廣州訪問就很是慢。第二個缺點是有單點風險的,好比說Master在北京,能當即遷到廣州嗎?這樣有個時間窗口的數據就丟失了,並且須要人工的干預,並且平常廣州的用戶訪問北京的Master是有很大延遲問題的,因此通常來講要作的很是優秀是不會考慮第一種方案的。第二種就是Multi-Master方案,它須要應用避免衝突,就是咱們不能多處改變。這個對於微博來講不會特別難,咱們的用戶一般只會再一個地方發表微博,用戶不會同時在廣州又在北京發表或者是修改本身的資料,這樣的話咱們應用上就已經避免了這種狀況。第三個就是Paxos就是能夠達到強一致寫,就是一條數據若是成功確定是多個機房都成功了,這個也顯而易見就是延遲性很是大。所以總結一下Multi-Master是最成熟的策略,可是它如今沒有成熟的產品,由於確實沒有。
咱們再來看微博的方案,因此咱們本身實現了一個多機房同步的方案。就是咱們前端應用將數據寫到數據庫,再經過一個消息代理,至關於經過咱們本身開發的一個技術,將數據廣播到多個機房。這個不但能夠作到兩個機房,並且能夠作到三個、四個。具體的方式就是經過消息廣播方式將數據多點分佈,就是說咱們的數據提交給一個代理,這個代理幫咱們把這些數據同步到多個機房,那咱們應用不須要關心這個數據是怎麼樣同步過去的。
用這種消息代理方式有什麼好處呢?能夠看一下Yahoo是怎麼來作的?第一個是數據提供以後沒有寫到db以後是不會消失的,我只要把數據提交成功就能夠了,不須要關心數據怎麼到達機房。第二個特色YMB是一款消息代理的產品,可是它惟一神奇的地方是爲廣域網設計的,它能夠把多機房應用歸到內部,咱們應用不須要關注這個問題。這個原理跟咱們目前本身開發的技術類似。
而後咱們再看一下目前即將推出的微博平臺的新架構。咱們知道API大部分的請求都爲了獲取最新的數據。API請求有一個特色,它大目前調用都是空返回的,好比說一款手機的客戶端每隔一分鐘它都要調用服務器一下,就是有沒有新數據,大目前的調用都是空返回,就是說無論服務器有沒有數據都要調用一次。此次詢問到下一次詢問中間,若是有新的數據來了,你是不會立刻知道的。所以咱們想API能不能改用推的方式,就是客戶端不須要持續的調用,若是有新數據就會推過去。技術特色,顯而易見低延遲,就是從發表到接受1秒內完成,實際上可能用不了1秒。而後服務端的鏈接就是高併發長鏈接服務,就是多點都鏈接在咱們的服務器上,這個比傳統的API要大不少。
咱們看一下推送架構怎麼從架構底層作到實時性的。java培訓機構從左上角的一條微博在咱們系統發佈以後,咱們把它放在一個消息隊列裏面,而後會有一個消息隊列的處理程序把它拿過來,處理之後放到db裏面。假如說咱們不作持久化,由於咱們推送數據也不能丟失,咱們就要寫一個很複雜的程序,將數據異步去存,這樣就會很是複雜,並且系統也會有不穩定的因素。從另一個角度來講,咱們作持久化也是作過測試的。咱們推送整個流程能夠作到100毫秒和200毫秒之間,就是說咱們在這個時間能把數據推送出去。
咱們再看一下內部細節,就是咱們收到數據以後首先要通過最上面RECEIVER。而後推到咱們的引擎裏面,這個引擎會作兩個事情,首先會把用戶的關係拿過來,而後按照用戶關係立刻推送給他相應的粉絲。因此咱們調用方已經在那兒等待了,咱們須要有一個喚醒操做,就是說在接口這兒把它喚醒,而後把它發送過去。最後是一個高併發的長連服務器,就是一臺服務器支持10萬以上的併發鏈接。最右邊中間有一個圓圈叫作Stream Buffer,咱們須要Stream Buffer是要保存用戶最近的數據。由於用戶可能會有斷線的,好比說他發送數據的時候斷線半分鐘,咱們須要把這半分鐘補給他。這就是咱們的推送架構。
下面介紹一下平臺安所有分。因爲咱們的接口是徹底開放的,因此咱們要防範不少惡意行爲,有不少人擔憂咱們接口是開放的,是否是有人經過這個接口發垃圾廣告,或者是刷粉絲,咱們技術架構怎麼來防範這一點呢?這是咱們的安全架構,作了三個層面的事情。最上面是咱們有一個實時處理,好比說根據頻度、內容的類似性來進行判斷,判斷髮的是否是廣告或者是垃圾內容。中間這個是一個日誌處理器,咱們會根據一些行爲進行判斷,好比說若是咱們只是實時攔截的話,有些行爲很難防止,咱們作了個離線糾正的模塊,好比說他潛伏的幾個月開始發廣告了,咱們能夠過後把這些人清除掉,以保證咱們平臺的健康。最後是經過監控的維度來保證內容的安全。目前內容安全的架構大概是541的體系,就是說咱們的實時攔截能夠作到50%的防止,離線分析大概能夠作到40%的防止。
微博平臺須要爲用戶提供安全及良好的體驗應用,以及爲開發者營造一個公平的環境,因此咱們的接口須要清晰安全的規則。從一個APP調用咱們的接口,須要幾個階層,須要劃分不一樣的業務模塊。第二個是安全層。第三個是權限層。這是咱們平臺安全的兩個維度,一個接口安全,一個是內容安全。
我今天講的是架構方面的問題,在座大部分是開發者,可能你們都在處理不一樣的架構問題,架構不少地方是相通的。咱們須要作一個軟件系統須要解決的本質問題是什麼?微博初版解決發佈規模問題,第二版是解決數據規模的問題,第三版是解決服務化的問題。將複雜的問題簡單化以後,咱們才能夠設計出一個容易擴展的大規模架構。我今天介紹就這麼多,咱們微博其實是很須要各方面的技術人員,你們對咱們的架構若是感興趣的話、對咱們的系統感興趣的話,也但願各方面的技術人員參與咱們微博的團隊,隨時能夠給我微博上發私信。