我们有一个想要限制uo并发访问的网页,所以我们使用memcached来实现一个全局计数器,例如
我们使用的是http://www.php.net/manual/en/class.memcache.php,所以没有cas,当前的代码类似于
$count = $memcache_obj->get('count');
if ($count < 100) {
$memcache_obj->set('count', $count+1);
echo "Welcome";
} else {
echo "No luck";
}正如你所看到的,在上面的代码中有竞态条件,但是如果我们不打算替换支持cas的memcached扩展,它是否能够仅使用PHP代码来支持它?
发布于 2012-10-30 22:22:31
如果您关心竞争条件,并且计数值完全是任意的,那么您可以在任何业务逻辑之前直接使用Memcache::increment。
increment方法将在增量发生后返回当前值;您可以对其中的结果进行比较。如果密钥尚未设置,Increment还将返回false;允许您的应用程序根据需要处理它。
$current = $memcache_obj->increment('count');
if($current === false) {
// NOT_FOUND, so let's create it
$memcache_obj->set('count',1); // <-- still risk of race-condition
echo "Your the first!";
} else if ($current < 100) {
echo "Hazah! Your under the limit.";
} else {
echo "Ah Snap! No Luck";
// If your worried about the value growing _too_ big, just drop the value down.
// $memcache_obj->decrement('count');
}发布于 2013-08-30 06:05:33
作为对"emcconville“的回答。即使没有CAS,这也是非阻塞的。
如果您关心竞争条件,并且计数值完全是任意的,那么您可以在任何业务逻辑之前直接使用Memcache::increment。
increment方法将在增量发生后返回当前值;您可以对其中的结果进行比较。如果密钥尚未设置,Increment还将返回false;允许您的应用程序根据需要处理它。
$current = $memcache_obj->increment('count');
if($current === false) {
// NOT_FOUND, so let's create it
// Will return false if has just been created by someone else.
$memcache_obj->add('count',0); // <-- no risk of race-condition
// At this point 'count' key is created by us or someone else (other server/process).
// "increment" will update 0 or whatever it is at the moment by 1.
$current = $memcache_obj->increment('count')
echo "You are the $current!";
}
if ($current < 100) {
echo "Hazah! You are under the limit. Congrats!";
} else {
echo "Ah Snap! No Luck - you reached the limit.";
// If your worried about the value growing _too_ big, just drop the value down.
// $memcache_obj->decrement('count');
}发布于 2014-11-21 18:41:22
function memcache_atomic_increment($counter_name, $delta = 1) {
$mc = new Memcache;
$mc->connect('localhost', 11211) or die("Could not connect");
while (($mc->increment($counter_name, $delta) === false) &&
($mc->add($counter_name, ($delta<0)?0:$delta, 0, 0) === false)) {
// loop until one of them succeeds
}
return intval($mc->get($counter_name));
}https://stackoverflow.com/questions/13132664
复制相似问题