Redis 緩存保存某段時間累加的數值,加入最大id防止同一秒並發過大,導致只統計了執行時同一秒的部分數據,而同一秒另一部分數據在下次累加時沒有統計到緩存中
//coin總數
public function get_stat_coin_total($key = '',$now = 0){ $redisTotal = 0; $redisMaxId = 0; $redisData = null; $effective_time = Kv::getStatEffectiveTime(); //有效時間
if($key == 'gift_log_coin_today'){ $time1 = strtotime(date('Y-m-d',strtotime('0 day'))); $time2 = $now; //統計到當前時間的數據
}elseif($key == 'gift_log_coin_yesterday'){ $time1 = strtotime(date('Y-m-d',strtotime('-1 day'))); $time2 = strtotime(date('Y-m-d',strtotime('0 day'))); }elseif($key == 'gift_log_coin_yesterday_before'){ $time1 = 0; //最開始時間
$time2 = strtotime(date('Y-m-d',strtotime('0 day'))); }elseif($key == 'gift_log_coin_total'){ $time1 = 0; //最開始時間
$time2 = $now; //統計到當前時間的數據
}else{ return 0; } $redis = self::getRedis(); $userStatListKey = UserStat::USER_STAT_LIST_KEY . $key; $redisData = $redis->hGetAll($userStatListKey); if($redisData && $redisData['effective_time'] > $now){ $time1 = $redisData['end_time']; $redisTotal = $redisData['total']; $redisMaxId = $redisData['max_id']; $effective_time = $redisData['effective_time']; } $sql = "SELECT sum(send_coin) as total,max(id) as max_id FROM `gift_log` WHERE add_time >= {$time1} AND add_time <= {$time2} AND id > {$redisMaxId}; "; $connection = $this->getReadConnection(); $data = $connection->fetchOne($sql); $total = empty($data['total'])?0:$data['total']; $max_id = empty($data['max_id'])?$redisMaxId:$data['max_id']; $result = [ 'start_time'=>$time1,
'end_time'=>$time2,
'total'=>$total+$redisTotal,
'max_id'=>$max_id,
'effective_time'=>$effective_time, ]; $redis->hMset($userStatListKey,$result); return $result['total']; }
一條語句判斷數據是否異常例子(保存統計過的最大自增id)
/** * 檢測 今日 coin 是否正常 統一查詢 * 保存統計過的最大自增id */
public function checkCoin() { $model = new UserStat(); $connection = $model->getReadConnection(); $redis = self::getRedis(); $userStatListKey = UserStat::USER_STAT_LIST_KEY; $redisData = $redis->hGetAll($userStatListKey); if ($redisData) { $sql = <<<SQL SELECT (SELECT concat(IFNULL(sum(coin),0),'_',ifnull(max(id),:max_recharge_id)) FROM wallet_recharge_log WHERE pay_status = 1 AND id > :max_recharge_id ) AS recharge ,(SELECT concat(IFNULL(sum(-send_coin),0),'_',ifnull(max(id),:max_send_gift_id)) AS send_total FROM gift_log WHERE id > :max_send_gift_id) AS send_gift ,(SELECT concat(IFNULL(sum(CASE type WHEN 1 THEN coin ELSE -coin END),0),'_',ifnull(max(id),:max_wallet_order_id)) FROM wallet_order_log WHERE id > :max_wallet_order_id ) AS wallet_order ,(SELECT IFNULL(sum(-coin),0) AS has_total_coin FROM user_wallet) AS has_coin ,(SELECT IFNULL(sum(-pay_coin),0) AS total FROM live_pay_log WHERE `status` =2) AS live_pay ,(SELECT concat(IFNULL(sum(-coin),0),'_',ifnull(max(id),:max_barrage_pay_id)) FROM user_barrage_log WHERE id > :max_barrage_pay_id) AS barrage_pay ,(SELECT concat(IFNULL(sum(-coin),0),'_',ifnull(max(id),:max_vip_pay_id)) FROM user_vip_log WHERE id > :max_vip_pay_id) AS vip_pay ,(SELECT concat(IFNULL(sum(coin),0),'_',ifnull(max(id),:max_exchange_get_id)) FROM wallet_exchange_log WHERE id > :max_exchange_get_id) AS exchange_get; SQL; $bind_arr = [ 'max_recharge_id' => $redisData['max_recharge_id'],
'max_send_gift_id' => $redisData['max_send_gift_id'],
'max_wallet_order_id' => $redisData['max_wallet_order_id'],
'max_barrage_pay_id' => $redisData['max_barrage_pay_id'],
'max_vip_pay_id' => $redisData['max_vip_pay_id'],
'max_exchange_get_id' => $redisData['max_exchange_get_id'], ]; $result = $connection->query($sql, $bind_arr)->fetch(); $change_coin = $redisData['has_coin'] - $result['has_coin']; $result['recharge'] = explode('_',$result['recharge']); $result['send_gift'] = explode('_',$result['send_gift']); $result['wallet_order'] = explode('_',$result['wallet_order']); $result['barrage_pay'] = explode('_',$result['barrage_pay']); $result['vip_pay'] = explode('_',$result['vip_pay']); $result['exchange_get'] = explode('_',$result['exchange_get']); $redis_arr = [ 'has_coin' => $result['has_coin'],
'live_pay' => $result['live_pay'],
'recharge' => $redisData['recharge'] + $result['recharge'][0],
'send_gift' => $redisData['send_gift'] + $result['send_gift'][0],
'wallet_order' => $redisData['wallet_order'] + $result['wallet_order'][0],
'barrage_pay' => $redisData['barrage_pay'] + $result['barrage_pay'][0],
'vip_pay' => $redisData['vip_pay'] + $result['vip_pay'][0],
'exchange_get' => $redisData['exchange_get'] + $result['exchange_get'][0], ]; $max_id_arr = [ 'max_recharge_id' => $result['recharge'][1],
'max_send_gift_id' => $result['send_gift'][1],
'max_wallet_order_id' => $result['wallet_order'][1],
'max_barrage_pay_id' => $result['barrage_pay'][1],
'max_vip_pay_id' => $result['vip_pay'][1],
'max_exchange_get_id' => $result['exchange_get'][1], ]; echo "send_gift : [{$result['send_gift'][0]}];change_coin [$change_coin]']\n\n"; } else { $sql = <<<SQL SELECT (SELECT concat(IFNULL(sum(coin),0),'_',ifnull(max(id),0)) FROM wallet_recharge_log WHERE pay_status = 1 ) AS recharge ,(SELECT concat(IFNULL(sum(-send_coin),0),'_',ifnull(max(id),0)) AS send_total FROM gift_log) AS send_gift ,(SELECT concat(IFNULL(sum(CASE type WHEN 1 THEN coin ELSE -coin END),0),'_',ifnull(max(id),0)) FROM wallet_order_log ) AS wallet_order ,(SELECT IFNULL(sum(-coin),0) AS has_total_coin FROM user_wallet) AS has_coin ,(SELECT IFNULL(sum(-pay_coin),0) AS total FROM live_pay_log WHERE `status` =2) AS live_pay ,(SELECT concat(IFNULL(sum(-coin),0),'_',ifnull(max(id),0)) FROM user_barrage_log ) AS barrage_pay ,(SELECT concat(IFNULL(sum(-coin),0),'_',ifnull(max(id),0)) FROM user_vip_log) AS vip_pay ,(SELECT concat(IFNULL(sum(coin),0),'_',ifnull(max(id),0)) FROM wallet_exchange_log) AS exchange_get; SQL; $result = $connection->query($sql)->fetch(); $result['recharge'] = explode('_',$result['recharge']); $result['send_gift'] = explode('_',$result['send_gift']); $result['wallet_order'] = explode('_',$result['wallet_order']); $result['barrage_pay'] = explode('_',$result['barrage_pay']); $result['vip_pay'] = explode('_',$result['vip_pay']); $result['exchange_get'] = explode('_',$result['exchange_get']); $redis_arr = [ 'has_coin' => $result['has_coin'],
'live_pay' => $result['live_pay'],
'recharge' => $result['recharge'][0],
'send_gift' => $result['send_gift'][0],
'wallet_order' => $result['wallet_order'][0],
'barrage_pay' => $result['barrage_pay'][0],
'vip_pay' => $result['vip_pay'][0],
'exchange_get' => $result['exchange_get'][0], ]; $max_id_arr = [ 'max_recharge_id' => $result['recharge'][1],
'max_send_gift_id' => $result['send_gift'][1],
'max_wallet_order_id' => $result['wallet_order'][1],
'max_barrage_pay_id' => $result['barrage_pay'][1],
'max_vip_pay_id' => $result['vip_pay'][1],
'max_exchange_get_id' => $result['exchange_get'][1], ]; } $coin_diff_today = array_sum($redis_arr); $coin_limit = Kv::get('coin_limit', '0'); //coin是否正常
if (abs($coin_diff_today) < $coin_limit) { //正常
$redis_arr['status'] = 1; } else { //異常
$redis_arr['status'] = 2; } $redis_arr = array_merge($redis_arr,$max_id_arr); $redis_arr['coin_diff_today'] = $coin_diff_today; $redis->hMset($userStatListKey,$redis_arr); if(!$redisData){ $redis->expire($userStatListKey,3600 * 24); } return $redis_arr; }