m

全干工程师

php借助redis和memcached实现一个悲观锁控制和乐观锁控制

在高并发的时候,我们取数据库的时候(比如抽奖机会),会导致用户只有一次机会抽多次的情况.在这种情况,解决方式就是给整个抽奖环节加上锁处理,在使用PHP处理的时候我们要借助外部的资源来实现这一功能。下面我们将通过redis和memcached来实现这个功能

Redis版本:

$redis = new Redis();
$redis->connect('127.0.0.1');
//setNx  @see https://github.com/phpredis/phpredis#setnx
//如果这个设置失败就进行循环
while( !$redis->setNx('LOCK', 1)) { 
//意思就是当并发的时候,设置一个锁KEY,由于 redis是单进程单线程,命令执行是要排队处理的,只有一个用户会成功,后续的请求处理都要等到下面的$redis->delete('LOCK')处理里完才会进行.
    这里不做任何操作
}
//这句话,在并发时候用户可能只有一次机会,但是由于每次请求获得的都是1
$lottery = $this->getLotteryCount();

if ($lottery > 0) {
    //这里是抽奖逻辑
    $this->lottery();
}
$redis->delete('LOCK');

Memcached版本:

$m = new memcached();
$m->addServer("127.0.0.1", 11211);
do {
    $isLock = $m->get($lockCacheKey, null, $cas);
    if ($m->getResultCode() == \Memcached::RES_NOTFOUND) {  
        $m->add($lockCacheKey, 1);
        try {
            //业务逻辑,比如抽奖还有其它需要加锁的业务
        } catch(Exception $e) {
            
        }
        $m->delete($lockCacheKey);
    } else {
        $isLock += 1;
        $m->cas($cas, $lockCacheKey, $isLock, 300);
    }
} while ($m->getResultCode() != \Memcached::RES_SUCCESS);
//memcached实现是通过cas版本实现的乐观锁
//文档地址: http://php.net/manual/zh/memcached.cas.php

 

留言