1

我正在将 memcache 与 CakePHP 一起使用。

我正在运行一个更新内存缓存键的多线程进程。

因此,两个不同的进程最终更新同一个 memcache 键的概率为 10%,这会引发错误。

4

1 回答 1

0

您可以在使用如下代码设置之前“锁定”一个键。

此代码假定您拥有 Instrumentation-for-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));
} 
于 2012-08-04T08:58:36.733 回答