继上一篇继续优化内容.

  1. 将排行榜缓存改为按日期存储,查看的时候可以根据日期查看当天的数据
    hscan的时候查询参数改为"*:“+type+”:"+time 就能获取指定日期的数据了
    然后存入的时候携带日期就行了 hset 的fieId为 username:time

  2. 根据id获取username的操作 原本是每次循环都根据id去数据库查,优化后是在循环前查出所有用户,然后存入map里 key=id value=username 然后循环的时候去map里取用户名 减少了mysql的多次查询操作

新需求既然是更具指定时间查数据,就没有汇总的操作,其实可以不用新的的字段存储汇总的数据作为缓存了 可以直接取原字段数据展示出来的.

以下代码是两个改动的方法

 @Scheduled(cron = "0 0 0/1 * * ? ")//一个小时执行一次
    public void getTrafficRankByDay(){
        LogUtils.info("==============redis更新用户使用流量排行开始=================");
        try {
            String today = DateUtil.today();//获取当天日期
            long start = System.currentTimeMillis();
            List<SysUser> sysUsers = userMapper.selectAll();
            Map<String, String> map = new HashMap<>();
            for (SysUser user :
                    sysUsers) {
                map.put(user.getId(), user.getUserName());
            }
            Map<String, String> trafficRank = userService.getTrafficRankByDay(1,today,map);//动态住宅
            Map<String, String> trafficRankjf = userService.getTrafficRankByDay(2,today,map);//海外机房住宅
            Map<String, String> gtrafficRank4g = userService.getTrafficRankByDay(3,today,map);//4G住宅

            JedisUtil.hmset(SysConstants.TRAFFIC_RANK,trafficRank);
            JedisUtil.hmset(SysConstants.TRAFFIC_RANK_JF,trafficRankjf);
            JedisUtil.hmset(SysConstants.TRAFFIC_RANK_4G,gtrafficRank4g);
            long end = System.currentTimeMillis();
            LogUtils.info("==============redis更新用户使用流量排行成功共耗时"+ (end - start) +"毫秒=================");
        } catch (Exception e) {
            e.printStackTrace();
            LogUtils.info("==============更新redis用户流量排行榜失败=================");
        }
    }

    public Map<String, String> getTrafficRankByDay(Integer type,String time,Map<String, String> userMap){
//        String newTime = replaceLast(time,"*");//将日期的最后一天改为*  只查询每个月01-09 10-19 20-29 30-31的数据
        //redis存的格式是   dbc1649c-d8d2-4808-af02-5736cbc66ada:1:2022-05-12 -> 流量
        HashMap<String, String>  map = new HashMap<>();
        HashMap<String, String>  userNameMap = new HashMap<>();
        long start = System.currentTimeMillis();
        Map<String, String> redisMap = JedisUtil.getAll("userFlowCounter", 50000,"*:"+type+":"+time);//
        long end = System.currentTimeMillis();
        System.err.println("=======================redis查询共耗时" + (end - start) + "毫秒=====================");//输出程序运行时间
        Set<String> keys = redisMap.keySet();   //此行可省略,直接将map.keySet()写在for-each循环的条件中
        //遍历redis的结果, 过滤key 只保留userId 和日流量再存入新的map里
        for(String key:keys){
            //截取:之前的userId
            String userId = StringUtils.substringBefore(key, ":");
            //判断map集合中有没有这个userId为名字的key
            //containsKey返回值为boolean类型
            //日流量
            BigDecimal userBillByDay = new BigDecimal(redisMap.get(key));
            if(map.containsKey(userId)){
                //根据key取出value再加上name相同的另一个参数的value
                BigDecimal mapBill = new BigDecimal(map.get(userId));
                BigDecimal addBill = userBillByDay.add(mapBill);//相加之后的流量
                map.put(userId,addBill.toString());
            }
            else{
                map.put(userId,userBillByDay.toString());
            }
        }
        Set<String> userName = map.keySet();   //获取用户名
        for(String key:userName){//先过滤:type:  指定类型的结果  1为动态2为海外机房3为4G
//            SysUser byId = userMapper.getById(key);
            //userMap 是userId:userName的结构
            if(ObjectUtil.isNotNull(userMap.get(key))){
                userNameMap.put(userMap.get(key)+":"+time,map.get(key));
            }else {
                userNameMap.put(key+":"+time,map.get(key));
            }
        }
//        Map<String, String> stringDoubleMap = sortMapByValue(userNameMap); 不排序  因为存入redis的时候又无序了   接口取数据的时候重新排序就行了
        return userNameMap;
    }
上一篇 下一篇