Redis 统计UV
需求:以一天为单位,统计 index.html 页面打开的UV。需根据 UserId 对访问的用户去重。(假设所有用户已经登录)
UV 和 PV 在本需求中的定义:
- UV 的定义:以UserId 为唯一标识,统计当天用户唯一访问量。比如:你在今天一共访问 index.html 10次,但是统计 UV 的时候,只算作 UV + 1
- PV定义:登录用户访问该页面的次数。
代码如下:
public static final String INIT_COUNT = "1";
public static final int TwoDaySeconds = 2 * 24 * 60 * 60;
/**
* 上报页面UV
*/
@Override
public void reportOpenPage(String userId) {
String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString();
// 统计 www.baidu.com/index.html 的页面访问UV
String key = String.format("%s:%s","wwww.baidu.com/index.html", date);
//打开页面次数 (PV)
String count = redisClient.hget(key, userId);
//为空:没有该用户的访问记录
if (StringUtils.isEmpty(count)) {
// redis 增加用户访问记录
redisClient.hset(key, userId, INIT_COUNT);
redisClient.expire(key, TwoDaySeconds);
log.info("打开页面用户访问uv增加,userId:{}",userId);
// 上报用户PV
report(xxxxxx);
} else {
//不为空:该用户今天已经访问过该页面:访问次数+1
log.info("打开页面用户访问uv不变,userId:{}",userId);
redisClient.hincrBy(key, userId, 1L);
}
}
这里使用了Redis 中的哈希表hash数据结构,创建一个哈希表,以URL+日期(年-月-日)
作为 key,以 userId 作为 field,PV 次数作为 value。
除重逻辑:
1、用户访问页面,产生页面PV
2、去缓存中查询是否有该用户的访问记录:hget URL+今天日期 userId
有:此人PV次数加一
没有:UV加一,添加该用户的访问记录 hset URL+今天日期 userId 1
注意:
- 需要设置过期时间,过期时间必须大于1天。
- 日期的获取需要注意时区。如果是System.milliSeconds获取时间戳,需要转换为不带有时区信息的日期,否则当使用EXPIREAT 或者 PEXPIREAT 会对过期时间产生影响,如果使用EXPIRE 或者 PEXIPRE命令设置过期秒数 24 * 60 * 60,就不需要关注这一点。