關鍵字包括:nginx,lighttpd,quixote,Memcached,mogile FS,Mako,Gentoo Linux,Xapian,spread
ps:竊覺得第一段關於語言的採訪,至關[csdn]化
你要是願意,就買一枝三塊錢的玫瑰,送給我吧,這城市也是怪讓人傷心的,我想死心塌地的愛上你」
這是一個叫鍾童茜的歌手的歌,我在豆瓣網站發現有人評論,才知道了這首有些淒涼的歌曲。你幾乎不可能從百度的最流行的mp3的列表中找到它,由於它不是那麼有名,也許是這個緣由,引起了我採訪豆瓣的願望。接受我採訪的是,豆瓣網站的技術總監洪強寧先生和產品經理張貝寧女士。
本刊記者:好,如今開始,豆瓣是一個很是著名的Web2.0網站,大家的開發語言選擇的是Python,我想問的是,爲何選擇python?
洪強寧:咱們選擇Python的理由是它是動態語言,具備動態語言的優勢,好比開發特別迅速。咱們作的是一個Web2.0的網站,這種網站的特色就是always beta,用戶的需求在隨時發生變化,咱們也不斷髮現新的價值。因此網站的結構和程序會不斷變化,若是用Java作,你的開發量比較大,你就難以作出迅速地改變。Python的特色就是開發迅速,你能夠在一兩個小時,就作出一個功能。或者說已??上線了,用戶反映須要某一功能,也能夠比較快地作出來。
本刊記者:這就是TDD,敏捷開發的思路,和傳統的方式有些不一樣。可是會有另外一方面的問題,Python的程序員好找嗎?在國內會Python的要比會Java程序員少的多。
洪強寧:對,確實是。在中國用Python的人確實很少,也給咱們尋找開發任何人員帶來困難。不過從另外一方面說,也有好處,由於沒有一個學校去教Python,會Python的人都是本身學的,也就是說他知道本身須要什麼技術,並且可以經過自學掌握它,包括Python的資料中文比較少,須要學習者接觸第一手資料,這都使得Python程序員的平均水平,要比使用其餘熱門語言的平均水平要高。另外一方面Python也愈來愈流行,在國外比較流行的動態語言有Perl,和Python,如今Python已經超過了Perl。
本刊記者:不過,在Web開發這方面有許多選擇,好比,Java,.NET,和PHP,在這個格局裏Python仍是比較弱勢。
洪強寧:對,固然,它是新興語言。在將來,我相信,至少在在Web2.0網站開發方面,它會有本身的一個位置。
本刊記者:還有問一個問題,Python與Perl比較怎麼樣?由於Python的面向對象的特性好一些,代碼看起來更容易理解一些吧,我之前是用 Perl寫程序的,以爲Perl的程序代碼看起來比較亂。
洪強寧:對,Perl 是write once風格的,一我的寫完了,過一段時間,可能本身都不能看懂,它確實很強大,但比較適合看成我的工具使用,不太適合團隊的開發。Python的哲學是解決問題的最好方式只有一種,這樣一樣的功能,每一個人寫出來的程序樣子應該差不太多,比較易於理解,更適合團隊開發。
本刊記者:還有一個問題,,有一種說法,認爲Python比較慢,在性能方面會不會有問題?
洪強寧:這個問題能夠分兩個方面說,首先,說Python慢,這是和編譯語言比,好比與C,C++,Java比,在動態語言中,它並不慢,它比Ruby要快,它和Perl性能至關。若是選擇動態語言的話,Python並非很慢。另外一方面,若是作網站開發,語言的不是速度的瓶頸,好比我把咱們如今用Python寫的程序所有用C寫,程序固然會快一點,可是改變不是很大。Web網站通常會有不少對IO的操做,好比對數據庫的訪問,對硬盤的訪問響應用戶的請求,80%,90%你的時間都花在IO上,語言的速度,相對而言,不是那麼重要。也能夠這樣說,網站的性能主要取決於架構設計的是否合理。由於網站須要響應大量的併發的請求,若是你的設計的很差,即便你用C寫的,也可能沒法應付。因此更多的考慮是在架構設計上,要使架構體系不會產生速度瓶頸。
本刊記者:那您能簡要地介紹一下豆瓣的架構嗎?
洪強寧:關於豆瓣的系統架構圖,首先咱們在Web server上作個劃分,把網站內容分爲動態內容和靜態內容。在豆瓣上全部的html都是動態內容,圖片都是靜態內容。分紅兩個Web 服務能夠作不一樣的調優。 對動態內容,咱們用的是nginx和lighttpd的混合,nginx作負載的平衡,lighttpd經過 SCGi 與application server相連,application server是基於 quixote這個框架寫的。
application server拿到用戶的請求,分析用戶的url,而且利用外部的資源,好比數據庫,組合成一個html,返回。從數據庫存取會比較慢,數據庫有大量的IO,咱們使用cache,咱們使用的是Memcached,這是一個分佈式的內存的cache,好比你能夠用不少機器,每一個機器有兩個G的內存,咱們本身開發了client端來使用它,另外若是用戶有搜索請求,咱們會用搜索引擎。Xapian是一個C++寫的開源的搜索引擎,咱們經過Web service去訪問它。其餘,咱們還提供了另外的Web service接口響應用戶的請求,好比要訪問某個文件。spread是咱們最近加了一部分,用戶有的請求能夠採用這樣的異步服務。
數據庫是這樣的,兩個MySQL作成一對,一個master ,一個 slave,根據應用劃分,使得load不會過高。這個圖上??的是兩對,實際上有三對。還有一個slave,一方面做爲備份,一方面用做數據挖掘,由於不能對線上的數據作直接操做。
對於靜態部分,咱們也是用nginx,你注意到豆瓣如今有日記的貼圖功能系統,用戶可能上傳不少圖片,咱們採用的方案是用了mogile FS ,這是一個分佈式的文件系統,同時能夠作備份,保持高可用性,能夠提升很大的IO。
關於application server,它都是用Python寫的。咱們是用的MVC方式,Controller咱們用的是quixote ,它接受用戶的請求,根據這個URL去找到Model的某個具體的函數來執行,它是一個dispatcher,當中會判斷用戶的權限等。而後再傳給View,View根據模版進行渲染,造成網頁。View的模版,咱們之前是用的是PTL,PTL很高效,最近引用了mako,這是一個比較現代的開源的模版,用它寫出的代碼比較好維護,比PTL好維護一些.。同時,在使用mako的同時,咱們的工程師作了不少加速的工做,如今mako的代碼有不少是豆瓣的人寫的。
你若是注意過Python的Web開發框架的話,你會發現Python的有三個比較著名的框架,Django,Pylons,TurboGears,Pylons默認的模版就是Mako。
下面的就是Model,業務模塊,核心是類是User,由於Web2.0是以人爲本,咱們確定會有一個User。只有人也作不了事情,還要有物。豆瓣的物,就是Subject,好比書,好比評論,好比小組等。
與數據庫進行連接,咱們一個很輕量級的與數據庫進行連接,這也是一個開源項目,SQL Farm Manager。這個Web service,豆瓣中有不少用的都是Web service。
本刊記者:好,還想問您一個問題,Web2.0會不會也在架構設計中也有所體現呢 ?
洪強寧: Web2.0用戶的反覆的操做很是多,你須要一個很是流暢的體現。這須要一些技術來實現,好比Ajax;豆瓣花了不少錢不少精力,來提升性能,好比買好的機器,使用Gentoo linux,爲何使用Gentoo Linux,由於它方便調優。還有,大量的使用cache。在數據庫調優方面,咱們也花了很大的精力。
另外一方面,Web 2,0是用戶提供數據的,用戶有不少寫操做。這樣不少1.0優化方法在2.0中行不通。豆瓣在數據庫上用的是分庫的方式。除此以外咱們還嘗試了一些其餘的方法。
本刊記者:我如今想問張貝寧一個問題,您可否談一下Web2.0社區網站和傳統的社區網站的區別?好比天涯論壇,和豆瓣的區別。
張貝寧:先說一下Web 2.0 的概念,傳統網站,用戶到這些網站,只是看信息,這些信息是怎麼來的呢,好比像Google,它是抓來的,或者像新浪這樣的門戶網站,是用戶給你編好的。你到這樣的網站,只是獲取信息,你不能創造信息,也不能決定它放的位置。按照業界的理解,Web 2.0相對於Web 1.0,它是以用戶爲中心的,或者說是以用戶創造內容爲主,而且能夠決定展示方式。你剛纔說的傳統的社區,在某種程度上,也能夠說是2.0的,由於它也由用戶提供內容。不過早期的BBS,網站之內容做分類,好比體育,軍事,文學等。用戶不能造成本身的分類。在豆瓣,用戶能夠對任何一個話題進行討論,這徹底是用戶自主的。這還只是關係到豆瓣的小組的功能,若是拿天涯論壇和豆瓣作比較的話,豆瓣與天涯這樣的BBS不一樣還在於,它首先有一個物的概念,好比書,音樂,和電影。
本刊記者:我也發現了這點。這樣的組織方式,給人的感受會很是不一樣。好比咱們要查找對餘華的小說《活着》的評論,在豆瓣就比較容易找到認真,有質量的評論。而在傳統的BBS上,你只能用查找的方式,搜索「活着」這個詞,找出的東西,也可能還不是談論《活着》這本小說的,而只是其中的文本包含了「活着」這個詞,並且有不少無心義的吵架帖。豆瓣的組織方式,讓人感受很嚴肅,雅氣。不過,我也發現了一個或許有些不便的地方,好比,我要在討論德里達的小組回帖,在通常的BBS能夠匿名,或具備一個ID就好了,但在豆瓣,我要首先參加德里達這個小組。
張貝寧:對,是這樣的。豆瓣更關心的是人羣,就是對同一話題和事物有興趣的人羣,而不是帖子,這與傳統的BBS確實有一些區別。
本刊記者:好,就到這裏。謝謝大家兩位可以接受個人採訪,分享大家的經驗與思想。php
----------------------------------------------------------------html
此次的 QCon 會議,《豆瓣網技術架構的發展歷程》這個議題差很少是最受關注的。洪強寧在演講開始告誡你們指望值不要過高,我仍是相信不會有人以爲失望的。前端
先說幾句題外話,整個演講聽下來,咱們會發現豆瓣在發展的過程當中也是有點彎路,這些是一個網站發展過程當中的寶貴財富,能把本身有周折的地方大大方方的拿出來,是難能難得的事情。儘管豆瓣批露了不少架構細節出來,也不會(也不可能)有哪一個公司一拿到這些東西,就能照貓畫虎再作一個豆瓣而且超過豆瓣。從某種程度上來講這體現了豆瓣同窗們的氣度,這是令國內大多數公司汗顏的。不少公司只願索取,而不肯奉獻哪怕一點點出來,用這樣封閉的心態對待技術實際上是小家子氣,守財奴的思惟。技術只有爲更多人所用纔是大道。java
議論說完,再來敘述。寫點對豆瓣架構的體會。戲法人人會變,各有巧妙不一樣。有些東西你們都在用(Nginx),可是有人的用得好,有人用了比不用還差。因此,須要逐漸總結,改進。學習別人的架構設計,不是要照搬,而是借鑑其思想。python
技術的選擇mysql
一直以來,豆瓣在技術上都給人很前衛的感受,看起來好像什麼新用什麼,實際上是不是的,他們一直是"用已掌握的技術解決問題",現有的東西若是夠用,那麼就不必必定遷移到新的上面去,而轉換每每是爲了解決當前問題。另外,換用新的東西,要有足夠的駕馭能力,從演講中得知,豆瓣曾有幾回在臨上線前發現基礎庫的Bug(好比 Libmemcached 的一致性哈希相關的Bug),技術團隊能在第一時間有進行修復而且提交給開源社區。不然的話,就變成了一種錯誤決策了。linux
磁盤轉速nginx
小話題。若是可能,直接買 15000 轉的磁盤好了。10000 轉的磁盤可能省錢,但這東西部署了以後幾乎就不太可能升級。因此,若是是初創公司,個人建議就是買高速磁盤,由於業務若是發展快了的話,先前對機器的定位也可能發生變化。git
杜絕遠程 I/O 程序員
在普通的 TCP/IP 網絡的環境下,不要進行遠程數據寫入操做。跨網絡操做的延時看似沒什麼大不了的,但一旦達到臨界點就回天乏術。這個事情基本是不撞南牆不回頭,有的技術人員總要親身體驗一把才肯罷休。
持續保持 URL 友好風格
演講中有屢次提到一致性 URL ,其實體現了豆瓣對 URL Rewrite 的重視,結構調整,或者應用程序變化的時候,URL 最好作到"用戶友好"的。這算是"軟技術",可是應該加以最大的重視。
數據庫複製延遲問題
對於 mysql 複製的環境,若是Slave 上有讀取操做,那麼有些狀況下可能由於 Master 和 Slave 節點數據不一致對用戶形成困惑。若是從一致性的角度上考慮,其實也不復雜:,只須要對"知道數據發生了變化的用戶"提供一致性就好了(基本上就是發起變動的用戶),不知道數據發生變化的用戶對數據的不一致有必定的"容忍程度",固然說着簡單,實現起來仍是須要技巧和精巧的。
大量小文件同步問題:Merkle tree
關於大量小文件的同步問題,不少上了規模的網站都會遇到,若是設計得很差或者是比較偷懶,用傳統的辦法(好比 rsync 之類的老模式)很容易觸發問題,也浪費資源。DoubanFS 是用Merkle tree(Hash Tree)的方式進行數據同步的。對這個問題的具體描述能夠參見《大量小文件的實時同步方案》。Merkle Tree 是個很精巧的思路,ZFS 在用(refer),Amazon Dynamo 系統也在用。
不會一下子又有人留言說:咱們早就採用這個思路了...... 我這裏預先來句回答:拜託,你早點共享啊?
豆瓣網對互聯網用戶來講是知名的Web 2.0社區,但對開發者而言,更重要的是一個應用Python打造的很是成功的Web 2.0站點。豆瓣網已經達到了300萬註冊用戶,另外還有千萬級的非註冊用戶。訪問量天天則超過兩千萬。
豆瓣Python應用開發經驗談
豆瓣是一個Web 2.0網站,這類網站的特色就是「Always Beta」,不斷有新的產品和功能升級來爲用戶提供更好的服務。做爲使用Python進行開發的網站,豆瓣有效的程序開發配置和版本控制值得咱們學習。
豆瓣的主要開發環境配置就是SVN+Trac+Bitten。豆瓣的版本管理系統使用的是Subversion(SVN),使用Trac來管理協同開發,同時使用Trac的Bitten插件進行持續集成。
在開發模式方面,因爲是Always Beta,豆瓣採用的方式是:站點運行在主分支上,開發者在開發新功能時會創建一個子分支,新功能開發並測試完成後,會更新服務器的主分支版本,以後上線。
在開發框架方面,豆瓣主要使用Quixote(被稱之爲「堂吉訶德」,一個輕量級的Python Web框架,簡單、高效,代碼簡潔);後臺運行的Web服務主要使用Web.py(web.py也是一個Python的Web框架,簡單且功能強大)。
豆瓣網可分割成兩大塊:一塊是前端的Web,也就是用戶在瀏覽器訪問的時候會觸發一系列的操做,從數據庫拿出數據,渲染成HTML頁面反饋給用戶,這是前端;另一塊是後端,在豆瓣有一個很強的數據挖掘團隊,天天把用戶產生的數據進行分析,進行組合,而後產生出用戶推薦,而後放在數據庫裏面,前端會實時的抓取這些數據顯示給用戶。
豆瓣(架構)設計如今在WEB這一端主要是用這麼幾種技術:前端是nginx和lighttpd,中間是Quixote的Web框架,後面是MySQL以及咱們本身開發的DoubanDB。這些除了Quixote都是一些比較流行的、尖端的技術。Quixote稍微老一點,若是要從新設計的話,可能會在這方面作一些考慮。好比Python社區中的Django、Pylons等等都是能夠考慮的,那麼在豆瓣的內部的話,咱們通常是用web.py,很輕量的一個Web框架來作,也是很是不錯的選擇,它可能須要本身作的事情多一點。
豆瓣如今尚未達到數據庫分片的程度。最多見的手段是,按照功能分區。咱們會把數據表分紅幾個獨立的庫,如今是一共有4個庫。每一個表都是庫的一個部分,每一個庫會有主副兩個。經過這種方式來減輕數據庫的壓力,固然這個是如今的方案,再日後的話,表的行數會增加,到達必定的程度後,還要進行水平分割,這是確定的。而後咱們如今的技術方面,在操做數據庫以前,首先獲取數據庫的遊標,有一個方法,這個方法會幹全部的事情,咱們之後作的時候會從這個方法中進行判斷該從哪取東西。這個架構已經在了,只是如今尚未作這一步而已。
數據庫這邊主要採用什麼解決方案呢?
在數據庫這邊,咱們主要用的是MySQL。MySQL有一個問題,大文本字段會影響它的性能。若是數據量過大的話,它會擠佔索引的內存。那麼如今一個行之有效的方法是,咱們另外創建一套可伸縮的Key-Value數據庫,叫作DoubanDB。咱們把不須要索引的大文本字段,放到DoubanDB裏面去。MySQL只保存須要索引的Relationship這方面的信息。這樣給MySQL數據庫下降了壓力,也就能夠保證它的性能。
好比說像保證數據的安全性,以及數據庫的吞吐量,豆瓣是怎樣的策略呢?
首先DoubanDB會把每一個數據在三個節點進行備份,任何一個出現故障都不會影響索取數據。MySQL是經過雙Master方案,同時還會帶1到2個slave,因此說在MySQL中咱們會有三到四個的備份。這點是能夠放心的。
你剛纔說到MySQL的雙Master方案,這方面會不會存在什麼問題?好比說同步的問題,等等?
在MySQL裏面,雙Master方案是一個比較經典的方案,咱們如今用它很大一部分是爲了解決咱們同步延遲的問題。在作切換的時候,會出現同步延遲的問題,但其實MySQL的同步速度仍是能夠的,在切換的時候,咱們會忍受幾秒鐘等待同步的時間。在作腳本的切換的時候,咱們會稍微等一下。
豆瓣的數據表通常是怎麼樣的規模?
數據表,這個很差說了,由於不一樣的表都是不同的。咱們最大的表是「九點」的Entry表,「九點」的爬蟲爬過來的全部的文章,如今應該有四千萬左右的行數。而後其餘的上百萬的表也有不少。還有包括收藏表也有千萬級的行數。
在這種海量數據的狀況下,對數據表的就結構變動,必定是一個比較麻煩的問題。常見的狀況,好比增長一個新的索引,會致使索引好幾個小時。像豆瓣以前會存在這樣的問題,是怎麼解決的呢?
這個問題曾經讓咱們吃過苦頭,在忽視它的情況下就去改表,而後就鎖了很長時間。後來咱們意識到這個問題,若是有表的改動的話,咱們會先在一個測試的庫上試驗一下它的時間長短,是否是在可接受的範圍,若是是可接受的範圍,好比說幾分鐘,就作一個定時任務,在深夜裏面去執行。若是耗時是不可忍受的,就必須經過其餘技術手段,咱們如今的手段通常是建一個新表,這個新表從舊錶同步數據,而後再寫數據的時候,也會同步,往兩邊寫,一直到兩邊徹底同樣了,再把舊錶刪掉,大概是這樣一個方式。
剛纔您好像提過大家設計了本身的DoubanDB,還有一個是DoubanFS,這二者關係是怎麼樣的?
首先是先出來的DoubanFS,咱們剛開始的時候用MogileFS來解決咱們可擴展圖片存儲的問題,因爲MogileFS有一個重型數據庫,這成爲了它的性能瓶頸。咱們爲了解決這個問題,開發了DoubanFS,基於哈希來尋找節點。以後,咱們又發現了新的問題,數據庫中的大文本字段也會影響性能。因此,咱們在DoubanFS的基礎上,換了一個底層,作了一些調整,參照Amazon的dynamo思想,搭建了DoubanDB,把文本字段放在DoubanDB裏面。作完以後,又反過來用DoubanDB來實現FS,大體是這麼一個過程。
DoubanFS跟DoubanDB的實現,他們在對於內容的安全性,或者內容的冗餘性…
都是(備份)三份。這都是能夠配置的,如今的配置是3份。
DoubanDB就是用什麼機制實現的?
DoubanDB簡單來講是這樣子:你來一個Key,它是Key-Value數據庫,你要寫或讀的時候,經過這個Key來尋找這個值。拿一個Key對它作哈希,經過Consistent哈希方法去查找它在哪一個節點上,而後往這個節點上去寫或讀。在這個節點上,順着哈希的wheel順次的找到第2、三個節點,寫的時候會保證這三個節點都寫,讀的時候是任意一個,若是其中一個讀失敗了,會自動切換到下一個。
您剛纔提DoubanDB的話,是採用的技術是?
DoubanDB的底層存儲用的是TokyoCabinet,是一個很輕量級、高效的Key-Value數據庫。咱們在它的基礎之上,作了分佈式,用這種方式來實現的。
實際上有一些其餘的方案能夠解決,好比說像Berkeley DB(簡稱BDB)、CouchDB等等,大家爲何要選擇TokyoCabinet?
最簡單的緣由是因爲它足夠快,實際上BDB跟它比較相似,BDB更增強大一些。對咱們而言,咱們在這邊就是須要一個可靠、高效的Key-Value存儲,這兩個實際上是咱們均可以替換的,只要統一下接口就能夠。CouchDB的話就是另一個東西了,它是一個文檔型數據庫,它不只僅作了一個Key-Value的工做,它還在這上面作了不少其餘的事情,好比它有View的概念,能夠進行query。這些TokyoCabinet是沒有的,而咱們暫時也不須要這些功能。CouchDB是一個頗有意思的數據庫,咱們可能會在其餘方面(應用),咱們也在研究它。
在豆瓣專門有一個算法團隊,他們的主要工做就是數據挖掘。這邊講技術實現的話,可能就講不完了。只能講一些大概,數據挖掘是怎麼和前端結合起來的,讓用戶看見的。天天用戶在豆瓣上的操做都會產生不少數據,在豆瓣上面看到的東西,收藏的東西,都會存在數據庫或是訪問日誌。天天這些信息都會傳到算法團隊的機器上,而後會從這個數據中創建一個稀疏矩陣,你看過什麼,幹過什麼。他們維護了一個很高效的稀疏矩陣運算庫,而後用它來作各類各樣的嘗試,去看是否能獲得好的結果,一旦發現這個結果很好,就會把它寫到數據庫裏面。而後用戶在訪問的時候,前端從數據庫中取出推薦給你的數據,而後把這些數據作一些過濾(好比你讀過的東西就再也不給你展示了)、調整,最後展示給用戶。基本上是這麼一個邏輯。
關於Python
Python語言的歷史能夠參考《Guido Rossum:打造Google第三大開發語言》
關於Subversion
Subversion(簡稱SVN)是一款開源的版本控制管理系統,被認爲是CVS的替代者。Subversion的版本庫能夠經過網絡訪問,從而使用戶能夠在不一樣的電腦上進行操做。從某種程度上來講,容許用戶在各自的空間裏修改和管理同一組數據能夠促進團隊協做。
關於Trac
Trac是一個開源軟件平臺,集成了Wiki和問題跟蹤管理系統。Trac以簡單的方式創建了一個軟件項目管理的Web應用,以幫助開發人員更好地寫出高質量的軟件。Trac採用Python語言開發的,所以Trac的在運行的時候,須要有Python環境的支持。
關於Quixote
Quixote是一個Python的Web框架,它基於簡單靈活的方案設計,能夠進行快速地開發項目,並且使用不少Python第三方模塊。經過恰當地配置,可讓Quixote發揮巨大能量,這使得它能夠被用於大規模系統當中。