在面試某搜索公司時,面試官問了我memcache並發的處理問題,自己平常沒有考慮這么多,只是簡單的set和get,差距還是很大吶
下面是收集到的一些memcache的並發控制的文章。
http://hi.baidu.com/chen_cong_520/item/1f5a230c93fd513cf2eafc29
memcached的原子性操作
memcached是原子的嗎?
當然!好吧,讓我們來明確一下:
所有的被發送到memcached的單個命令是完全原子的。如果您針對同一份數據同時發送了一個set命令和一個get命令,它們不會影響對方。它們將被串行化、先后執行。即使在多線程模式,所有的命令都是原子的,除非程序有bug:)
命令序列不是原子的。如果您通過get命令獲取了一個item,修改了它,然后想把它set回memcached,我們不保證這個item沒有被其他進程(process,未必是操作系統中的進程)操作過。在並發的情況下,您也可能覆寫了一個被其他進程set的item。
memcached 1.2.5以及更高版本,提供了gets和cas命令,它們可以解決上面的問題。如果您使用gets命令查詢某個key的item,memcached會 給您返回該item當前值的唯一標識。如果您覆寫了這個item並想把它寫回到memcached中,您可以通過cas命令把那個唯一標識一起發送給 memcached。如果該item存放在memcached中的唯一標識與您提供的一致,您的寫操作將會成功。如果另一個進程在這期間也修改了這個 item,那么該item存放在memcached中的唯一標識將會改變,您的寫操作就會失敗。
<?php
$m = new Memcached();
$m->addServer('localhost', 11211);
do {
/* 獲取ip列表以及它的標記 */
$ips = $m->get('ip_block', null, $cas);
/* 如果列表不存在, 創建並進行一個原子添加(如果其他客戶端已經添加, 這里就返回false)*/
if ($m->getResultCode() == Memcached::RES_NOTFOUND) {
$ips = array($_SERVER['REMOTE_ADDR']);
$m->add('ip_block', $ips);
/* 其他情況下,添加ip到列表中, 並以cas方式去存儲, 這樣當其他客戶端修改過, 則返回false */
} else {
$ips[] = $_SERVER['REMOTE_ADDR'];
$m->cas($cas, 'ip_block', $ips);
}
} while ($m->getResultCode() != Memcached::RES_SUCCESS);
?>
