1
我使用的內存緩存使用CakePHP。可以將單個的memcache可以通過兩種不同的工藝在同一時間更新?
我運行一個多線程的過程,更新內存緩存鍵。
因此,有一個10%的可能性兩個不同的過程結束更新相同的內存緩存密鑰,這將引發錯誤。
任何人都可以幫助我解決這個問題。
我使用的內存緩存使用CakePHP。可以將單個的memcache可以通過兩種不同的工藝在同一時間更新?
我運行一個多線程的過程,更新內存緩存鍵。
因此,有一個10%的可能性兩個不同的過程結束更新相同的內存緩存密鑰,這將引發錯誤。
任何人都可以幫助我解決這個問題。
可以「鎖定」使用如下代碼設置前的關鍵。
此代碼假定您有儀器換PHP庫:
http://code.google.com/p/instrumentation-for-php
註釋掉儀器行,如果你不想使用它
function acquire_mutex_or_wait($key,$memcache = false) {
Instrumentation::get_instance()->increment('memcache_mutex_requests', 1);
if($memcache === false) {
#bring in memcache from global scope
global $memcache;
}
#prepend LOCK:: to the key to designate the new key as a lock for the given key
$key = "LOCK::$key";
#generate a random number for the lock (see below)
$lockval = mt_rand(1,2^31);
#add is SUPPOSED to be atomic, but it isn't really with multiple servers
#to protect against two connections getting the mutex we initialize it
#to a random value and check the value after setting. If we didn't
#really aquire the mutex, the value we get will be different from the
#value we set
$got_lock = $memcache->add($key, $lockval);
if($got_lock) {
$got_lock = $memcache->get($key);
$got_lock = $got_lock === $lockval;
if($got_lock) return true;
}
#the mutex was not acquired. we must wait for it to be released
$sleep_time = .01; #initial sleep time
$sleep_time_increment = .05;
$max_sleep_time=1; #maximum number of seconds to sleep between checking locks
Instrumentation::get_instance()->timer();
Instrumentation::get_instance()->increment('memcache_mutex_waits', 1);
while(1) {
usleep($sleep_time * 1000000);
$sleep_time += $sleep_time_increment;
if($sleep_time > $max_sleep_time) $sleep_time = $max_sleep_time;
$exists = $memcache->get($key);
if(!$exists) break; #mutex has been released
}
Instrumentation::get_instance()->increment('memcache_mutex_wait_time', Instrumentation::get_instance()->timer());
return false;
}
#NOTE - only the connection that acquired a mutex should release it. there is no
#protection to ensure this is the case
function release_mutex($key, $memcache = false) {
if($memcache === false) {
#bring in memcache from global scope
global $memcache;
}
$key = "LOCK::$key";
return($memcache->delete($key));
}