天天看點

Memcached曆險記

[url=http://code.google.com/p/memcached/wiki/TutorialCachingStory]點選檢視英文原文[/url]

兩個勇敢的冒險者,程式員和系統管理者,開始了一段旅程。他們一起搭建一個基于web server和database的網站。網上的使用者與web server互動,并請求獲得他們所需要的頁面。web server請求databases以獲得資料來建構頁面。在這個項目中,程式員進行編碼,而系統管理者負責web server 和database的安裝與部署。

某天,管理者發現他們的資料庫系統快要跨掉了,幾乎也不能負載得起web server的請求了。程式員咨詢起管理者該怎麼辦,這時管理者想起了一個叫memcached的項目,它曾真真切切的使用在livejournal項目中,并取得了很好的效果。程式員高興的說:“非常好,咱們也試一下吧”。

勇敢的管理者分析下目前的web server,發現已經有了6個web servers。他決定使用其中的三個用為memcached server,并為每個web server添加一個G的記憶體空間,然後把每個memcached的緩存空間限定為1G,并啟動了memcached server。現在,他已經擁有了三個memcached 執行個體,并且每個都能負載1G的資料容量。這時程式員和管理者開始回過頭來并分析如何使用這神奇的memcached。

他們發現memcached還不能正确的工作,因為memcached server裡并未緩存任何内容,而目前databases的負載已經更高了。勇敢的程式員拿來了pecl/memcache用戶端使用手冊,并自信地說“不要擔心,我知道怎麼辦了”。然後取到了三個memcache server的IP位址及端口,并添加到一個php的數組中:如下

$MEMCACHE_SERVERS = array(
    "10.1.1.1", //web1
    "10.1.1.2", //web2
    "10.1.1.3", //web3
);
           

然後他定義了個Memcache執行個體,并把上面得到的server加入其中:

$memcache = new Memcache();
foreach($MEMCACHE_SERVERS as $server){
    $memcache->addServer ( $server );
}
           

完成這些工作後,程式員陷入了深思,突然眼睛一亮:“我知道了,在網站的首頁上會運作這個SQL'SELECT * FROM hugetable WHERE timestamp > lastweek ORDER BY timestamp ASC LIMIT 5000',但這個語句會耗時5秒鐘,我可以把這個查詢的結果放到memcached裡。”他改變了原有的SELECT語句,并開始使用了$memcache對象,在程式中會判斷這個查詢是否已經緩存到了memcache server裡,如果還沒有就到databases裡查詢并把結果放到memcache裡,如下:

$huge_data_for_frong_page = $memcache->get("huge_data_for_frong_page");
if($huge_data_for_frong_page === false){
    $huge_data_for_frong_page = array();
    $sql = "SELECT * FROM hugetable WHERE timestamp > lastweek ORDER BY timestamp ASC LIMIT 50000";
    $res = mysql_query($sql, $mysql_connection);
    while($rec = mysql_fetch_assoc($res)){
        $huge_data_for_frong_page[] = $rec;
    }
    // cache for 10 minutes
    $memcache->set("huge_data_for_frong_page", $huge_data_for_frong_page, 600);
}
           

程式員送出了代碼,”汗,資料庫負載降到了原來的一半。“管理者驚喜的叫喊着。現在網站速度又變得相當快了。”那麼,“管理者猜測,”到底發生了什麼呢“。”我把資料放到了memcached server裡。通過cacti,我看到資料隻發送到了一台memchace server上,可我部署了三台memcached server啊“,管理者想着。管理者快速檢視ascii protocol并telnet到memcached server的11211端口。

”嗨,'get huge_data_for_front_page'在這嗎?“,管理者問道。

這一台memcached server沒有回答,第二台也沒有回答。即便如此,第三台memchaced server把一堆資料顯示在了目前的telnet會話終端上。”這是要查詢的資料,“管理者自言自語道,”原來隻有一個memcached server會緩存程式的資料“。

管理者感到很困惑,他就到郵件清單上去尋找答案,而他們卻一緻的回答道:這是一個分部式緩存,正如它所做的,資料隻會緩存到一台機器上。但是,這對于應用來說又意味着什麼呢,管理者依然很茫然。經過掙紮之後,他決定請程式員再cache一些資料到memcached server裡。”讓我們看到memcached到底做了些什麼,雖然我們是些奇怪的想法,但我們确信能找到答案。“管理者說着。

”呃,這還有一個查詢,雖然不太慢,但每秒會有100次請求。也許緩存起來也應該有用的“,程式員說。說着,他說按着上次的做法,把這個查詢操作也與memcached結合起來進行了重構。然後他們發現,系統負載又降了不少。

有了上面的效果,程式員對越來越多的查詢做了重構。多神奇的東西啊,程式員說,現在DB負載已經降到很低了。

現在,管理者又telnet到這三台memcached server上,此時些三台server都在運作,并且對于每台機器的查詢請求,都有結果傳回。這下管理者終于放心了,所有的memcached server都在正常的使用。

但是他不解的是程式中的資料是如何映射到memcached server上的呢,也就是說為何有些查詢在某個server上沒有結果,而在另外一個server有傳回呢。”難道就不能把每個key映射到所有的memcached上嗎?“管理者想着。

”等一下,我給每個memcached配置設定了1G記憶體,也就是說現在我總共可以緩存3G的資料了,而不是1G。呃,原來如此“管理者松了口氣。

”但是,web server還在運作,可突然某個memcached server當機了會怎麼樣?“為了确信會發現什麼,管理者把其中一台memcached server給停掉了。這時他再觀察DB的負載,稍有上升,但并沒有表現出負載壓力,同時另外兩台memcached server還在運作并有資料傳輸。”不會太壞,隻是一部分的緩存丢失了,另外的memcached server還會有效,不會一下子把所有的請求扔給database。“,管理者想着。終于找着答案了,管理者把網停掉的memcached server重新啟動起來了。

經過上面的曆險,程式員和管理者繼續他們的網站開發,并不停的在應用中使用緩存,而db也不再有壓力了。進而每個人都過上了開心的生活。

繼續閱讀