function get_my_data2() {
$cache_id = "mykey";
$data = $memcache_obj->get($cache_id);
if ( !$data ) {
// check to see if someone has already set the lock
$data_lock = $memcache_obj->get($cache_id . ‘_qry_lock’);
if ( $data_lock ) {
$lock_counter = 0;
// loop until you find that the lock has been released. that implies that the query has finished
do while ( $data_lock ) {
// you may only want to wait for a specified period of time.
// one second is usually sufficient since your goal is to always have sub-second response time
// if you query takes more than 1 second, you should consider "warming" your cached data via a cron job
if ( $lock_counter > $max_time_to_wait ) {
$lock_failed = true;
break;
}
// you really want this to be a fraction of a second so the user waits as little as possible
// for the simplicity of example, I’m using the sleep function.
sleep(1);
$data_lock = $memcache_obj->get($cache_id . ‘_qry_lock’);
}
// if the loop is completed, that either means the user waited for too long
// or that the lock has been removed. try to get the cached data again; it should exist now
$data = $memcache_obj->get($cache_id);
if ( $data ) {
return $data;
}
}
// set a lock for 2 seconds
$memcache_obj->set($cache_id . ‘_qry_lock’, true, 2);
$data = get_data_from_db_function();
$memcache_obj->set($cache_id, $data, $sec_to_cache_for);
// don’t forget to remove the lock
$memcache_obj->delete($cache_id . ‘_qry_lock’);
}
return $data;
}
function get_my_data3() {
$cache_id = "mykey";
$data = $memcache_obj->get($cache_id);
// if there is cached data and the expire timestamp has already expired or is within the next 2 minutes
// then we want the user to freshen up the cached data
if ( $data && ($data[‘cache_expires_timestamp’] – time()) < 120 ) {
// if the semaphore lock has already been set, just return the data like you normally would.
if ( $memcache_obj->get($cache_id . ‘_expire_lock’) ) {
return $data;
}
// now we want to set the lock and have the user freshen the data.
$memcache_obj->set($cache_id . ‘_expire_lock’, true, 2);
// by unsetting the data it will cause the data gather logic below to execute.
unset($data);
}
if ( !$data ) {
// be sure to include all of the semaphore logic from example 2
// set the _qry_lock for 2 seconds
$memcache_obj->set($cache_id . ‘_qry_lock’, true, 2);
$raw_data = get_data_from_db_function();
$data[‘cache_expires_timestamp’] = time() + $sec_to_cache_for;
$data[‘cached_data’] = $raw_data;
$memcache_obj->set($cache_id, $data, $sec_to_cache_for);
// remove the _qry_lock
$memcache_obj->delete($cache_id . ‘_qry_lock’);
// remove the _expires_lock
$memcache_obj->delete($cache_id . ‘_expires_lock’);
}
return $data;
}
更多资料:
Memcached FAQ中也有详细介绍 How
to prevent clobbering updates, stampeding requests