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; } /** * 获取缓存的巡乐会期数