目前,用到memcache的公司和網站也越來越多。memcache的用戶端操作一般都隻提供了get,set等簡單的操作,這些操作都是非常高效的。 雖然memcache是個key-value存儲的系統,但是在某些時候,我們可能需要周遊memcache的資料。
memcache的stats指令包括:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauYjM5cmbvlXZkVHavw1LcpDc0RHaiojIsJye.png)
stats
stats reset
stats malloc
stats maps
stats sizes
stats slabs
stats items
stats cachedump slab_id limit_num
stats detail [on|off|dump]
通過指令完成周遊
通過這些stats指令我們就可以完成memcache存儲的内容的周遊,ok,下面我們通過telnet直接連接配接到memcache通過這些指令來完成相關的操作。
telnet到192.168.15.225(區域網路測試機器)的memcache伺服器
執行stats items指令,可以看到出現 很多的items行。
貼上一段php實作的周遊memcache資料的代碼,其他語言可以參考代碼自己實作。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauYjM5cmbvlXZkVHavw1LcpDc0RHaiojIsJye.png)
<?php
$host='localhost';
$port=11211;
$mem=new memcache();
$mem->connect($host,$port);
$items=$mem->getextendedstats ('items');
$items=$items["$host:$port"]['items'];
foreach($items as $key=>$values){
$number=$key;
$str=$mem->getextendedstats ("cachedump",$number,0);
$line=$str["$host:$port"];
if( is_array($line) && count($line)>0){
foreach($line as $key=>$value){
echo "<pre>".$key.'=>';
print_r($mem->get($key));
echo "</pre><br/>";
}
}
}
?>
memcached如何實作高性能批量删除,插入
memcached 的批量删除,向來是 memcached 使用者很頭疼的事情,因為 memcached 采取的緩存方案是哈希表結構,是以沒有辦法實作 delete from tablename where key like ‘%xx%’ 類似這樣的批量删除功能。是以不得不自己采取一些政策實作批量删除。常見的删除方案主要有以下兩種:
第一種方案:通過記錄 key 到 db 然後循環删除。
其實這也是最正常的删除方法,最容易想到,可能大部分人首先都會這麼考慮。具體方法如下:
1. 添加業務資料時,在向 memcached 緩存 set 資料的時候,将其 key 記錄到資料庫(或記憶體中,或檔案中,由于資料量大,記憶體中基本不可行),也就是每 set 一條資料到 memcached 緩存中,就向記錄 key 的資料表(這類專門用于輔助删除緩存的表可以按業務分類建表,為了友善,我們下文簡稱 keytable, 因為不可能所有的 key 都用一張表,即使按業務分類建,資料量也是很龐大的) insert 一條記錄。資料表結構可以設計為這兩個字段: key( 對應緩存 key), id( 對應業務實體 id) ,這裡的存儲 id 主要是友善批量查詢出需要從緩存删除的 key 時友善 , 也可以根據實際業務設計。
2. 删除業務資料時,首先從資料庫的業務資料表删除資料,然後從 keytable 中查詢出 keylist. 查詢語句類似, select key from keytable where 條件 ,再然後循環 keylist 從 memcached 緩存中 remove 掉相應的記錄,最後删除 keytable表中相應的記錄,删除語句類似 delete key from keytable where 條件.
這種方法的優點:方案設計思路簡單,符合正常思維,而且能達到精确删除的目的。
這種方法的缺點:删除代價比較高,需要資料庫或其他存儲媒體輔助,而且實際應用中,緩存量是很大的,會導緻大量頻繁的對 keytable 表的 insert 操作,性能問題将會很嚴重,需要根據具體情況運用。
這種方案主要是利用 memcached 緩存根據 lru 算法進行定期自動清理不用或少用的緩存,通過對 key 增加版本管理來實作。
該方案的具體方法如下(拿商品資料舉例說明):
1. 對緩存中的每個 key 進行版本管理,比如緩存商品資料的 key 為 product_10001.0, 這裡的 product 表示商品這類業務資料, product_10001 表示具體的商品對象 10001 , 0 表示版本号。
2. 在 memcached 中維護一版本記錄資料,這個很簡單,比如整個系統隻有商品,訂單,使用者這三類緩存資料,則在memcached 中隻維護三個 key ,類似 product_version,book_version,user_version. 他們的取值範圍為 0-99 之間循環,之所有循環是防止資料版本多了無限增大,管理麻煩,而且數字大了占用空間大(要對應到每個 key 的值)。
3. 删除商品資料時,首先從資料庫删除對應商品資料的記錄。然後更新對應商品的版本: product_version = product_version+1 (記得當 product_version=99 時, product_version=0 )。
4. 從 memcached 中 get 資料時,需要 get 兩次,首次按 get 對應業務資料的版本号,如 product_version ,然後根據資料本身的 key+ 最新的 product_version 作為真正的 key 去取資料。這樣删除了的資料自動為過期資料, memcached 會根據 lru 算法清理。
5. 向 memcached 中 set 資料時,也是先取最新的 product_version ,然後将資料本身的 key+product_version 作為 key儲存資料到緩存。
這種方案的優點:減少了批量删除從 memcached 真正删除資料的麻煩。利用 memcached 自身的特點解決删除問題,符合 memcached 的設計思想。
這種方案的缺點: a. 每次 set 資料都要,先 get 版本,然後 set, 性能上差不多降低了 1 倍,雖然性能方面還是不錯。不過這個問題好像沒有辦法解決,原先考慮在用戶端緩存版本,因為版本畢竟不是時時都變,但是考慮到版本資料時多程序間共享資料,是以不能這樣做,每次必須從 memcached 中取版本。否則難以保證是最新的。 b. 這種方案對記憶體上有點浪費,雖然 memcached 會根據 lru 算法清理低版本的垃圾資料,但是畢竟不是實時清理,是以必然浪費記憶體,是以記憶體不足的情況下,要仔細考慮采取此方案。