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