From d284ee834668601bfeea054c6e0ec38574b313a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E9=92=8A?= Date: Thu, 16 Oct 2025 18:24:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E9=9C=80=E6=B1=82-=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=E9=9C=80=E6=B1=82-=E7=9B=B2=E7=9B=92=E8=BD=AC=E7=9B=98?= =?UTF-8?q?=E8=B0=83=E9=80=9A=E7=9B=98-=E5=B7=A1=E4=B9=90=E4=BC=9A-?= =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/BlindBoxTurntableGiftDrawWorld.php | 103 ++++++++++++++---- 1 file changed, 84 insertions(+), 19 deletions(-) diff --git a/application/api/model/BlindBoxTurntableGiftDrawWorld.php b/application/api/model/BlindBoxTurntableGiftDrawWorld.php index d455567..d2fac2e 100644 --- a/application/api/model/BlindBoxTurntableGiftDrawWorld.php +++ b/application/api/model/BlindBoxTurntableGiftDrawWorld.php @@ -767,23 +767,75 @@ class BlindBoxTurntableGiftDrawWorld extends Model */ private function handleXlhOperations($room_id, $xlh_ext, $currentXlhPeriodsNum,$addcurrentXlhPeriodsNum,$room) { - $xlhIsPiaoPing = 0; - $xlhPeriodsNum = $this->getCachedXlhPeriodsNum("get"); - if($xlhPeriodsNum < $xlh_ext['open_condition']['waiting_start_num'] && $currentXlhPeriodsNum >= $xlh_ext['open_condition']['waiting_start_num']){ - $xlhIsPiaoPing = 1; + // 增加对 $xlh_ext 的安全检查 + if (empty($xlh_ext) || !isset($xlh_ext['open_condition'])) { + return; } - if($xlhPeriodsNum < $xlh_ext['open_condition']['start_num'] && $currentXlhPeriodsNum >= $xlh_ext['open_condition']['start_num']){ - $xlhIsPiaoPing = 2; - } - // 更新房间巡乐会次数 - $this->getCachedXlhPeriodsNum("set",$addcurrentXlhPeriodsNum); + // 使用 Redis 锁防止并发问题 + $lockKey = "xlh_operation_lock_{$room_id}"; + $lockAcquired = false; - // 处理飘屏 - if ($xlhIsPiaoPing == 1 || $xlhIsPiaoPing == 2) { - $this->handleXlhPiaoPing($room_id, $xlh_ext, $xlhIsPiaoPing); + if ($this->redis) { + // 尝试获取锁,最多等待3秒 + $lockValue = uniqid(); + for ($i = 0; $i < 30; $i++) { + if ($this->redis->set($lockKey, $lockValue, ['NX', 'EX' => 10])) { + $lockAcquired = true; + break; + } + usleep(100000); // 等待100ms + } + } + try { + $xlhPeriodsNum = $this->getCachedXlhPeriodsNum("get"); + $xlhIsPiaoPing = 0; + if($xlhPeriodsNum < $xlh_ext['open_condition']['waiting_start_num'] && $currentXlhPeriodsNum >= $xlh_ext['open_condition']['waiting_start_num']){ + $xlhIsPiaoPing = 1; + } + if($xlhPeriodsNum < $xlh_ext['open_condition']['start_num'] && $currentXlhPeriodsNum >= $xlh_ext['open_condition']['start_num']){ + $xlhIsPiaoPing = 2; + } + // 更新房间巡乐会次数 + $this->getCachedXlhPeriodsNum("set",$addcurrentXlhPeriodsNum); + + // 处理飘屏 + if ($xlhIsPiaoPing == 1 || $xlhIsPiaoPing == 2) { + $this->handleXlhPiaoPing($room_id, $xlh_ext, $xlhIsPiaoPing); + } + // 减少不必要的数据库查询 + $shouldUpdateStatus = false; + if ($xlhPeriodsNum <= $xlh_ext['open_condition']['waiting_start_num']) { + $shouldUpdateStatus = true; + } else { + // 使用缓存优化,避免每次都查询数据库 + $panXlhCacheKey = "pan_xlh_status"; + $hasActiveXlh = Cache::get($panXlhCacheKey); + + if ($hasActiveXlh === null) { + $pan_xlh = db::name('vs_room_pan_xlh') + ->where('send_time', 0) + ->order('id', 'desc') + ->find(); + $hasActiveXlh = !empty($pan_xlh) ? 1 : 0; + Cache::set($panXlhCacheKey, $hasActiveXlh, 30); // 缓存30秒 + } + + if (!$hasActiveXlh) { + $shouldUpdateStatus = true; + // 清除缓存以便下次重新检查 + Cache::rm($panXlhCacheKey); + } + } + + if ($shouldUpdateStatus) { + $this->updateAndPushXlhStatus($room_id, $xlh_ext, $currentXlhPeriodsNum); + } + } finally { + // 释放锁 + if ($lockAcquired && $this->redis) { + $this->redis->del($lockKey); + } } - // 更新巡乐会状态并推送 - $this->updateAndPushXlhStatus($room_id, $xlh_ext, $currentXlhPeriodsNum); } private function handleXlhPiaoPing($room_id, $xlh_ext, $xlhIsPiaoPing){ if($xlhIsPiaoPing == 1){ @@ -1002,12 +1054,25 @@ class BlindBoxTurntableGiftDrawWorld extends Model */ private function getCachedXlhPeriodsNum($type="get",$num=1) { $cacheKey = "xlh_periods_num"; - $xlh_periods_num = Cache::get($cacheKey) ?? 0; - if($type=="set"){ - $xlh_periods_num = $xlh_periods_num + $num; - Cache::set($cacheKey, $xlh_periods_num, 0); + if ($type == "set") { + if ($this->redis) { + // 使用 Redis 原子操作 + return $this->redis->incrBy($cacheKey, $num); + } else { + // 回退到缓存操作 + $xlh_periods_num = Cache::get($cacheKey) ?? 0; + $xlh_periods_num = $xlh_periods_num + $num; + Cache::set($cacheKey, $xlh_periods_num, 0); + return $xlh_periods_num; + } + } else { + if ($this->redis) { + $value = $this->redis->get($cacheKey); + return $value !== false ? (int)$value : 0; + } else { + return Cache::get($cacheKey) ?? 0; + } } - return $xlh_periods_num; } /** * 获取缓存的巡乐会期数