redis 数据统计(用自增id防止同一秒并发过大没统计成功)

时间:2023-02-22 18:37:34

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;
}

redis 数据统计(用自增id防止同一秒并发过大没统计成功)的更多相关文章

  1. mysql插入数据后返回自增ID的方法&comma;last&lowbar;insert&lowbar;id&lpar;&rpar;&comma;selectkey

    mysql插入数据后返回自增ID的方法 mysql和oracle插入的时候有一个很大的区别是,oracle支持序列做id,mysql本身有一个列可以做自增长字段,mysql在插入一条数据后,如何能获得 ...

  2. mysql函数之六:mysql插入数据后返回自增ID的方法&comma;last&lowbar;insert&lowbar;id&lpar;&rpar;&comma;selectkey

    mysql插入数据后返回自增ID的方法 mysql和oracle插入的时候有一个很大的区别是,oracle支持序列做id,mysql本身有一个列可以做自增长字段,mysql在插入一条数据后,如何能获得 ...

  3. mysql清空表数据并重置自增ID

    mysql清空表数据并重置自增ID: ## 查看mysql> select * from work_order_company;mysql> show create table work_ ...

  4. mysql插入数据后返回自增ID的方法

    mysql和oracle插入的时候有一个很大的区别是,oracle支持序列做id,mysql本身有一个列可以做自增长字段,mysql在插入一条数据后,如何能获得到这个自增id的值呢? 方法一是使用la ...

  5. mybatis插入数据并返回自增Id

    上图mybatis的写法,在xxxMapper.xml中: 加入:useGeneratedKeys="true" keyProperty="applyId" k ...

  6. Mybatis使用generatedKey在插入数据时返回自增id始终为1,自增id实际返回到原对象当中的问题排查

    今天在使用数据库的时候,遇到一个场景,即在插入数据完成后需要返回此数据对应的自增主键id,但是在使用Mybatis中的generatedKey且确认各项配置均正确无误的情况下,每次插入成功后,返回的都 ...

  7. 如何在MySQl数据库中给已有的数据表添加自增ID?

    由于使用MySQL数据库还没有多久的缘故,在搭建后台往数据库导入数据的时候发现新增的表单是没有自增id的,因次就有了上面这个问题. 解决方法 1.给某一张表先增加一个字段,这里我们就以node_tab ...

  8. Sql Server插入数据并返回自增ID,&commat;&commat;IDENTITY,SCOPE&lowbar;IDENTITY和IDENT&lowbar;CURRENT的区别

    预备知识:SQLServer的IDENTITY关键字IDENTITY关键字代表的是一个函数,而不是identity属性.在access里边没有这个函数,所以在access不能用这个语句.语法:iden ...

  9. Sql Server插入数据并返回自增ID,&commat;&commat;IDENTITY,SCOPE&lowbar;IDENTITY和IDENT&lowbar;CURRENT的区别(转载)

    预备知识:SQL Server的IDENTITY关键字IDENTITY关键字代表的是一个函数,而不是identity属性.在access里边没有这个函数,所以在access不能用这个语句.语法:ide ...

随机推荐

  1. JAVA GUI

    JAVA GUI中的事件处理:   委托事件模型:事件源对象和监听器对象具有绑定关系   一个监听器可以绑定多个事件源 一个事件源也可以绑定多个监听器 监听器有各自监听的事件类型   设置容器的布局管 ...

  2. &lbrack;转&rsqb;Tangram框架应用开发的一般模式

    //转的,怕想百度博客一样搬家,赶紧先复制下来. 框架其实就是一种开发模式,用tangram框架开发应用程序意味着选择一种面向接口.模块化的开发方式.这和传统的Delphi应用程序开发方式有一定区别, ...

  3. grep -C n &quot&semi;匹配字符串&quot&semi; 匹配字符串上下N行

    [root@xxxxx ~]# grep -C 'ip_whitelist' /etc/gitlab/gitlab.rb # 'PATH' => "/opt/gitlab/bin:/o ...

  4. 【Qt】Qt Linguist介绍【转】

    简介 Qt提供了一款优秀的支持Qt C++和Qt Quick应用程序的翻译工具.发布者.翻译者和开发者可以使用这款工具来完成他们的任务. 发布者:承担了全面发布应用程序的责任.通常,他们协调开发者和翻 ...

  5. easyui datagrid 隔行变色

    easyui datagrid  隔行变色 一:实现样图 二:实现代码 $('#dataGrid').datagrid({ rowStyler:function(index,row){ if (row ...

  6. &lbrack;转&rsqb;50个极好的bootstrap 后台框架主题下载

    50个极好的bootstrap 后台框架主题下载 http://sudasuta.com/bootstrap-admin-templates.html 越来越多的设计师和前端工程师开始用bootstr ...

  7. SpringBoot(十六)-- 使用外部容器运行springBoot项目

    spring-boot项目需要部署在外部容器中的时候,spring-boot导出的war包无法再外部容器(tomcat)中运行或运行报错. 为了解决这个问题,需要移除springBoot自带的tomc ...

  8. Mybatis-Plus 实战完整学习笔记&lpar;四&rpar;------全局参数配置

    一.全局配置设置 (1)全局配置Id自动生成 <!--定义mybatisplus全局配置--> <bean id="globalConfig" class=&qu ...

  9. SQL脚本去重分组统计

    需求:首先有一张表记录学生姓名.科目和成绩,然后模拟插入几条数据,脚本如下: create table score ( Name ),--姓名 subject ),--科目 grade int--成绩 ...

  10. Android 如何修改gen下包的名字

    前言 当将项目中包进行重命名后,所有包名字修改了,但是在gen目录下android sdk 自动生成的包名并没有修改,如果要引用R.java 中的字段, 又得import以前的包名字.   原因 出现 ...