聽豆瓣架構變遷分享會總結

王滔發表於2013-12-21

要點如下:


目前23臺pc server


每天pv數2k萬左右。註冊使用者數300萬。
表的資料,大部分是行數量是千萬的。

5個人演算法團隊。另外開發人員總共11個,包括全職和兼職(以前看百姓網分享其技術也只有10名)

06年的時候每天120萬左右動態請求。這個時候主要瓶頸在磁碟i/0上面,拿到風投,有錢購買硬體裝置。購買兩臺iu伺服器(雙核,4g記憶體)
一臺作為應用伺服器,一臺作為資料庫伺服器,遷移到雙線ip機房,使用dns解析不同網段ip(自己去找哪些網段是電信的哪些網段是網通,然後自己進行解析)。看演講後面提到的機房調整感覺到,其實這是走了彎路,可以選擇一個好的機房來解決dns解析方面(後來總結是靠ip段來分佈資料不靠譜)

具體怎麼做,就是放到一個支援多線的(教育網鐵通等)機房,現在我們公司用的阿里雲就是多線)
那麼這樣子就不需要自己多ip段分配了(就是判斷訪問使用者是電信還是網通等)。

使用記憶體快取(豆瓣使用的是memcached)的兩點原則:


1、對於需要比較消耗資源的資料。比如需要大量計算才能得到結果,那麼預先計算好,放入到快取中供查詢。
2、需要重複使用的資料。如果只需要使用一次,那麼即便是比較消耗資源,丟入快取也沒多少意義

理解:記憶體快取也需要記憶體,沒必要浪費。如果不需要重複使用,丟入記憶體中也比較浪費(畢竟記憶體不便宜,也佔用伺服器資源)

豆瓣的memached命中率挺高的。靠這個也緩解了很多壓力。



innodb併發訪問支援好,因為支援行級儲存。使用myisam還是innodb他們的的業務特點是:讀多寫少使用myisam,寫多讀少使用innodb

資料庫切分方面:目前是按照功能進行分割槽(作者沒有詳細解釋,應該是按照功能模組劃分表。一個功能模組相關的表放到一個庫中去),提到,採用了經典的mysql主從架構。所以每個庫其實是重複三份的(他說的主輔庫)。應該是三個mysql從伺服器

分庫之後,操作多個庫,使用遊標的方式獲取具體的庫和具體的表。傳入引數進去(具體沒看懂)

 

其實,水平切分維護起來很麻煩,比較複雜。先還是垂直拆分為好。實在滿足不了了。後面考慮水平拆分。



資料庫主從複製延遲問題一直是一個常見問題。

購買硬碟是一個教訓:剛開始還是寧願投資多點錢購買好的點的磁碟,因為磁碟這東西升級不太可能。到時候網站扛不住了。仍然得換。那麼,剛開始寧願多花點錢,購買高速磁碟,因為業務如果發展快了的話,就得換。即便開始貴點,應用遠遠沒達到硬碟瓶頸,磁碟仍然沒有被浪費。



200萬每天的動態請求的時候,豆瓣提到,靜態的小檔案服務(使用者頭像、封面圖片)使得磁碟i/0成為瓶頸,以前愚蠢得把圖片都放到一個目錄下面,這個目錄下面有幾十萬個小檔案(直接導致不能使用ls命令,一使用伺服器就死掉了),這個時候把檔案分目 錄。分成每個目錄儲存10000個檔案。



有專門的資料探勘團隊。演算法團隊進行矩陣計算,把結果放入mysql,供前端查詢顯示出來。


豆瓣的fs是專門針對圖片儲存,自己開發的。其實機制是參考了amazon的,寫的時候寫三份資料。


磁碟隨機尋道比吞吐量更加重要,當時的效能瓶頸在磁碟尋道速度上(這點跟之前看淘寶的圖片檔案系統分析的大量的圖片訪問帶來的磁碟磁頭頻繁定位造成的延時類似)


後來把所有myisam表改為innodb表。

innodb的快取:是在程式中自我管理(也就是記憶體中),而myisam的快取是基於檔案中(受作業系統控制)。以前既用myisam表也用innodb表,導致兩種型別的表相互競爭記憶體,效率不高。索引全部換成innodb儲存引擎(這點我不是很理解,只明白其考慮點是為了更好利用記憶體)



應用伺服器故障:nginx自帶功能。


圖片的流量成為很大成本:遷移到天津機房是因為更加便宜點。機櫃比較便宜,把資料探勘方面的資料和圖片資料都搬過去。

