用memcached做分頁緩存,可能很多人會覺得麻煩而不用。因為在增加、修改、刪除的過程中,你不知道會影響到哪些數據,而如果把所有分頁相關的數據緩存都刪除並重新生成一遍,實現又很麻煩,甚至不可行,所以干脆就用mysql直接分頁,簡單方便,但是這樣性能卻也下降了。 本章就講一個簡單的實現用memcached做分頁緩存的方法。
首 先假使我們有一個文章頁需要做分頁顯示,分頁類型有按分類分頁,按最新分頁,按熱點分頁,按自定義方式分頁,等等。這就出現了一個比較棘手的問題,我們對 數據的更新影響到哪些分頁我們是不可知的,不知道需要刪除哪些相關的緩存。你可能會想,更新數據時刪除所有類型分頁的緩存不就好了。那我問你,有多少種分 頁類型,每個類型各有多少頁,key的組成方式各是什么,如果分頁帶有其他get查詢參數,你怎么知道get都傳遞了哪些值,不知道這些,你怎么刪除全部分頁緩存。
講到這里,你可能會覺得有點失望吧,不是嗎,沒想到用memcached做 分頁緩存原來這么麻煩。那么,有沒有簡單的解決方案?答案是肯定的,請相信,我寫這篇文章的目的,就是來告訴你一個簡單的解決方案來的。說了這么多,其實 我們需要解決的核心問題就只有一個,我們增加、修改、刪除文章數據時,能夠讓分頁的緩存都失效。解決方案也很簡單,我們只需要引入版本號就可以了,在所有 受影響的memcached的key中都加入版本號,當我們增加、修改、刪除文章數據時,版本號+1,這樣就等於所有分頁相關的緩存都失效了。
實現代碼如下:
- <?php
- //備注:假使下面函數都已經已經初始化$memcached了
- class Article
- {
- private $article_version = 'article_version';
- public function getArticle($type='new',$page='1',$limit=0){
- //設置memcached的key,在key的末端加上版本號
- $cache_id = 'art_type'.$type.'_page'.$page.'_limit'.$limit.'v_'.$this->_getArticleVersion();
- //得到分頁數據
- $artdata = $memcached->get($cache_id);
- if( FALSE === $artdata) {
- //重新從數據庫得到數據並設置新的memcached緩存
- }
- return $artdata;
- }
- public function updateArticle($conditions,$data){
- //更新數據庫數據操作
- //更新Article的版本,這樣所有Article表相關的緩存就都失效了,下次調用getArticle函數的時候將生成新的緩存數據
- $this->_setArticleVersion();
- }
- private function _getArticleVersion(){
- $article_version_num = $memcached->get($this->article_version);
- if( FALSE === $article_version_num){
- $article_version_num = 1;
- $memcached->set($this->article_version, $article_version_num, 86400);
- }
- return $article_version_num;
- }
- private function _setArticleVersion(){
- $article_version_num = $memcached->get($this->article_version);
- $article_version_num++;
- $memcached->set($this->article_version, $article_version_num, 86400);
- }
- }
- ?>
是不是很簡單?也就是比平常的memcached緩存多了兩個函數_ getArticleVersion()和_ setArticleVersion(),這樣當我們有增加、修改、刪除文章的時候,就調用_ setArticleVersion()函數,使版本號+1,也就是之前版本的數據都失效了,由於在獲得文章分頁緩存數據時key都有加入_ getArticleVersion(),所以得不到新版本號的緩存數據,就從數據庫查到,然后生成新版本的緩存,舊的緩存在時間過期之后會自動釋放內存空間。