php memcached set function lock -
i use php memcached implement token code below:
function addtokenkey($token) { $alltokens = $this->memcache->get("alltokens"); if(gettype($alltokens) == "boolean") { $array = array(); array_push($array,$token); $this->memcache->set("alltokens",$array); echo "addtokenkey 1.2:".count($array)."<br>"; } else{ echo "addtokenkey 2.1:".count($alltokens)."<br>"; array_push($alltokens,$token); $this->memcache->set("alltokens",$alltokens); echo "addtokenkey 2.2:".count($alltokens)."<br>"; } }
i send mulitple request call function @ same time
but sometime same result,ex:
request result
addtokenkey 2.1:5
addtokenkey 2.2:6
another request result
addtokenkey 2.1:5
addtokenkey 2.2:6
how avoid case happen? lock or ..?
refer to:https://github.com/zerkalica/semaphore
i use library try lock & release,the code below:
function addtokenkey($token) { $adapter = new memcachedadapter($this->memcache); $semaphore = new semaphoremanager($adapter); $ttl = 60; // time in seconds, used, if script dies , release never called. $handle = $semaphore->acquire('addtokenkey_lock_key', $ttl); $alltokens = $this->memcache->get("alltokens"); if($alltokens == false) { //array_push($alltokens,$token); $array = array(); array_push($array,$token); $this->memcache->set("alltokens",$array); echo "addtokenkey 1.2:".count($array)."<br>"; } else{ echo "addtokenkey 2.1:".count($alltokens)."<br>"; array_push($alltokens,$token); $result = $this->memcache->set("alltokens",$alltokens); echo "addtokenkey 2.2:".count($alltokens)." ".$result."<br>"; } $semaphore->release($handle); }
but got 2 error
fatal error: uncaught exception 'errorexception' message 'can't acquire lock millwright_semaphoreaddtokenkey_lock_key' in /xxxxxxx/server/lib/semaphore/semaphoremanager.php on line 50
fatal error: uncaught exception 'logicexception' message 'call ::acquire('millwright_semaphoremillwright_semaphoreaddtokenkey_lock_key') first' in /xxxxxxx/server/lib/semaphore/semaphoremanager.php on line 65
i fix error in semaphoremanager.php removing "$this->prefix ." code
but still have miss array count problem.
i modify code below try,
i send 100 request,finally alltokens number 50,
others show "unable set"
function addtokenkey($token) { // initialize lock $lock = false; // initialize configurable parameters $tries = 0; $max_tries = 1000; $lock_ttl = 10; $alltokens = $this->memcache->get("alltokens"); while($lock === false && $tries < $max_tries ) { if( $alltokens == false ) { $alltokens = array(); array_push($alltokens,$token); $this->memcache->set("alltokens",$alltokens); echo "addtokenkey 1.2:".count($alltokens)."<br>"; return; } $count = count($alltokens) ; // add() return false if raced lock // use add() custom locks $lock = $this->memcache->add("lock_".$count, 1, $lock_ttl); $tries++; usleep(100*($tries%($max_tries/10))); // exponential backoff style of sleep } if($lock === false && $tries >= $max_tries) { print("unable set"); } else { echo "addtokenkey 2.1:".count($alltokens)."<br>"; array_push($alltokens,$token); $this->memcache->set("alltokens",$alltokens); echo "addtokenkey 2.2:".count($alltokens)."<br>"; } }
finally use memcached getallkeys function fix problem,don't diy record alltokens function can use in linux memcached, windows memcache don't support getallkeys
in normal senario, issue not visible creating problem when there n number of concurrent requests. , because memecache update not atomic normal get/set. use memcached increment/decrement insuring atomicity setting integer valued keys senario there concurrency in requests. since memcached increment() atomic itself, need not put locking mechanism. yes , acheiveing atomicity other race conditions , have apply custom locking etc insure atomicity concurrent requests.
try below , check it:
$mem = new memcache; $mem->addserver("127.0.0.1", 11211); function incrementuservisits($useridfromrequest) { global $mem; $key = "visit_".$useridfromrequest; $count = $mem->increment($key, 1); if( $count === false ) { $count = $mem->add($key, 1, 0, 0); if($count === false) { $count = $mem->increment($key, 1); if($count === false) { return false; } else { return true; } } else { return true; } } else { return true; } } incrementuservisits($useridfromrequest);
you can try below code ( have managed combine/build after bit of research) have not tested syntax error feels in achieving custom lock handle race conditions.
$mem = new memcache; $mem->addserver("127.0.0.1", 11211); function addtokenkey($token) { global $mem; // initialize lock $lock = false; // initialize configurable parameters $tries = 0; $max_tries = 1000; $lock_ttl = 10; $alltokens = $mem->get("alltokens"); while($lock === false && $tries < $max_tries ) { if( gettype($alltokens) == "boolean" ) { $alltokens = array(); array_push($alltokens,$token); $mem->set("alltokens",$alltokens); echo "addtokenkey 1.2:".count($alltokens)."<br>"; } $count = count($alltokens) ; // add() return false if raced lock // use add() custom locks $lock = $mem->add("lock_".$count, 1, 0, $lock_ttl); $tries++; usleep(100*($tries%($max_tries/10))); // exponential backoff style of sleep } if($lock === false && $tries >= $max_tries) { print("unable set"); } else { echo "addtokenkey 2.1:".count($alltokens)."<br>"; array_push($alltokens,$token); $mem->set("alltokens",$alltokens, 0, 0); echo "addtokenkey 2.2:".count($alltokens)."<br>"; } } addtokenkey('xxx111');
apology error think can play , can achieve looking for.
Comments
Post a Comment