北京與天津兩個機房。裡面各自搭建mysql的master-slave結構。



搜尋方面:以前一直使用mysql的全文索引。後來遷移使用sphinx(這個結合mysql來使用,作為mysql的一個儲存引擎),後來又變為xapain

為什麼沒使用sphinx了?沒有詳細解釋


使用MogileFS來儲存圖片,後來又自己開發了doubanfs儲存。遷移的原因:mogilefs出現效能瓶頸,由於mogilefs是把後設資料(名稱空間, 和檔案在哪裡)儲存在mysql中,資料庫行數變多之後,就會變得越來越慢。而大量的小檔案需要讀取資料庫,也影響了速度。當時的行數增長非常快,當時瓶頸在於mysql資料庫上。



大欄位影響了資料庫的效能,實際上資料錶行數並不多。就是大欄位的影響。大文字欄位移除出去,儲存到自己開發的doubanDB中(是一個key-value資料庫,參考了亞馬遜的dymamo,進行簡化)。底層儲存基於tokyocabinet。後來把doubanfs重寫,基於doubandb實現,把圖片儲存進去。


使用雙master方案。解決了複製延遲問題,因為寫和讀都是對同一個master,讀取到的資料是最新的。而以前:從master寫入,然後從slave讀,存在資料延遲



部署lvs。

之前使用spread作為訊息佇列,後來使用rabbitMQ替代

 

 

關於mysql資料庫進行線上ddl

 

聽過豆瓣網的架構變遷分享會中提到,他們以前在這方面也吃過苦頭的,一張很大的表(比如上千萬),線上加個索引,由於資料量大,整個應用就卡死了。

其實有時候卡幾個小時可能都很正常。死鎖了嘛。另外對臨時表要進行復制資料,建立這個臨時表也需要時間嘛。

 

他們現在用的辦法是:先拷貝一張一模一樣的表,數量也是差不多,先在這張表上面測試,看看需要多長時間。如果幾分鐘,是在可以接受的時間範圍內,就可以。如果幾個小時就不行了。這樣子提早預先知道。

另外,也使用了online-schema-change這個工具(沒明說,不過我從他們運維另外一篇文章分享教訓的時候看到過)

 

這是很多大資料表線上ddl都會碰到麻煩,後來我專門總結了業界對此常見的辦法:http://www.cnblogs.com/wangtao_20/p/3504395.html



=========================================================


總結:照搬其架構和技術方案是不可行的。借鑑他的錯誤經驗和背後的設計思想才能學到本質(主要了解為什麼那樣子做,出於什麼考慮)。

教訓:磁碟的選擇和機房的選擇。磁碟選擇轉數快的,開始成本貴點值得。

分庫,首先從功能角度劃分割槽。暫時還沒必要去做水平分割槽。功能相關表放到一個庫中或者單獨的伺服器上這是必經的階段。

把錢花在記憶體上是值得的的,一臺機器的記憶體永遠不嫌多,資料庫消耗的記憶體比較多,一般記憶體往往會成為瓶頸(大量連線,計算資料都能導致記憶體不夠用)。memcached並不廉價(網路i/0,消耗cpu)。放入memcached的東西要慎重。

避免資料庫的join操作(這點與以前看的石展分享的觀點類似,減少join操作,寧願拆分成多次獲取資料,facebook的架構中也提到不做JOIN 操作)



總體感覺,從豆瓣中學到資料庫方面的經驗是分庫方面。他們的訪問量級別還不需要進行到水平切分,進行分庫即可了,按照業務功能分割槽。一個業務功能模組相關的表都拆分到同一個庫中去。然後對資料庫伺服器做主從同步保持資料熱備份。

Sharding 在業界的應用場景基本上也就是這種讀應用比較重的情況,而且對事務的安全性要求不高,這樣的場景會非常適合。

sata*3查了一下 450G 1000多塊錢一個。

sata硬碟故障率比較高,換了scsi硬碟。

針對圖片儲存或者小檔案儲存方面,因為量大(流量成本,儲存成本),開發了自己的檔案系統

圖片儲存如果依賴於資料庫做儲存,資料量大之後,確實會成為瓶頸(難怪淘寶的圖片檔案系統,將一部分後設資料隱藏到圖片的儲存檔名上)


疑問:北京和天津跨機房,兩邊的mysql之間進行同步資料,或者是天津那邊的資料探勘程式往北京寫入資料,這個速度如何?

這個我查了一下資料,一般是需要使用專用光釺網路通道。

相關文章