盲盒转盘优化-重构-调试
This commit is contained in:
@@ -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)];
|
||||
|
||||
@@ -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']);
|
||||
}
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user