redis 数据统计(用自增id防止同一秒并发过大没统计成功)
2017-11-21 15:50
706 查看
Redis 缓存保存某段时间累加的数值,加入最大id防止同一秒并发过大,导致只统计了执行时同一秒的部分数据,而同一秒另一部分数据在下次累加时没有统计到缓存中
一条语句判断数据是否异常例子(保存统计过的最大自增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; }
相关文章推荐
- 并发下,使用redis防止数据重复插入(数据库未对表字段设置唯一情况下)
- 游戏数据统计:【ID:村里最强】个人高速道具赛统计图表
- PHP使用Redis实现防止大并发下二次写入的方法
- txt文件导入Mysql提示导入成功但是只有一条ID为0的无效数据
- 高并发数据采集的架构应用(Redis的应用)
- 使用redis计数器防止并发请求
- PHP使用redis防止大并发下二次写入
- 漫谈redis在运维数据分析中的去重统计方式
- Java通过Jedis插入数据到redis无法成功
- 网站用户行为数据统计与分析之五:redis及其配置
- PHP实现Redis单据锁以及防止并发重复写入
- 使用Redis计数器防止并发请求
- 三千万数据量下redis2.4的一统计情况
- 高并发下防止商品超卖的Redis实现
- SYSAUX 表空间历史统计数据过大的处理办法—--范例篇
- Redis 中文入库成功,读取数据写入文件乱码问题
- 使用redis计数器防止并发请求
- sql查询统计,根据新闻类别ID统计,没有数据显示0
- codis迁移槽位遇到value过大的数据导致redis进程堵塞问题
- redis如何防止并发?