最近做了一个评论的点赞功能,感觉有必要记录一下。
思路:
点赞功能,看起来挺简单,但是做的高效稳定还是需要一些处理。
归纳思路如下:
1.点赞接口要利用redis做点赞次数限制,比如一分钟之内最多点赞或取消点赞四次
2.点赞是很高频随兴的操作,最好不要直接操作数据库,先把点赞信息放入redis缓存,然后跑定时任务每15秒去同步到数据库,同步完之后把同步好的信息批量从redis删除。
3.把点赞信息放入redis缓存的时候选用hashset类型存储,结构大概为hset(rediskey,hashKey,value)的形式。
4.要保证定时任务同步的时候不会内存溢出,所以存储在redis里的时候要分页去存储,比如每5000条生成一个redisKey,然后递归去取值点赞记录同步到数据库,这样每次取值最大也就5000条,避免因数据量太大导致的内存溢出问题。
5.每个人对每条评论只会有一条数据,要么点赞要么取消点赞。
示例
点赞或取消点赞controller:
/**
* app点赞或取消点赞
* @param uid
* @param appId
* @param lang
* @param reqid
* @param paramsObj
* @return
*/
@PostMapping(value = "/comments/venucia/app/likeorcancellike")
public ResponseVO likeOrCancelLike(
@RequestHeader(required = true) String uid,
@RequestHeader(required = false) String appId,
@RequestHeader(required = false) String lang,
@RequestHeader(name = "reqid", required = false) String reqid,
@RequestBody JSONObject paramsObj) {
ResponseVO paramsVo = CommentsUtil.validLikeOrCancelLikeParamsObj(paramsObj, lang);
if(ErrorCodeEntity.ERROR_1.equals(paramsVo.getResult())){
logger.info("appLikeOrCancellike请求参数:{},reqid{},uid{}", paramsObj.toJSONString(), reqid, uid);
Map paramsMap = new HashMap();
paramsMap.put("moduleTypeId", paramsObj.getString("moduleTypeId"));//模块类型id
paramsMap.put("topicId", Long.parseLong(paramsObj.getString("topicId")));//文章或主题id
paramsMap.put("commentId", paramsObj.getString("commentId"));//评论id
paramsMap.put("level", paramsObj.getString("level"));//1为一级评论2为2级评论
paramsMap.put("userId", paramsObj.getString("userId"));//评论人id
paramsMap.put("type", paramsObj.getString("type"));//1是点赞,0是取消点赞
paramsMap.put("lang", AppFrameworkUtil.getLang(lang));
paramsMap.put("uid", uid);//点赞人id
ResponseVO resultVo = appCommentsService.likeOrCancelLike(paramsMap);
return resultVo;
}
return paramsVo;
}
点赞或取消点赞impl(把点赞信息存储在redis里,每个key最多存5000条数据):
public ResponseVO likeOrCancelLike(Map paramsMap) {
String lang = paramsMap.get("lang").toString();
String code = ErrorCodeEntity.ERROR_1;
String message = ErrorMsgLang.errorMsg(code, lang);
String moduleTypeId = paramsMap.get("moduleTypeId").toString();
String topicId = paramsMap.get("topicId").toString();
String commentId = paramsMap.get("commentId").toString();
String level = paramsMap.get("level").toString();
String uid = paramsMap.get("uid").toString();
//检验一分钟内同一用户对同一条评论不能超过四次
String validKey = Constant.REDIS_PREFIX + "lik