高并发的时候,对关键业务的数据保护,一般是用mysql加锁,有表锁行锁共享排锁一堆。。我选择了redis分布式锁,have a look at the code:
composer require signe/redlock-php
引入这个包之后,代码里面可以这样写:
private function unlock($key)
{
$servers = [[
$this->config['cache']['redis']['hosts'],
$this->config['cache']['redis']['ports'],
30,
$this->config['cache']['redis']['auth'],
$this->config['cache']['redis']['select'],
]];
$redlock = new RedLock($servers);
return $redlock->unlock($key);
}
private function lock($key, $time = 1000, $retry = 3) { //Cache::getInstance()->delete(md5(3410) . 'showTree');exit; $servers = [[ $this->config['cache']['redis']['hosts'], $this->config['cache']['redis']['ports'], 30, $this->config['cache']['redis']['auth'], $this->config['cache']['redis']['select'], ]]; $redlock = new RedLock($servers, $retry); return $redlock->lock($key, $time); }
$count = 0; do { if ($lock = $this->lock('recharge_add_lower_level ') . $orders['user_id']) { Db::table('t_user')->where('id', $orders['user_id'])->increment('amount', 3000);//$orders['total_amount'] $this->addLowerLevel($inviter_id, $orders['user_id']); $this->unlock($lock); break;//正常退出 } if ($count > 5) ret(2, '', '锁定金额失败:' . date('Y-m-d H:i:s'));//超时退出 usleep(200000); $count++; } while (true);
这里遇到一个坑,这个包里默认连接redis是选择db0的,如果需要自由选择db,需要修改这个包的代码:
\vendor\signe\redlock-php\src\RedLock.php
at line:160
if ($db)
$redis->select($db);
改完之后如下图(增加了161-162两行):