function withLock($lockKey, $callback, $maxRetries = 50, $lockExpire = 20)
{
$lock = Redis::set($lockKey, 1, 'EX', $lockExpire, 'NX');
$time = timestamp_to_datatime(timestamp(), true);
echo ("[$time] req: " . getreq('reqGuid') . ', lock: ' . ($lock ? 'true' : 'false') . ', retry remain: ' . $maxRetries . "\n");
if ($lock) {
try {
return $callback();
} finally {
Cache::push(getreq('reqGuid'), $lockKey); //记录锁的key 在中间件返回前清除
}
}
// 获取锁失败,等待后重试
if ($maxRetries > 0) {
echo("sleep start\n");
Timer::sleep(0.1); // 等待100ms
echo("sleep finish\n");
return withLock($lockKey, $callback, $maxRetries - 1, $lockExpire);
}
return error('系统繁忙,请重试');
}
function getContractNo(){
$pre = "666"; //假设开头都是666
$lockKey = 'testContractNO_lock_' . md5($pre);
return withLock($lockKey, function () use ($Model, $pre) {
$contractNo = Db::name('test')->where('like', $pre . '%')->max('contractno');
if (!$contractNo) {
$contractNo = $pre . '00001';
} else {
$maxNo = substr($contractNo, -5);
$newNo = (int) $maxNo + 1;
while (strlen((string) $newNo) < 5) {
$newNo = '0' . $newNo;
}
$contractNo = $pre . $newNo;
}
return $contractNo;
});
}
$time = timestamp_to_datatime(timestamp(), true);
echo ("[$time] req: " . getreq('reqGuid') . " createData start\n");
//事务开始
......
$contractNo = getContractNo();
//写入数据库
......
//事务结束
echo ("[$time] req: " . getreq('reqGuid') . " createData finish\n");
webman5.1 fiber
正常请求的时候应该是

这样输出
但是用apifox做并发测试
会出现

从创建 start 后 直接就done的情况
然后一旦真的进入sleep 所有进程都会卡死 求助一下 卡壳半天了