zoukankan      html  css  js  c++  java
  • redis 数据统计(用自增id防止同一秒并发过大没统计成功)

    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]']
    
    ";
            } 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;
        }

     

  • 相关阅读:
    常用辅助类(ContDownLatch、CyclicBarrier、Semaphore)
    Redis
    SpringBoot
    微服务概述
    数据库 子查询和分页查询
    数据库基础语句,聚合函数,练习
    数据库基础知识

    for循环的类型以及while循环
    C#编程循环练习
  • 原文地址:https://www.cnblogs.com/-mrl/p/7873536.html
Copyright © 2011-2022 走看看