同步Redis中PV&UV数据到MongoDB的定时任务
实体类
package com.gaiaworks; import lombok.Data; /** * 请求地址访问量 */ @Data public class MPv { /** 请求地址 */ private String requestURL; /** 访问量 */ private Long count; }
package com.gaiaworks; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import java.util.Date; import java.util.List; /** * 权益商城PV统计 */ @Document(collection = "shop_pv_statistic") @Data public class MShopPvStatistic { /** id */ @Id private String id; /** appId */ private String appId; /** 日期 */ private String day; /** 总访问量 */ private Long total; /** 请求地址访问量集合 */ private List<MPv> pvList; /** 创建时间 */ private Date createTime; /** 更新时间 */ private Date updateTime; }
package com.gaiaworks; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import java.util.Date; /** * 权益商城UV统计 */ @Document(collection = "shop_uv_statistic") @Data public class MShopUvStatistic { /** id */ @Id private String id; /** appId */ private String appId; /** 日期 */ private String day; /** 总访问量 */ private Long total; /** 创建时间 */ private Date createTime; /** 更新时间 */ private Date updateTime; }
Job
package net.baiqu.shop.data.core.job; import lombok.extern.slf4j.Slf4j; import net.baiqu.shop.data.core.util.DateUtils; import net.baiqu.shop.data.core.util.RedisUtil; import net.baiqu.shop.data.dal.entity.document.MPv; import net.baiqu.shop.data.dal.entity.document.MShopPvStatistic; import net.baiqu.shop.data.dal.entity.document.MShopUvStatistic; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import redis.clients.jedis.Jedis; import redis.clients.jedis.Tuple; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; /** * 同步redis和mongodb中pv uv统计数据的定时任务 */ @Component @EnableScheduling @Slf4j public class PvUvJob { /** 权益商城appId */ private static final String SHOP_APP_ID = "500000"; /** redis片区 */ private static final int REDIS_INDEX = 0; /** 权益商城PV统计collection */ private static final String SHOP_PV_COLLECTION = "shop_pv_statistic"; /** 权益商城UV统计collection */ private static final String SHOP_UV_COLLECTION = "shop_uv_statistic"; @Autowired private MongoTemplate mongoTemplate; @Autowired private RedisUtil redisUtil; /** * 同步Redis中PV数据到MongoDB定时任务 */ @Scheduled(fixedRate = 10 * 60 * 1000) public void redisPvToMongodbTask() { String day = DateUtils.formatToString(new Date(), "yyyy-MM-dd"); String key = SHOP_APP_ID + "_pv_" + day; log.info("PvUvJob.redisPvToMongodbTask: 开始同步{}数据", key); // 查询mongodb中是否有当天的pv统计数据,有则更新,无则插入 MShopPvStatistic shopPvStatistic = mongoTemplate.findOne( Query.query( Criteria.where("day").is(day) ), MShopPvStatistic.class); List<MPv> pvList = new ArrayList<>(); // 查询redis中的pv数据 long total = this.queryPvByRedis(key, pvList); if (shopPvStatistic == null) { // 插入 // 封装pv统计数据 shopPvStatistic = new MShopPvStatistic(); shopPvStatistic.setAppId(SHOP_APP_ID); shopPvStatistic.setDay(day); shopPvStatistic.setPvList(pvList); shopPvStatistic.setTotal(total); shopPvStatistic.setCreateTime(new Date()); shopPvStatistic.setUpdateTime(new Date()); // 将pv统计数据存入mongo中 mongoTemplate.insert(shopPvStatistic, SHOP_PV_COLLECTION); log.info("PvUvJob.redisPvToMongodbTask: 插入{}数据到mongo", key); } else { // 更新 mongoTemplate.updateFirst( Query.query( new Criteria("day").is(day) ), Update.update("total", total) .set("pvList", pvList) .set("updateTime", new Date()), MShopPvStatistic.class ); log.info("PvUvJob.redisPvToMongodbTask: 更新{}数据到mongo", key); } log.info("PvUvJob.redisPvToMongodbTask: 完成同步{}数据", key); } /** * 同步Redis中UV数据到MongoDB定时任务 */ @Scheduled(fixedRate = 10 * 60 * 1000) public void redisUvToMongodbTask() { String day = DateUtils.formatToString(new Date(), "yyyy-MM-dd"); String key = SHOP_APP_ID + "_uv_" + day; log.info("PvUvJob.redisUvToMongodbTask: 开始同步{}数据", key); // 查询mongodb中是否有当天的uv统计数据,有则更新,无则插入 MShopUvStatistic shopUvStatistic = mongoTemplate.findOne( Query.query( Criteria.where("day").is(day) ), MShopUvStatistic.class); // 查询redis中的uv数据 long total = this.queryUvByRedis(key); if (shopUvStatistic == null) { // 插入 // 封装uv统计数据 shopUvStatistic = new MShopUvStatistic(); shopUvStatistic.setAppId(SHOP_APP_ID); shopUvStatistic.setDay(day); shopUvStatistic.setTotal(total); shopUvStatistic.setCreateTime(new Date()); shopUvStatistic.setUpdateTime(new Date()); // 将pv统计数据存入mongo中 mongoTemplate.insert(shopUvStatistic, SHOP_UV_COLLECTION); log.info("PvUvJob.redisUvToMongodbTask: 插入{}数据到mongo", key); } else { // 更新 mongoTemplate.updateFirst( Query.query( new Criteria("day").is(day) ), Update.update("total", total) .set("updateTime", new Date()), MShopUvStatistic.class ); log.info("PvUvJob.redisUvToMongodbTask: 更新{}数据到mongo", key); } log.info("PvUvJob.redisUvToMongodbTask: 完成同步{}数据", key); } /** * 查询Redis中PV数据 */ private long queryPvByRedis(String key, List<MPv> pvList) { Jedis jedis = redisUtil.getJedis(); long total = 0; jedis.select(REDIS_INDEX); Set<Tuple> tuples = jedis.zrevrangeWithScores(key, 0, Long.MAX_VALUE); if (! CollectionUtils.isEmpty(tuples)) { for (Tuple tuple : tuples) { MPv pv = new MPv(); pv.setRequestURL(tuple.getElement()); pv.setCount((long) tuple.getScore()); total = total + (long) tuple.getScore(); pvList.add(pv); } } return total; } /** * 查询Redis中UV数据 */ private long queryUvByRedis(String key) { Jedis jedis = redisUtil.getJedis(); jedis.select(REDIS_INDEX); Set<Tuple> tuples = jedis.zrevrangeWithScores(key, 0, Long.MAX_VALUE); return tuples.size(); } }