盲盒转盘优化-调试-加日志监控
This commit is contained in:
@@ -236,24 +236,24 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
|
|
||||||
// 2. 获取可用礼物
|
// 2. 获取可用礼物
|
||||||
$availableGifts = $this->getAvailableGifts($bag_data['id'], $totalDrawTimes);
|
$availableGifts = $this->getAvailableGifts($bag_data['id'], $totalDrawTimes);
|
||||||
// if (empty($availableGifts)) {
|
if (empty($availableGifts)) {
|
||||||
// $availableGifts = $this->resetPoolAndReload($bag_data['id']); //重置奖池并重新加载
|
$availableGifts = $this->resetPoolAndReload($bag_data['id']); //重置奖池并重新加载
|
||||||
// if (empty($availableGifts)) {
|
if (empty($availableGifts)) {
|
||||||
// throw new \Exception('重置奖池后仍无可用礼物');
|
throw new \Exception('重置奖池后仍无可用礼物');
|
||||||
// }
|
}
|
||||||
// $totalDrawTimes = 0;//总抽奖次数重置
|
$totalDrawTimes = 0;//总抽奖次数重置
|
||||||
// }
|
}
|
||||||
// 在处理奖池重置逻辑之前添加检查
|
// 在处理奖池重置逻辑之前添加检查
|
||||||
// if (!is_array($availableGifts)) {
|
if (!is_array($availableGifts)) {
|
||||||
// throw new \Exception('可用礼物数据格式错误');
|
throw new \Exception('可用礼物数据格式错误');
|
||||||
// }
|
}
|
||||||
// 3. 预加载礼物信息(减少后续查询)
|
// 3. 预加载礼物信息(减少后续查询)
|
||||||
$giftInfoMap = $this->preloadGiftInfo($availableGifts);
|
$giftInfoMap = $this->preloadGiftInfo($availableGifts);
|
||||||
|
|
||||||
// 4. 处理奖池重置逻辑 - 优化版本
|
// 4. 处理奖池重置逻辑 - 优化版本
|
||||||
$needGiftNum = count($toarray) * $num; //总需要的礼物数
|
$needGiftNum = count($toarray) * $num; //总需要的礼物数
|
||||||
$remaining_available_gifts = [];
|
$remaining_available_gifts = [];
|
||||||
$remainingGiftCount = array_sum(array_column($availableGifts, 'remaining_number')) ?? 0;
|
$remainingGiftCount = array_sum(array_column($availableGifts, 'remaining_number'));
|
||||||
|
|
||||||
if ($remainingGiftCount < $needGiftNum) {
|
if ($remainingGiftCount < $needGiftNum) {
|
||||||
// 如果当前奖池礼物不足以满足需求
|
// 如果当前奖池礼物不足以满足需求
|
||||||
@@ -335,34 +335,35 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ($i = 0; $i < $userRemainingAllocation; $i++) {
|
for ($i = 0; $i < $userRemainingAllocation; $i++) {
|
||||||
if(!empty($remaining_available_gifts)){
|
$selectedGift = $this->selectGiftWithAliasMethod($aliasTableForRemaining);
|
||||||
$randomKey = array_rand($remaining_available_gifts);
|
if ($selectedGift) {
|
||||||
$selectedGift = $remaining_available_gifts[$randomKey];
|
$gift = $giftInfoMap[$selectedGift['foreign_id']];
|
||||||
--$remaining_available_gifts[$randomKey]['remaining_number'];
|
$precomputedResults[] = [
|
||||||
if($remaining_available_gifts[$randomKey]['remaining_number'] <=0){
|
'gift_user_id' => $giftUserId,
|
||||||
unset($remaining_available_gifts[$randomKey]);
|
'gift_bag_detail' => $selectedGift,
|
||||||
}
|
'gift' => $gift,
|
||||||
if ($selectedGift) {
|
'draw_times' => $totalDrawTimes,
|
||||||
$gift = $giftInfoMap[$selectedGift['foreign_id']];
|
'periods' => $periods,
|
||||||
$precomputedResults[] = [
|
];
|
||||||
'gift_user_id' => $giftUserId,
|
// $precomputedResultss[] = [
|
||||||
'gift_bag_detail' => $selectedGift,
|
// 'gift_user_id' => $giftUserId,
|
||||||
'gift' => $gift,
|
// 'gift_bag_detail' => $selectedGift,
|
||||||
'draw_times' => $totalDrawTimes,
|
// 'gift' => $gift,
|
||||||
'periods' => $periods,
|
// 'draw_times' => $totalDrawTimes,
|
||||||
];
|
// 'periods' => $periods,
|
||||||
// $totalDrawTimes++;
|
// ];
|
||||||
$currentXlhPeriodsNum++;
|
// $totalDrawTimes++;
|
||||||
$addcurrentXlhPeriodsNum++;
|
$currentXlhPeriodsNum++;
|
||||||
|
$addcurrentXlhPeriodsNum++;
|
||||||
|
|
||||||
// 更新Alias表
|
// 更新Alias表
|
||||||
$this->updateAliasTable($aliasTableForRemaining, $selectedGift['id']);
|
$this->updateAliasTable($aliasTableForRemaining, $selectedGift['id']);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$totalDrawTimes = 0;
|
$totalDrawTimes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 再从新奖池中分配剩余所需礼物
|
// 再从新奖池中分配剩余所需礼物
|
||||||
if ($newGiftsNeeded > 0 && !empty($availableGifts)) {
|
if ($newGiftsNeeded > 0 && !empty($availableGifts)) {
|
||||||
$aliasTableForNew = $this->buildAliasTable($availableGifts);
|
$aliasTableForNew = $this->buildAliasTable($availableGifts);
|
||||||
@@ -380,52 +381,34 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
for ($i = 0; $i < $userNewAllocation; $i++) {
|
for ($i = 0; $i < $userNewAllocation; $i++) {
|
||||||
$selectedGift = $this->selectGiftWithAliasMethod($aliasTableForNew);
|
$selectedGift = $this->selectGiftWithAliasMethod($aliasTableForNew);
|
||||||
if ($selectedGift) {
|
if ($selectedGift) {
|
||||||
// 检查实际库存是否足够
|
|
||||||
if ($selectedGift['remaining_number'] <= 0) {
|
|
||||||
// 如果库存不足,重新构建 Alias 表
|
|
||||||
$aliasTableForNew = $this->buildAliasTable($availableGifts);
|
|
||||||
$selectedGift = $this->selectGiftWithAliasMethod($aliasTableForNew);
|
|
||||||
}
|
|
||||||
// 更新内存中的礼物库存
|
|
||||||
foreach ($availableGifts as &$gift) {
|
|
||||||
if ($gift['id'] == $selectedGift['id']) {
|
|
||||||
$gift['remaining_number']--;
|
|
||||||
if($gift['remaining_number'] ==0){
|
|
||||||
unset($gift);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($gift); // 清除引用
|
|
||||||
|
|
||||||
$giftInfoMap = $this->preloadGiftInfo($availableGifts);
|
$giftInfoMap = $this->preloadGiftInfo($availableGifts);
|
||||||
$gift = $giftInfoMap[$selectedGift['foreign_id']];
|
$gift = $giftInfoMap[$selectedGift['foreign_id']];
|
||||||
if($gift){
|
if($gift)
|
||||||
$precomputedResults[] = [
|
$precomputedResults[] = [
|
||||||
'gift_user_id' => $giftUserId,
|
'gift_user_id' => $giftUserId,
|
||||||
'gift_bag_detail' => $selectedGift,
|
'gift_bag_detail' => $selectedGift,
|
||||||
'gift' => $gift,
|
'gift' => $gift,
|
||||||
'draw_times' => $totalDrawTimes,
|
'draw_times' => $totalDrawTimes,
|
||||||
'periods' => $periods,
|
'periods' => $periods,
|
||||||
];
|
];
|
||||||
$precomputedResultss[] = [
|
$precomputedResultss[] = [
|
||||||
'gift_user_id' => $giftUserId,
|
'gift_user_id' => $giftUserId,
|
||||||
'gift_bag_detail' => $selectedGift,
|
'gift_bag_detail' => $selectedGift,
|
||||||
'gift' => $gift,
|
'gift' => $gift,
|
||||||
'draw_times' => $totalDrawTimes,
|
'draw_times' => $totalDrawTimes,
|
||||||
'periods' => $periods,
|
'periods' => $periods,
|
||||||
];
|
];
|
||||||
$totalDrawTimes++;
|
$totalDrawTimes++;
|
||||||
$currentXlhPeriodsNum++;
|
$currentXlhPeriodsNum++;
|
||||||
$addcurrentXlhPeriodsNum++;
|
$addcurrentXlhPeriodsNum++;
|
||||||
|
|
||||||
// 更新Alias表
|
// 更新Alias表
|
||||||
$this->updateAliasTable($aliasTableForNew, $selectedGift['id']);
|
$this->updateAliasTable($aliasTableForNew, $selectedGift['id']);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['precomputedResults' => $precomputedResults, 'precomputedResultss' => $precomputedResultss, 'addcurrentXlhPeriodsNum' => $addcurrentXlhPeriodsNum];
|
return ['precomputedResults' => $precomputedResults, 'precomputedResultss' => $precomputedResultss, 'addcurrentXlhPeriodsNum' => $addcurrentXlhPeriodsNum];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +535,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 批量更新库存(按ID排序避免死锁)
|
// 3. 批量更新库存(按ID排序避免死锁)
|
||||||
$this->batchUpdateGiftInventory($availableGiftss,$bag_data['id']);
|
$this->batchUpdateGiftInventory($availableGiftss, $room_id);
|
||||||
|
|
||||||
// 4. 批量插入礼包发放记录
|
// 4. 批量插入礼包发放记录
|
||||||
$this->batchInsertGiftBagReceiveLog($user_id, $boxTurntableLog, $bag_data, $room_id, $precomputedResults);
|
$this->batchInsertGiftBagReceiveLog($user_id, $boxTurntableLog, $bag_data, $room_id, $precomputedResults);
|
||||||
@@ -578,14 +561,14 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
];
|
];
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
db::rollback();
|
db::rollback();
|
||||||
throw new \Exception($e->getMessage());
|
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量更新礼物库存
|
* 批量更新礼物库存
|
||||||
*/
|
*/
|
||||||
private function batchUpdateGiftInventory($precomputedResults,$gift_bag_id)
|
private function batchUpdateGiftInventory($precomputedResults, $room_id)
|
||||||
{
|
{
|
||||||
// 按礼物ID分组统计需要减少的数量
|
// 按礼物ID分组统计需要减少的数量
|
||||||
$inventoryUpdates = [];
|
$inventoryUpdates = [];
|
||||||
@@ -599,33 +582,13 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
|
|
||||||
// 批量更新
|
// 批量更新
|
||||||
foreach ($inventoryUpdates as $giftId => $count) {
|
foreach ($inventoryUpdates as $giftId => $count) {
|
||||||
// 使用 FOR UPDATE 锁定记录
|
|
||||||
$giftBagDetail = Db::name("vs_gift_bag_detail")
|
|
||||||
->where('id', $giftId)
|
|
||||||
->find();
|
|
||||||
if (!$giftBagDetail) {
|
|
||||||
throw new \Exception("礼物详情不存在,ID: " . $giftId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查库存是否足够
|
|
||||||
if ($giftBagDetail['remaining_number'] < $count) {
|
|
||||||
$this->redis->setex('blind_box_draw_world_errors_' . date('Y-m-d-H-i-s'), 86400 * 7, "礼物库存不足 礼物ID:".$giftId.' 数量:'.$count.' 预处理结果:'.json_encode($precomputedResults).'礼物数量详情:'.json_encode($inventoryUpdates));
|
|
||||||
throw new \Exception("礼物库存不足,ID: " . $giftId);
|
|
||||||
}
|
|
||||||
// 执行更新
|
|
||||||
$ret = db::name("vs_gift_bag_detail")->where('id',$giftId)
|
$ret = db::name("vs_gift_bag_detail")->where('id',$giftId)
|
||||||
->setDec('remaining_number', $count);
|
->setDec('remaining_number', $count);
|
||||||
if (!$ret) {
|
if (!$ret) {
|
||||||
$this->redis->setex('blind_box_draw_world_errors_' . date('Y-m-d-H-i-s'), 86400 * 7, "更新礼物剩余数量失败 礼物ID:".$giftId.' 数量:'.$count.' 预处理结果:'.json_encode($precomputedResults));
|
Log::record('巡乐会更新礼物剩余数量: ' . $room_id."【数据】".var_export($precomputedResults, true),"info");
|
||||||
throw new \Exception('更新礼物剩余数量失败');
|
throw new \Exception('更新礼物剩余数量失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$total_remaining_number = db::name("vs_gift_bag_detail")
|
|
||||||
->where(['gift_bag_id' => $gift_bag_id])
|
|
||||||
->sum('remaining_number');
|
|
||||||
if($total_remaining_number <= 0){
|
|
||||||
$this->reset_gift_pool($gift_bag_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -715,7 +678,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
|
|
||||||
// 3. 处理巡乐会相关操作
|
// 3. 处理巡乐会相关操作
|
||||||
if (!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $precomputedResults[0]['gift_bag_detail']['gift_bag_id']) {
|
if (!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $precomputedResults[0]['gift_bag_detail']['gift_bag_id']) {
|
||||||
$this->handleXlhOperations($room_id, $xlh_ext, $currentXlhPeriodsNum,$addcurrentXlhPeriodsNum);
|
$this->handleXlhOperations($room_id, $xlh_ext, $currentXlhPeriodsNum,$addcurrentXlhPeriodsNum,$room);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,7 +779,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
/**
|
/**
|
||||||
* 处理巡乐会相关操作
|
* 处理巡乐会相关操作
|
||||||
*/
|
*/
|
||||||
private function handleXlhOperations($room_id, $xlh_ext, $currentXlhPeriodsNum,$addcurrentXlhPeriodsNum)
|
private function handleXlhOperations($room_id, $xlh_ext, $currentXlhPeriodsNum,$addcurrentXlhPeriodsNum,$room)
|
||||||
{
|
{
|
||||||
$xlhIsPiaoPing = 0;
|
$xlhIsPiaoPing = 0;
|
||||||
$xlhPeriodsNum = $this->getCachedXlhPeriodsNum("get");
|
$xlhPeriodsNum = $this->getCachedXlhPeriodsNum("get");
|
||||||
@@ -860,27 +823,21 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
'from_type' => 102
|
'from_type' => 102
|
||||||
];
|
];
|
||||||
$push->xunlehui($text_list_new);
|
$push->xunlehui($text_list_new);
|
||||||
$pan_xlh = db::name('vs_room_pan_xlh')
|
// 巡乐会正式开始
|
||||||
->where(['send_time' => 0])
|
$this_xlh_periods = $this->getCachedXlhPeriods('get');
|
||||||
->order('id', 'desc')
|
$pan_xlh_id = db::name('vs_room_pan_xlh')->insertGetId([
|
||||||
->find();
|
'room_id' => $room_id,
|
||||||
if (empty($pan_xlh)) {
|
'gift_id' => $xlh_ext['locking_condition']['locking_gift_id'],
|
||||||
// 巡乐会正式开始
|
'homeowner_gift_id' => $xlh_ext['locking_condition']['give_homeowner_gift_id'],
|
||||||
$this_xlh_periods = $this->getCachedXlhPeriods('get');
|
'periods' => $this_xlh_periods+1,
|
||||||
$pan_xlh_id = db::name('vs_room_pan_xlh')->insertGetId([
|
'num' => 0,
|
||||||
'room_id' => $room_id,
|
'end_time' => time() + $xlh_ext['locking_time']['end_time'] * 60,
|
||||||
'gift_id' => $xlh_ext['locking_condition']['locking_gift_id'],
|
'createtime' => time()
|
||||||
'homeowner_gift_id' => $xlh_ext['locking_condition']['give_homeowner_gift_id'],
|
]);
|
||||||
'periods' => $this_xlh_periods + 1,
|
if(!$pan_xlh_id){
|
||||||
'num' => 0,
|
return ['code' => 0, 'msg' => '创建巡乐会失败!', 'data' => []];
|
||||||
'end_time' => time() + $xlh_ext['locking_time']['end_time'] * 60,
|
|
||||||
'createtime' => time()
|
|
||||||
]);
|
|
||||||
if (!$pan_xlh_id) {
|
|
||||||
return ['code' => 0, 'msg' => '创建巡乐会失败!', 'data' => []];
|
|
||||||
}
|
|
||||||
$this->getCachedXlhPeriods('set', $this_xlh_periods + 1);//修改巡乐会期数
|
|
||||||
}
|
}
|
||||||
|
$this->getCachedXlhPeriods('set', $this_xlh_periods+1);//修改巡乐会期数
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private function updateAndPushXlhStatus($room_id, $xlh_ext, $currentXlhPeriodsNum){
|
private function updateAndPushXlhStatus($room_id, $xlh_ext, $currentXlhPeriodsNum){
|
||||||
@@ -1085,21 +1042,21 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
* @param int $gift_bag_id 礼物包ID
|
* @param int $gift_bag_id 礼物包ID
|
||||||
*/
|
*/
|
||||||
private function reset_gift_pool($gift_bag_id,$remaining_available_gifts=[]) {
|
private function reset_gift_pool($gift_bag_id,$remaining_available_gifts=[]) {
|
||||||
// $bag_detail = db::name("vs_gift_bag_detail")->where('gift_bag_id',$gift_bag_id)->select();
|
$bag_detail = db::name("vs_gift_bag_detail")->where('gift_bag_id',$gift_bag_id)->select();
|
||||||
db::name("vs_gift_bag")->where('id',$gift_bag_id)->setInc('periods'); //更新期数
|
db::name("vs_gift_bag")->where('id',$gift_bag_id)->setInc('periods'); //更新期数
|
||||||
db::name("vs_gift_bag_detail")->where('gift_bag_id',$gift_bag_id)->update(['remaining_number'=>db::raw('quantity')]);//重置奖池
|
db::name("vs_gift_bag_detail")->where('gift_bag_id',$gift_bag_id)->update(['remaining_number'=>db::raw('quantity')]);//重置奖池
|
||||||
//防止并发,上把如果件数小于0,则加上
|
//防止并发,上把如果件数小于0,则加上
|
||||||
// foreach ($bag_detail as $pan) {
|
foreach ($bag_detail as $pan) {
|
||||||
// if($pan['remaining_number']<0){
|
if($pan['remaining_number']<0){
|
||||||
// db::name("vs_gift_bag_detail")->where('id', $pan['id'])->setInc('remaining_number', $pan['remaining_number']);
|
db::name("vs_gift_bag_detail")->where('id', $pan['id'])->setInc('remaining_number', $pan['remaining_number']);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//补充上把礼物有剩余
|
//补充上把礼物有剩余
|
||||||
// if(!empty($remaining_available_gifts)){
|
if(!empty($remaining_available_gifts)){
|
||||||
// foreach ($remaining_available_gifts as $gift) {
|
foreach ($remaining_available_gifts as $gift) {
|
||||||
// db::name("vs_gift_bag_detail")->where('id', $gift['id'])->setInc('remaining_number',$gift['remaining_number']);
|
db::name("vs_gift_bag_detail")->where('id', $gift['id'])->setInc('remaining_number',$gift['remaining_number']);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1274,10 +1231,6 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
// 批量更新库存
|
// 批量更新库存
|
||||||
ksort($inventory_updates); // 按ID排序
|
ksort($inventory_updates); // 按ID排序
|
||||||
foreach ($inventory_updates as $detail_id => $count) {
|
foreach ($inventory_updates as $detail_id => $count) {
|
||||||
$bag_detail = db::name("vs_gift_bag_detail")->field('remaining_number') ->where('id',$detail_id)->find();
|
|
||||||
if($bag_detail['remaining_number'] < $count){
|
|
||||||
throw new \Exception('库存不足');
|
|
||||||
}
|
|
||||||
db::name("vs_gift_bag_detail")->where('id',$detail_id)->setDec('remaining_number', $count);
|
db::name("vs_gift_bag_detail")->where('id',$detail_id)->setDec('remaining_number', $count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user