盲盒转盘优化-重构-调试

This commit is contained in:
2025-10-28 12:03:43 +08:00
parent 60b517312c
commit 4f917863e6
3 changed files with 186 additions and 2 deletions

View File

@@ -72,7 +72,9 @@ class User extends adminApi
if($v=='coin1'){
$where['c.coin'] = ['>=',$input_data];
}elseif($v=='coin2'){
$where['c.coin'] = ['<=',$input_data];
if($input_data){
$where['c.coin'] = ['<=',$input_data];
}
}elseif($v=='createtime'){
$where['a.createtime'] = ['>=',strtotime($input_data)];
$where['a.createtime'] = ['<=',strtotime($input_data)];

View File

@@ -40,7 +40,7 @@ class BlindBoxTurntable extends BaseCom
$num = input('num',1);
$heart_id = input('heart_id',0);
$auction_id = input('auction_id',0);
$reslut = model('BlindBoxTurntableGiftDrawWorld')->draw_gift($gift_bag_id, $user_id, $gift_user_ids,$num,$room_id,$heart_id,$auction_id);
$reslut = model('BlindBoxTurntableGiftDrawWorldNew')->draw_gift($gift_bag_id, $user_id, $gift_user_ids,$num,$room_id,$heart_id,$auction_id);
return v($reslut['code'], $reslut['msg'], $reslut['data']);
}
/*

View File

@@ -8,6 +8,7 @@ use think\Model;
use think\Db;
use think\Session;
use Redis;
use think\queue;
/*
* 盲盒转盘优化后方法
*
@@ -149,6 +150,118 @@ class BlindBoxTurntableGiftDrawWorld extends Model
return ['code' => 0, 'msg' => "网络加载失败,请重试!", 'data' => null];
}
}
/**
* 生成奖池并存入Redis
*/
public function generateGiftPool($gift_bag_id)
{
try {
// 获取奖池基本信息
$poolKey = "blind_box_pool:{$gift_bag_id}";
$poolInfoKey = "blind_box_pool_info:{$gift_bag_id}";
// 检查Redis连接
if (!$this->redis) {
throw new \Exception('Redis连接不可用');
}
// 获取数据库中的期数信息
$dbPeriods = db::name("vs_gift_bag")
->where(['id' => $gift_bag_id])
->value('periods');
// 获取奖池详细信息
$gift_bag_detail_data = $this->getCachedGiftBagDetail($gift_bag_id);
// 获取可用礼物列表
$availableGifts = [];
foreach ($gift_bag_detail_data as $gift) {
if ($gift['remaining_number'] > 0) {
// 根据权重添加礼物到可选列表
for ($i = 0; $i < $gift['weight']; $i++) {
$availableGifts[] = $gift;
}
}
}
if (empty($availableGifts)) {
throw new \Exception('没有可用的礼物');
}
// 生成大量抽奖结果例如1000个
$results = [];
for ($i = 0; $i < 1000; $i++) {
$randomIndex = array_rand($availableGifts);
$selectedGift = $availableGifts[$randomIndex];
// 获取礼物详细信息
$giftInfo = db::name("vs_gift")
->where(['gid' => $selectedGift['foreign_id']])
->find();
$results[] = [
'gift_bag_detail' => $selectedGift,
'gift' => $giftInfo ?? []
];
}
// 使用事务确保原子操作
$this->redis->watch($poolKey, $poolInfoKey);
$this->redis->multi();
// 清空现有奖池
$this->redis->del($poolKey);
// 添加新结果到奖池
foreach ($results as $result) {
$this->redis->rPush($poolKey, json_encode($result));
}
// 更新奖池信息
$this->redis->hMSet($poolInfoKey, [
'periods' => $dbPeriods,
'draw_times' => 0,
'total_count' => count($results),
'last_update' => time()
]);
$this->redis->exec();
Log::record("奖池生成成功gift_bag_id: {$gift_bag_id}", 'info');
return true;
} catch (\Exception $e) {
Log::record('生成奖池失败: ' . $e->getMessage(), 'error');
return false;
}
}
/**
* 从奖池中获取一个礼物
*/
public function getGiftFromPool($gift_bag_id)
{
try {
$poolKey = "blind_box_pool:{$gift_bag_id}";
// 从Redis奖池中取出一个结果
$result = $this->redis->lPop($poolKey);
if (!$result) {
// 奖池为空,重新生成
$this->generateGiftPool($gift_bag_id);
$result = $this->redis->lPop($poolKey);
}
return $result ? json_decode($result, true) : null;
} catch (\Exception $e) {
Log::record('从奖池获取礼物失败: ' . $e->getMessage(), 'error');
return null;
}
}
/**
* 验证抽奖参数
*/
@@ -598,6 +711,9 @@ class BlindBoxTurntableGiftDrawWorld extends Model
Log::record('巡乐会更新礼物剩余数量: ' . $room_id."【数据】".var_export($precomputedResults, true),"info");
throw new \Exception('更新礼物剩余数量失败');
}
// 同时更新缓存中的库存信息
$this->updateCachedGiftBagDetail($giftBagDetail['gift_bag_id'], $giftId, $count);
}
}
@@ -1542,5 +1658,71 @@ class BlindBoxTurntableGiftDrawWorld extends Model
Log::record('Redis操作失败: ' . $e->getMessage(), 'error');
}
}
/**
* 获取转盘礼包详细信息【缓存】
*/
private function getCachedGiftBag($gift_bag_id,$is_cache = true) {
$cacheKey = "pan_gift_bag".$gift_bag_id;
$gift_bag_data = Cache::get($cacheKey);
if (!$gift_bag_data || !$is_cache) {
$bag_data = db::name("vs_gift_bag")
->field('id,name,ext,periods')
->where('id', $gift_bag_id)
->find();
if (!$bag_data) {
return [];
}
$gift_bag_data = json_decode($bag_data['ext'], true);
$gift_bag_data['gift_bag_id'] = $gift_bag_id;
$gift_bag_data['gift_bag_name'] = $bag_data['name'];
$gift_bag_data['periods'] = $bag_data['periods'];
$gift_bag_data['gift_price'] = DB::name("vs_gift") ->where(['gid' => $gift_bag_data['gift_id']])->value('gift_price');
Cache::set($cacheKey, $gift_bag_data, $this->cache_time);
}
return $gift_bag_data;
}
/**
* 获取奖池详细信息【缓存】
*/
private function getCachedGiftBagDetail($gift_bag_id,$is_cache = true) {
$cacheKey = "pan_gift_bag_detail".$gift_bag_id;
$gift_bag_detail_data = Cache::get($cacheKey);
if (!$gift_bag_detail_data || !$is_cache) {
$gift_bag_detail_data = db::name("vs_gift_bag_detail")
->field('id,quantity,remaining_number,weight,foreign_id,gift_bag_id')
->where(['gift_bag_id' => $gift_bag_id])
->select();
if (!$gift_bag_detail_data) {
return [];
}
$gift_bag_detail_data['total_quantity'] = 0;
$gift_bag_detail_data['total_remaining'] = 0;
foreach ($gift_bag_detail_data as &$item) {
$item['total_quantity'] += $item['quantity'];
$item['total_remaining'] += $item['remaining_number'];
}
Cache::set($cacheKey, $gift_bag_detail_data, $this->cache_time);
}
return $gift_bag_detail_data;
}
/**
* 更新缓存中的奖池信息
*/
private function updateCachedGiftBagDetail($gift_bag_id, $detail_id, $decrement = 1) {
$cacheKey = "pan_gift_bag_detail".$gift_bag_id;
$gift_bag_detail_data = Cache::get($cacheKey);
if ($gift_bag_detail_data) {
foreach ($gift_bag_detail_data as &$item) {
if ($item['id'] == $detail_id) {
$item['remaining_number'] -= $decrement;
break;
}
}
Cache::set($cacheKey, $gift_bag_detail_data, $this->cache_time);
}
}
}