來源:http://chaoqun.17348.com/2008/08/memcached_work_with_mysql
這次是Fotolog的經驗,傳說中比Flickr更大的網站,Fotolog在21台伺服器上部署了51個memcached執行個體,總計有254G緩衝空間可用,緩衝了多達175G的內容,這個數量比很多網站的資料庫都要大的多,原文是A Bunch of Great Strategies for Using Memcached and MySQL Better Together,我這裡還是選擇性的翻譯以及按照我的理解補充,感謝Todd Hoff,總能給我們一些學習的案例,從這裡也能看出國外技術的開放態度,不似我們,其實就那麼點小九九還藏著掖著,好了,進入正題。
一、關於memcached
還不知道這個?那你去面試的時候要吃虧了,趕緊去官方網站看一下http://www.danga.com/memcached/,另外google一下用法,硬碟總是太慢,把資料存在記憶體裡面吧,如果你只有一台伺服器,推薦用一下APC(Facebook在用)或者eaccelerator或者Xcache(國人開發的),這些產品單機效果更好,如果你需要分布式的緩衝方案,那麼用memcached吧。
二、memcached如何與mysql並肩作戰?
- 通過資料庫分區來解決資料庫寫擴充的問題把資料庫分區,部署到不同的伺服器上,免得只有一個主伺服器,寫操作成為瓶頸以及可能有的“單點故障”,一般的資料庫分區主要是按照業務來分,儘可能的拆分業務,不相干的都獨立起來做成服務也好
- 前 端mysql和一堆memcached伺服器來應付讀的問題應用程式首先從memcached中擷取資料,擷取不到再從資料庫中獲得並儲存在 memcached中,以前看過一篇文章說好的應用95%的資料從memcache的中獲得,3%的資料從mysql的query cache中獲得,剩下2%才去查表,對比一下你的應用,差距有多遠?
- 通過mysql複製(master-slave)來解決讀的問題
首先mysql資料庫通過master-slave讀寫分離,多個slave來應對應用程式讀的操作。
三、為什麼不用mysql的query cache?
我們都知道mysql有個query cache,可以緩衝上次查詢的結果,可實際上幫不上太多的忙,下面是mysql quety cache的不足:
- 只能有一個執行個體
意味著你能儲存內容的上限就是你伺服器的可用記憶體,一台伺服器能有多少記憶體?你又能存多少呢?
- 只要有寫操作,mysql的query cache就失效
只要資料庫內容稍有改變,那怕改變的是其他行,mysql的query cache也會失效
- mysql的query cache只能快取資料庫資料行
意味著其他內容都不行,比如數組,比如對象,而memcached理論上可以緩衝任何內容,甚至檔案^_^
四、Fotolog的緩衝技術
- 非確定性緩衝你不確定你要的資料緩衝中有沒有,你也不知道是不是到期了,於是你就試探性的問memcached,我要的什麼 什麼資料你那有嗎?我可不要到期的資料啊,memcached告訴你說有並且給你,你就開心了,如果沒有呢,你就要從資料庫或者別的地方去擷取了,這是 memcached典型的應用。主要應用在:
1.複雜的資料需要多次讀取,你的資料庫做了分區處理,從多個資料庫中擷取資料並組合起來是一個非常大的開銷,你大可以把這些資料取出來之後存到memcached中
2.mysql query cache的一個好的替代方案,這樣資料庫其他部門改變了,只要自己沒改變就沒問題(注意資料庫更新的問題,後面會提到)
3.把關係或者列表緩衝起來,比如某個欄目下的多篇文章列表
4.被多個頁面調用並且擷取起來很慢的資料,或者是更新很慢的資料,比如文章瀏覽熱門排行榜
5.如果cache的開銷超過重新擷取的開銷,那麼不要緩衝它吧
6.標籤雲和自動建議(類似google sugest)
例如:當一個使用者上傳一個圖片,這個使用者的好友頁面上都要列出這張圖片來,那麼把它緩衝起來吧。
潛在問題:
memcached消耗的主要是伺服器記憶體,對CPU消耗很小,所以Fotolog把memcached部署在他們的應用伺服器上(貌似我們也是這樣),他們遇到了CPU搞到90%的使用率(怎麼會那麼高?哪出問題了吧)、記憶體回收(這是個大問題)等等問題。
- 狀態緩衝把應用服務的目前狀態存在memcached中主要應用在:
1.“昂貴”的操作,開銷大的操作
2.sessions會話,Flickr把session存在資料庫中,個人感覺還是存memcached比較“便宜”些,如果memecached伺服器down掉了,那麼重新登入吧。
3.記錄使用者線上資訊(我們也是這樣做的)
- 確 定性緩衝對於某些特定資料庫的全部內容,都緩衝到memcached,有一個專門的應用服務來保障你要的資料都在memcached中,其他應用服務直接 從memcached中擷取資料而不去取資料庫,因為資料庫已經全部儲存到memcached中並保持同步。主要應用在:
1.讀取伸展,所有的讀取都從memcached中獲得,資料庫沒有負載
2.”永不到期“(相對的)的資料,比如行政規劃資料,變動很小吧
3.經常調用的內容
4.使用者的認證資訊
5.使用者的概要資訊
6.使用者的參數設定
7.使用者當前常用的媒體檔案列表,比如使用者的圖片
8.使用者登入,不走資料庫,只走memcached(個人覺得這個不太好,登入資訊還是需要持久化的,用類似BDB這樣效果也不錯)
使用方式:
1.多個專門的緩衝池而不是一個大的快取服務器,多個緩衝池保障了高可用性,一個緩衝執行個體掛掉了走其他的緩衝執行個體,所有的緩衝執行個體掛掉了,走資料庫(估計資料庫抗不住^_^)
2.所有的緩衝池都用程式來維護,比如資料庫有更新時,程式自動把更新後的內容同步到多個緩衝執行個體中
3.伺服器重啟之後,緩衝要比網站先啟動,這就意味著當網站已經啟動了,所有的緩衝都可用
4.讀取的請求可以負載平衡到多個緩衝執行個體中去,高效能,高可靠性
潛在的問題:
1.你需要足夠多的記憶體來儲存那麼多的資料
2.資料以行記錄資料,而memcached以對象來儲存資料,你的邏輯要把行列的資料轉換成緩衝對象
3.要維護多個緩衝執行個體非常麻煩,Fotolog用Java/Hibernate,他們自己寫了個用戶端來輪詢
4.管理多個緩衝執行個體會增加應用程式的許多開銷,但這些開銷相對於多個緩衝得到的好處來說算不了什麼
- 主 動快取資料魔法般的出現在緩衝中,當資料庫中有更新的時候,緩衝立馬填充,更新的資料被調用的可能性更高(比如一篇新文章,看的的人當然多),是非確定性 緩衝的一種變形(原文是It’s non-deterministic caching with a twist.我覺得這樣翻譯怪怪的)。主要應用在:
1.預填充緩衝:讓memcached儘可能的少調用mysql如果內容不展現的話。
2.“預熱”緩衝:當你需要跨資料中心複製的時候
使用步驟:
1.解析資料庫更新的二進位日誌,探索資料庫更新時對memcached也進行同樣的更新
2.執行使用者自訂函數,設定觸發器調用UDF更新,具體參考http://tangent.org/586/Memcached_Functions_for_MySQL.html
3.使用BLACKHOLE策 略,傳說中Facebook也用mysql的Blackhole儲存引擎來填充緩衝,寫到Blackhole的資料複製到緩衝中,Facebook用這來 設定資料作廢以及跨國界的複製,好處是資料庫的複製不走mysql,這就意味著沒有二進位日誌以及對CPU使用不那麼多(啊?難道通過memcached 儲存二進位日誌,然後複製到不同的資料庫?有經驗的同志在這個話題上可以補充。)
- 檔案系統快取把檔案直接緩衝在memcached中,哇,夠BT的,減輕NFS的負擔,估計只緩衝那些過於熱門的圖片吧。
- 部分頁面內容緩衝如果頁面的某些部分擷取起來非常費勁,以其快取頁面面的未經處理資料還不如把頁面的部分內容直接緩衝起來直接調用
- 應用程式層級的複製通過API來更新緩衝,API的執行細節如下:1.一個應用把資料寫到某個緩衝執行個體,這個緩衝執行個體把內容複寫到其他緩衝執行個體(memcached同步)
2.自動獲得緩衝池地址以及執行個體個數
3.同時對多個緩衝執行個體更新
4.如果某個緩衝執行個體down掉了,跳到下一個執行個體,直到更新成功
整個過程非常高效以及低開銷
- 其他技巧1.多節點以應對”單點故障”2.使用熱備技術,當某個節點down掉了,另外一台服務自動替換成它的IP,這樣用戶端不用更新memcached的IP地址
3.memcached可以通過TCP/UDP訪問,持續串連可以減輕負載,系統設計成可同時承受1000個串連
4.不同的應用服務,不同的快取服務器群
5.檢查一下你的資料大小是否匹配你分配的緩衝,更多請參考http://download.tangent.org/talks/Memcached%20Study.pdf
6.不要考慮資料行緩衝,緩衝複雜的對象
7.不要在你的資料庫伺服器上跑memcached,兩個都是吃記憶體的怪獸
8.不要被TCP延遲困擾,本地的TCP/IP對記憶體複製是做了最佳化的
9.儘可能的平行處理資料
10.並不是所有的memcached的用戶端都是一樣的,仔細研究你用的語言所對應的(好像php和memcached配合的不錯)
11.儘可能的是資料到期而不是使資料無效,memcached可以設定到期時間
12.選擇一個好的緩衝標識key,比如更新的時候加上版本號碼
13.把版本號碼儲存在memcached中
作者最後的感言我就不翻譯了,貌似mysql proxy正在做一個項目,自動同步mysql以及memcached,更多參考