在没有cas的Memcached中实现原子计数器

Rya*_*yan 2 php algorithm memcached transactions

我们有一个网页想要限制uo到100个人可以同时访问,所以我们使用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";
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,上面的代码中存在竞争条件,但如果我们不打算替换memcached扩展哪个支持cas,它只能使用PHP代码支持它吗?

Int*_*ice 7

作为"emcconville"的答案.即使没有CAS,这也是无阻塞的.

如果您关注竞争条件,并且计数值完全是任意的,您可以Memcache::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');

}
Run Code Online (Sandbox Code Playgroud)


emc*_*lle 6

如果您关注竞争条件,并且计数值完全是任意的,您可以Memcache::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');

}
Run Code Online (Sandbox Code Playgroud)