Authored by bblu

获取排队列表加入redis缓存

/**
*
*/
package com.yoho.activity.common.redis;
import org.apache.commons.lang3.StringUtils;
/**
*
* @author bblu
*
*/
public enum CacheKeyEnum {
DRAWLINE_LIST("yh:activity:", "activity.drawlinelist.redisSwitch", "activity.drawlinelist.redisExpire", "活动排队列表");
// 缓存的key
private String cacheKey;
// 开关的key(如果为空,则开关key与缓存key一样)
private String switchKey;
// 超时时间配置的key
private String expireKey;
private String desc;
private CacheKeyEnum(String cacheKey, String switchKey, String expireKey, String desc) {
this.cacheKey = cacheKey;
this.switchKey = switchKey;
this.expireKey = expireKey;
this.desc = desc;
}
/**
* 获取该枚举的信息
*
* @param key
* @return
*/
public static CacheKeyEnum getEnumByKey(String key) {
if (StringUtils.isEmpty(key)) {
return null;
}
for (CacheKeyEnum e : values()) {
if (key.equalsIgnoreCase(e.name())) {
return e;
}
}
return null;
}
public String getCacheKey() {
return cacheKey;
}
public String getSwitchKey() {
return switchKey;
}
public String getExpireKey() {
return expireKey;
}
public String getDesc() {
return desc;
}
}
\ No newline at end of file
... ...
package com.yoho.activity.common.redis;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicPropertyFactory;
/**
* 缓存所有的KEY的管理 格式: 所有的KEY均由 yh:users:XXXX 开头
*
* @author Created by dengxinfei on 2016/3/13.
*/
public class CacheKeyHelper {
static Logger log = LoggerFactory.getLogger(CacheKeyHelper.class);
/**
* 根据枚举,获取该枚举对应的缓存key
* 获取之前需要判断缓存总开关和该缓存对应的开关
* 开关配置在cachesSwitch.properties中
* @param cacheKey
* @param obj
* @return
*/
public static String getCacheKeyAndCheck(CacheKeyEnum cacheKey, Object obj) {
//获取总开关
DynamicBooleanProperty totalOnoff = DynamicPropertyFactory.getInstance().getBooleanProperty("redis.total.key.switch", false);
log.info("getCacheKeyAndCheck. totalOnoff is {}, cacheKey is {}, obj is {}", totalOnoff.get(), cacheKey, obj);
if (!totalOnoff.get()) {
return null;
}
//如果开关的key为空,则用缓存key代替
String switchKey = cacheKey.getSwitchKey();
if (StringUtils.isEmpty(switchKey)) {
switchKey = cacheKey.getCacheKey();
}
//获取该缓存对应的开关
DynamicBooleanProperty onoff = DynamicPropertyFactory.getInstance().getBooleanProperty(switchKey, false);
if (!onoff.get()) {
return null;
}
log.debug("getCacheKeyAndCheck key is {}", cacheKey.getCacheKey());
return cacheKey.getCacheKey() + obj;
}
/**
* 序列化value值
* @param value
* @return
*/
public static <T> String value2String(T value) {
String v = null;
if (value == null) {
return null;
}
if (value instanceof String) {
v = (String) value;
} else {
v = JSON.toJSONString(value);
}
return v;
}
/**
* 反序列化value值
* @param value
* @param clazz
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T string2Value(String value, Class<T> clazz) {
if (StringUtils.isEmpty(value)) {
return null;
}
if (clazz.getName().equalsIgnoreCase("java.lang.String")) {
return (T) value;
}
return (T) JSON.parseObject(value, clazz);
}
}
... ...
package com.yoho.activity.common.redis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.netflix.config.DynamicLongProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.yoho.core.redis.YHListOperations;
import com.yoho.core.redis.YHRedisTemplate;
/**
*
* @author bblu
*
*/
@Component
public class RedisListCache {
private static final Logger logger = LoggerFactory.getLogger(RedisListCache.class);
@Autowired
YHRedisTemplate<String, String> yHRedisTemplate;
@Autowired
YHListOperations<String, String> yhListOperations;
/**
* redis range 操作
*
* @param cacheEnum
* 缓存开关的枚举
* @param obj
* 缓存key的后缀
* @param clazz
* 对象类型
* @param start
* 开始索引
* @param end
* 结束索引
* @return
*/
public <T> List<T> range(CacheKeyEnum cacheEnum, Object obj, Class<T> clazz, long start, long end) {
logger.debug("Enter range redis list. cacheEnum is {}, obj is {}, clazz is {}", cacheEnum, obj, clazz);
String cacheKey = CacheKeyHelper.getCacheKeyAndCheck(cacheEnum, obj);
// 如果获取的key为空,则说明缓存开关是关闭的
if (StringUtils.isEmpty(cacheKey)) {
return null;
}
try {
List<String> strList = yhListOperations.range(cacheKey, start, end);
logger.info("range redis value. value size {}", strList == null ? 0 : strList.size());
if (CollectionUtils.isEmpty(strList)) {
return null;
}
// 遍历,组装对象
List<T> list = new ArrayList<T>();
for (String str : strList) {
list.add(CacheKeyHelper.string2Value(str, clazz));
}
return list;
} catch (Exception e) {
logger.warn("get redis value operation failed. key is {}", cacheKey, e);
}
return null;
}
/**
* redis range 操作
*
* @param cacheEnum
* 缓存开关的枚举
* @param obj
* 缓存key的后缀
* @param clazz
* 对象类型
* @param start
* 开始索引
* @param end
* 结束索引
* @return
*/
public <T> void rightPushAll(CacheKeyEnum cacheEnum, Object obj, Collection<T> values) {
logger.debug("Enter rightPushAll redis list. cacheEnum is {}, obj is {}, value is {}", cacheEnum, obj, values);
// 如果是空列表,直接返回
if (CollectionUtils.isEmpty(values)) {
return;
}
String cacheKey = CacheKeyHelper.getCacheKeyAndCheck(cacheEnum, obj);
// 如果获取的key为空,则说明缓存开关是关闭的
if (StringUtils.isEmpty(cacheKey)) {
return;
}
try {
Collection<String> strValues = new ArrayList<String>();
for (T t : values) {
String strValue = CacheKeyHelper.value2String(t);
if (StringUtils.isEmpty(strValue)) {
continue;
}
strValues.add(strValue);
}
yhListOperations.rightPushAll(cacheKey, strValues);
DynamicLongProperty expire = DynamicPropertyFactory.getInstance().getLongProperty(cacheEnum.getExpireKey(), 10);
yHRedisTemplate.longExpire(cacheKey, expire.get(), TimeUnit.SECONDS);
} catch (Exception e) {
logger.warn("rightPushAll redis list operation failed. key is {}", cacheKey, e);
}
}
public boolean hasKey(CacheKeyEnum cacheEnum, Object obj) {
logger.debug("Enter hasKey redis list. cacheEnum is {}, obj is {}", cacheEnum, obj);
String cacheKey = CacheKeyHelper.getCacheKeyAndCheck(cacheEnum, obj);
// 如果获取的key为空,则说明缓存开关是关闭的
if (StringUtils.isEmpty(cacheKey)) {
return false;
}
try {
return yHRedisTemplate.hasKey(cacheKey);
} catch (Exception e) {
logger.warn("hasKey redis list operation failed. key is {}", cacheKey, e);
}
return false;
}
}
... ...
... ... @@ -10,6 +10,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yoho.activity.common.cache.RedisCache;
import com.yoho.activity.common.redis.CacheKeyEnum;
import com.yoho.activity.common.redis.RedisListCache;
import com.yoho.activity.queue.convert.DrawlineUserQueueConvert;
import com.yoho.activity.queue.service.IDrawlineList2MapService;
import com.yoho.activity.queue.service.IDrawlineUserQueueService;
... ... @@ -38,6 +40,8 @@ public class DrawlineUserQueueServiceImpl implements IDrawlineUserQueueService {
@Autowired
private RedisCache redisCache;
@Autowired
private RedisListCache redisListCache;
public int addDrawlineUserQueue(DrawlineUserQueueReqBO drawlineUserQueueReqBO) throws ServiceException {
logger.info("Enter addDrawlineUserQueue. param drawlineUserQueueReqBO is {}", drawlineUserQueueReqBO);
... ... @@ -91,102 +95,10 @@ public class DrawlineUserQueueServiceImpl implements IDrawlineUserQueueService {
throw new ServiceException(900001007, "参加活动排队失败");
}
// // (6)查询排队序号
// drawlineUserQueue =
// drawlineUserQueueDAO.selectByUidAndActivityIdAndUserType(uid,
// activityId, userType);
// logger.debug("addDrawlineUserQueue: drawlineUserQueueDAO.selectByUidAndActivityIdAndUserType. uid is {}, activityId is {}, userType is {}, drawlineUserQueue is {}",
// uid, activityId, userType,
// drawlineUserQueue);
//
// // (7)返回
// int sort = null == drawlineUserQueue.getSort() ? 0 :
// drawlineUserQueue.getSort().intValue();
logger.info("addDrawlineUserQueue: return. drawlineUserQueueReqBO is {}, sort is {}", drawlineUserQueueReqBO, sort);
return sort;
}
// public int addDrawlineUserQueue(DrawlineUserQueueReqBO
// drawlineUserQueueReqBO) throws ServiceException {
// logger.info("Enter addDrawlineUserQueue. param drawlineUserQueueReqBO is {}",
// drawlineUserQueueReqBO);
//
// // (1)获取参数
// int uid = 0, activityId = 0;
// byte userType = 1;
// if (null != drawlineUserQueueReqBO) {
// uid = null == drawlineUserQueueReqBO.getUid() ? 0 :
// drawlineUserQueueReqBO.getUid().intValue();
// activityId = null == drawlineUserQueueReqBO.getActivityId() ? 0 :
// drawlineUserQueueReqBO.getActivityId().intValue();
// userType = null == drawlineUserQueueReqBO.getUserType() ? 1 :
// drawlineUserQueueReqBO.getUserType().byteValue();
// }
//
// // (2)校验
// validAddDrawlineUserQueue(uid, activityId);
//
// // (3)判断活动是否存在,是否过期
// DrawlineActivity drawlineActivity =
// drawlineActivityDAO.selectByPrimaryKey(activityId);
// if (null == drawlineActivity) {
// logger.warn("addDrawlineUserQueue: drawlineActivity is not exists");
// throw new ServiceException(900001003, "活动已不存在");
// }
// int beginTime = null == drawlineActivity.getBeginTime() ? 0 :
// drawlineActivity.getBeginTime().intValue();
// int endTime = null == drawlineActivity.getEndTime() ? 0 :
// drawlineActivity.getEndTime().intValue();
// int currentTime = (int) (System.currentTimeMillis() / 1000);
// if (0 < beginTime && currentTime < beginTime) {
// logger.warn("addDrawlineUserQueue: drawlineActivity is not begin");
// throw new ServiceException(900001004, "活动尚未开始");
// }
// if (0 < endTime && currentTime > endTime) {
// logger.warn("addDrawlineUserQueue: drawlineActivity is already end");
// throw new ServiceException(900001005, "活动已结束");
// }
//
// // (4)判断是否已经参加排队
// DrawlineUserQueue drawlineUserQueue =
// drawlineUserQueueDAO.selectByUidAndActivityIdAndUserType(uid, activityId,
// userType);
// logger.debug("addDrawlineUserQueue: drawlineUserQueueDAO.selectByUidAndActivityIdAndUserType. uid is {}, activityId is {}, userType is {}, drawlineUserQueue is {}",
// uid, activityId, userType,
// drawlineUserQueue);
// if (null != drawlineUserQueue) {
// logger.warn("addDrawlineUserQueue: drawlineUserQueue is exists already");
// throw new ServiceException(900001006, "您已经参加过排队,无需再次排队");
// }
//
// // (5)组装数据,新增排队
// drawlineUserQueue = DrawlineUserQueueConvert.toDOBy(uid, activityId,
// userType);
// int rows = drawlineUserQueueDAO.insertAutoSort(drawlineUserQueue);
// logger.debug("addDrawlineUserQueue: drawlineUserQueueDAO.insertAutoSort. drawlineUserQueue is {}, rows is {}",
// drawlineUserQueue, rows);
// if (1 > rows) {
// logger.warn("addDrawlineUserQueue: fail to addDrawlineUserQueue. uid is {}, activityId is {}, userType is {}",
// uid, activityId, userType);
// throw new ServiceException(900001007, "参加活动排队失败");
// }
//
// // (6)查询排队序号
// drawlineUserQueue =
// drawlineUserQueueDAO.selectByUidAndActivityIdAndUserType(uid, activityId,
// userType);
// logger.debug("addDrawlineUserQueue: drawlineUserQueueDAO.selectByUidAndActivityIdAndUserType. uid is {}, activityId is {}, userType is {}, drawlineUserQueue is {}",
// uid, activityId, userType,
// drawlineUserQueue);
//
// // (7)返回
// int sort = null == drawlineUserQueue.getSort() ? 0 :
// drawlineUserQueue.getSort().intValue();
// logger.info("addDrawlineUserQueue: return. drawlineUserQueueReqBO is {}, sort is {}",
// drawlineUserQueueReqBO, sort);
// return sort;
// }
public List<DrawlineUserQueueRespBO> getDrawlineUserQueueList(DrawlineUserQueueReqBO drawlineUserQueueReqBO) throws ServiceException {
logger.info("Enter getDrawlineUserQueueList. param drawlineUserQueueReqBO is {}", drawlineUserQueueReqBO);
... ... @@ -195,7 +107,7 @@ public class DrawlineUserQueueServiceImpl implements IDrawlineUserQueueService {
if (null != drawlineUserQueueReqBO) {
activityId = null == drawlineUserQueueReqBO.getActivityId() ? 0 : drawlineUserQueueReqBO.getActivityId().intValue();
sort = null == drawlineUserQueueReqBO.getSort() ? 0 : drawlineUserQueueReqBO.getSort().intValue();
limit = drawlineUserQueueReqBO.getLimit();
limit = 1 > drawlineUserQueueReqBO.getLimit() ? 10 : drawlineUserQueueReqBO.getLimit();
}
// (2)校验
... ... @@ -216,14 +128,22 @@ public class DrawlineUserQueueServiceImpl implements IDrawlineUserQueueService {
return new ArrayList<DrawlineUserQueueRespBO>();
}
// (4)查询条件下,总记录数
int total = drawlineUserQueueDAO.selectCountBy(activityId, sort);
logger.debug("getDrawlineUserQueueList: drawlineUserQueueDAO.selectCountBy. activityId is {}, sort is {}, total is {}", activityId, sort, total);
// (4)重新计算sort,以补齐客户端记录数
if (0 < sort && sort < limit) {
sort = limit;
}
// (5)查询排队信息,如果条件记录总数小于分页数需补齐记录
if (0 < sort && total < limit) {
sort += limit - total;
// (5)redis 获取数据
if (0 < sort) { // sort为0时表示查询最新数据,不从redis中获取数据
String redisKeySuffix = activityId + ":" + sort + ":" + limit;
List<DrawlineUserQueueRespBO> drawlineUserQueueRespBOList = redisListCache.range(CacheKeyEnum.DRAWLINE_LIST, redisKeySuffix, DrawlineUserQueueRespBO.class, 0, -1);
if (null != drawlineUserQueueRespBOList) {
logger.info("getDrawlineUserQueueList: get result from redis. first result is {}", drawlineUserQueueRespBOList.get(0));
return drawlineUserQueueRespBOList;
}
}
// (6) 查询排队列表
List<DrawlineUserQueue> drawlineUserQueueList = drawlineUserQueueDAO.selectBy(activityId, sort, limit);
logger.debug("getDrawlineUserQueueList: drawlineUserQueueDAO.selectBy. activityId is {}, sort is {}, limit is {}, drawlineUserQueueList is {}", activityId, sort, limit, drawlineUserQueueList);
if (null == drawlineUserQueueList || 0 == drawlineUserQueueList.size()) {
... ... @@ -231,23 +151,38 @@ public class DrawlineUserQueueServiceImpl implements IDrawlineUserQueueService {
throw new ServiceException(900001008, "无人参与活动排队");
}
// (6)组装uids
// (7)组装uids
List<Integer> uidList = getUidList(drawlineUserQueueList);
// (7)调用查询用户信息服务
// (8)调用查询用户信息服务
AsyncFuture<UserBaseRspBO[]> userBaseRspBOArrAsync = drawlineList2MapService.postForUserBaseInfo(uidList);
// (8)查询用户中奖信息
// (9)查询用户中奖信息
Map<String, DrawlineLuckyUser> drawlineLuckyUserMap = drawlineList2MapService.getDrawlineLuckyUserMap(activityId, uidList);
// (9)查询马甲信息
// (10)查询马甲信息
Map<Integer, DrawlineVirtualUser> drawlineVirtualUserMap = drawlineList2MapService.getDrawlineVirtualUserMap(uidList);
// (10)获取用户信息
// (11)获取用户信息
Map<Integer, UserBaseRspBO> userBaseRspBOMap = drawlineList2MapService.getUserBaseRspBOMap(userBaseRspBOArrAsync);
// (11)组装返回
// (12)组装返回
List<DrawlineUserQueueRespBO> drawlineUserQueueRespBOList = DrawlineUserQueueConvert.toBOListByDOList(drawlineUserQueueList, drawlineLuckyUserMap, userBaseRspBOMap, drawlineVirtualUserMap);
// (13)数据保存至redis
for (DrawlineUserQueueRespBO drawlineUserQueueRespBO : drawlineUserQueueRespBOList) {
if (null == drawlineUserQueueRespBO || null == drawlineUserQueueRespBO.getSort()) {
continue;
}
sort = drawlineUserQueueRespBO.getSort().intValue();
break;
}
String redisKeySuffix = activityId + ":" + sort + ":" + limit;
if (redisListCache.hasKey(CacheKeyEnum.DRAWLINE_LIST, redisKeySuffix)) {
return drawlineUserQueueRespBOList;
}
redisListCache.rightPushAll(CacheKeyEnum.DRAWLINE_LIST, redisKeySuffix, drawlineUserQueueRespBOList);
return drawlineUserQueueRespBOList;
}
... ...
... ... @@ -35,3 +35,14 @@ drawline.luckydraw.interval=1440
# ******************** drawline lucky user notice task interval(TimeUnit.MINUTES) ********************
drawline.luckyUserNotice.interval=120
#******************* Redis **************************#
#total switch
redis.total.key.switch=true
#drawlinelist switch
activity.drawlinelist.redisSwitch=true
#drawlinelist expire time(second)
activity.drawlinelist.redisExpire=10
... ...
... ... @@ -35,3 +35,14 @@ drawline.luckydraw.interval=${drawline.luckydraw.interval}
# ******************** drawline user notice task interval(TimeUnit.MINUTES) ********************
drawline.luckyUserNotice.interval=${drawline.luckyUserNotice.interval}
#******************* Redis **************************#
#total switch
redis.total.key.switch=true
#drawlinelist switch
activity.drawlinelist.redisSwitch=true
#drawlinelist expire time(second)
activity.drawlinelist.redisExpire=10
... ...