m meShell 全干工程师 2023/06/01 22:14 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');PHPCopy 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.phpPHPCopy