需求:要统计每天有多个用户访问这个渠道的H5页面,计算PV UV
废话少说,直接上代码:
(1)这个是渠道H5的index方法,利用Redis hash里的下面三个方法
HEXISTS key field
查看哈希表 key 中,指定的字段是否存在。
HINCRBY key field increment
为哈希表 key 中的指定字段的整数值加上增量 increment 。
HSET key field value
将哈希表 key 中的字段 field 的值设为 value 。
/**
* demo:要统计每天有多个用户访问这个渠道的H5页面
* 假设这个是访问H5首页的方法
* 页面访问一次,就计算一次 pv uv 数据
* @return
*/
public String index(HttpServletRequest request,Long channelId){
/*获取用户真实ip*/
String ip = Utils.getRealIp(request);
/*缓存key*/
String key = "CHANNEL_DATA_CACHE_KEY_" + channelId;
/*判断该缓存是否有该ip*/
boolean hexists = redisClient.hexists(key, ip);
if (hexists) {
/*有的话,说明之前该ip访问过,次数加1*/
redisClient.hincrby(key, ip, 1);
} else {
/*没有,说明第一次访问,给该ip计数1次*/
HashMap map = new HashMap<>(2);
map.put(ip, "1");
redisClient.hmset(key, map);
}
return "ok";
}
(2)统计缓存里的 pv uv,利用Redis hash里的下面三个方法
HLEN key
获取哈希表中字段的数量(UV)
HVALS key
获取哈希表中所有值(PV)
/**
* 统计pv uv,可做定时任务,每晚0点更新到DB里
* @return
*/
public String dataStatistics(Long channelId){
/*缓存key*/
String key = "CHANNEL_DATA_CACHE_KEY_" + channelId;
/*uv*/
Long uvToday = redisClient.hlen(key);
/*pv*/
List hvals = redisClient.hvals(key);
Long pvToday = 0L;
for (String str : hvals) {
pvToday += Long.valueOf(str);
}
return "ok";
}
获取用户真实IP :
public static String getRealIp(HttpServletRequest request) {
String ip = null;
//X-Forwarded-For:Squid 服务代理
String ipAddresses = request.getHeader("X-Forwarded-For");
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
//Proxy-Client-IP:apache 服务代理
ipAddresses = request.getHeader("Proxy-Client-IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
//WL-Proxy-Client-IP:weblogic 服务代理
ipAddresses = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
//HTTP_CLIENT_IP:有些代理服务器
ipAddresses = request.getHeader("HTTP_CLIENT_IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
//X-Real-IP:nginx服务代理
ipAddresses = request.getHeader("X-Real-IP");
}
//有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
if (ipAddresses != null && ipAddresses.length() != 0) {
ip = ipAddresses.split(",")[0];
}
//还是不能获取到,最后再通过request.getRemoteAddr();获取
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
ip = request.getRemoteAddr();
}
return ip;
}
RedisClient的全部方法奉上,供参考:
package com.aplus.config.redis;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import javax.annotation.Resource;
import java.util.*;
/**
* @author 王弘博
*/
@Component
public class RedisClient {
private Logger logger = LoggerFactory.getLogger(RedisClient.class);
@Resource
private JedisPool jedisPool;
public Long del(String key) {
Long value = null;
Jedis jedis = null;
try {
jedis = this.getResource();
if (jedis.exists(key)) {
value = jedis.del(key);
this.logger.debug("del {} = {}", key, value);
}
} catch (Exception e) {
this.logger.error("del {} = {}", new Object[]{key, value, e});
} finally {
this.release(jedis);
}
return value;
}
public String get(String key) {
String value = null;
Jedis jedis = null;
try {
jedis = this.getResource();
if (jedis.exists(key)) {
value = jedis.get(key);
value = StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
this.logger.debug("get {} = {}", key, value);
}
} catch (Exception e) {
this.logger.error("get {} = {}", new Object[]{key, value, e});
} finally {
this.release(jedis);
}
return value;
}
public String set(String key, String value) {
return this.set(key, value, 0);
}
public String set(String key, String value, int expire) {
Jedis jedis = null;
String result = null;
try {
jedis = this.getResource();
result = jedis.set(key, value);
if (expire != 0) {
jedis.expire(key, expire);
}
logger.debug("set {} = {}", key, value);
} catch (Exception e) {
logger.error("set {} = {}", new Object[]{key, value, e});
} finally {
this.release(jedis);
}
return result;
}
public boolean exists(String key) {
boolean result = false;
Jedis jedis = null;
try {
jedis = this.getResource();
result = jedis.exists(key);
} catch (Exception e) {
logger.error("exists {}", key, e);
} finally {
this.release(jedis);
}
return result;
}
/**
* ttl
*
* @param key
* @return
*/
public Long ttl(String key) {
Long result = 0L;
Jedis jedis = null;
try {
jedis = this.getResource();
result = jedis.ttl(key);
} catch (Exception e) {
logger.error("exists {}", key, e);
} finally {
this.release(jedis);
}
return result;
}
public Long incr(String key) {
return incrWithExpire(key, 0);
}
public Long incrWithExpire(String key, int seconds) {
Jedis jedis = null;
Long incr;
try {
if (StringUtils.isBlank(key)) {
incr = null;
return incr;
}
jedis = this.getResource();
incr = jedis.incr(key);
if (seconds > 0) {
jedis.expire(key, seconds);
}
} catch (Exception e) {
logger.error("incr {} ", key, e);
return null;
} finally {
this.release(jedis);
}
return incr;
}
public Long incrBy(String key, Long integer) {
Jedis jedis = null;
Long incrBy;
try {
if (StringUtils.isBlank(key)) {
incrBy = null;
return incrBy;
}
if (integer == null) {
integer = 0L;
}
jedis = this.getResource();
incrBy = jedis.incrBy(key, integer);
} catch (Exception e) {
logger.error("incr {} ", key, e);
return null;
} finally {
this.release(jedis);
}
return incrBy;
}
public Long incrByWithExpire(String key, Long integer, int seconds) {
Jedis jedis = null;
Long incrBy;
try {
if (StringUtils.isBlank(key)) {
incrBy = null;
return incrBy;
}
if (integer == null) {
integer = 0L;
}
jedis = this.getResource();
incrBy = jedis.incrBy(key, integer);
if (seconds > 0) {
jedis.expire(key, seconds);
}
} catch (Exception e) {
logger.error("incr {} ", key, e);
return null;
} finally {
this.release(jedis);
}
return incrBy;
}
public Long decrBy(String key, Long integer) {
Jedis jedis = null;
Long decrBy;
try {
if (StringUtils.isBlank(key)) {
decrBy = null;
return decrBy;
}
if (integer == null) {
integer = 0L;
}
jedis = this.getResource();
decrBy = jedis.decrBy(key, integer);
} catch (Exception e) {
logger.error("incr {} ", key, e);
return null;
} finally {
this.release(jedis);
}
return decrBy;
}
public Long decr(String key) {
Jedis jedis = null;
Long decr;
try {
if (StringUtils.isBlank(key)) {
decr = null;
return decr;
}
jedis = this.getResource();
decr = jedis.decr(key);
return decr;
} catch (Exception e) {
logger.error("decr {} ", key, e);
return null;
} finally {
this.release(jedis);
}
}
/**
* hgetAll
*
* @param key
* @return
*/
public Map hgetAll(String key) {
Map map = new HashMap<>();
Jedis jedis = null;
try {
if (StringUtils.isBlank(key)) {
return map;
}
jedis = this.getResource();
map = jedis.hgetAll(key);
return map;
} catch (Exception e) {
logger.error("hgetAll {} ", key, e);
return null;
} finally {
this.release(jedis);
}
}
/**
* hmset
*
* @param key
* @return
*/
public String hmset(String key, Map map) {
Jedis jedis = null;
try {
if (StringUtils.isBlank(key)) {
return null;
}
jedis = this.getResource();
return jedis.hmset(key, map);
} catch (Exception e) {
logger.error("hmset {} ", key, e);
return null;
} finally {
this.release(jedis);
}
}
/**
* hexists
*
* @param key
* @param field
* @return
*/
public boolean hexists(String key, String field) {
Jedis jedis = null;
try {
if (StringUtils.isBlank(key)) {
return false;
}
jedis = this.getResource();
return jedis.hexists(key, field);
} catch (Exception e) {
logger.error("hexists {} ", key, e);
return false;
} finally {
this.release(jedis);
}
}
/**
* hincrby
*
* @param key
* @param field
* @return
*/
public Long hincrby(String key, String field, long increment) {
Jedis jedis = null;
try {
if (StringUtils.isBlank(key)) {
return null;
}
jedis = this.getResource();
return jedis.hincrBy(key, field, increment);
} catch (Exception e) {
logger.error("hincrby {} ", key, e);
return null;
} finally {
this.release(jedis);
}
}
/**
* hlen
*
* @param key
* @return
*/
public Long hlen(String key) {
Jedis jedis = null;
try {
if (StringUtils.isBlank(key)) {
return null;
}
jedis = this.getResource();
return jedis.hlen(key);
} catch (Exception e) {
logger.error("hlen {} ", key, e);
return null;
} finally {
this.release(jedis);
}
}
/**
* hvals
*
* @param key
* @return
*/
public List hvals(String key) {
Jedis jedis = null;
List result = new ArrayList<>();
try {
if (StringUtils.isBlank(key)) {
return result;
}
jedis = this.getResource();
result = jedis.hvals(key);
} catch (Exception e) {
logger.error("hvals {} ", key, e);
return result;
} finally {
this.release(jedis);
}
return result;
}
/**
* hdel
*
* @param key
* @param fields
* @return
*/
public Long hdel(String key, String... fields) {
Jedis jedis = null;
try {
jedis = this.getResource();
return jedis.hdel(key, fields);
} catch (Exception e) {
logger.error("hdel {} ", key, e);
return null;
} finally {
this.release(jedis);
}
}
/**
* 获取分布式锁
*
* @param lockKey
* @return
*/
public boolean getLock(String lockKey) {
return this.getLock(lockKey, "1", 5);
}
/**
* 获取分布式锁
*
* @param lockKey
* @param requestId
* @param expireTime
* @return
*/
public boolean getLock(String lockKey, String requestId, int expireTime) {
Jedis jedis = null;
try {
jedis = this.getResource();
String result = jedis.set(lockKey, requestId, "NX", "EX", expireTime);
if ("OK".equals(result)) {
return true;
}
return false;
} catch (Exception e) {
logger.error("getLock {} ", lockKey, e);
return false;
} finally {
this.release(jedis);
}
}
/**
* 释放分布式锁
*
* @param lockKey
* @return
*/
public boolean unLock(String lockKey) {
return this.unLock(lockKey, "1");
}
/**
* 释放分布式锁
*
* @param lockKey
* @param requestId
* @return
*/
public boolean unLock(String lockKey, String requestId) {
Jedis jedis = null;
try {
String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
jedis = this.getResource();
Object result = jedis.eval(script, Collections.singletonList(lockKey),
Collections.singletonList(requestId));
if ("OK".equals(result)) {
return true;
}
return false;
} catch (Exception e) {
logger.error("unLock {} ", lockKey, e);
return false;
} finally {
this.release(jedis);
}
}
private Jedis getResource() throws Exception {
try {
return jedisPool.getResource();
} catch (Exception e) {
logger.error("getResource.", e);
throw e;
}
}
private void release(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
}