线上楼层错误问题
1.0版本的代码,先查最大楼层号,测试环境怎么测都没问题
//查询最大楼层号
Comments latestComment = commentsDAO.selectFirstByPostId(post.getId());
int maxFloorNum = 0;
if(latestComment != null) {
maxFloorNum = latestComment.getFloorNum();
}
logger.debug("addPostComment: the post_id {} maxFloorNum is {}", post.getId(), maxFloorNum);
//(2) 将回复插入到comments表
Comments comment = PostCommentConvert.toPostComment(commentReqBO);
comment.setForumCode(post.getForumCode());
comment.setFloorNum(maxFloorNum+1);
int num = commentsDAO.insertSelective(comment);
后来线上出了问题,以为是并发造成的,于是在发评论的时候加了锁
Comments comment = null;
int num = 0;
int sleepTimeMillis = 500, maxWaitSeconds = 5;//超时时间
//当前时间
long startTime = System.currentTimeMillis();
while (true) {
try {
//redis获取锁
simpleLock.tryLock(KeyBuilder.getKeySocialPostCommentLock());
} catch (YHLockFailedException e) { //尝试获取锁
try {
Thread.sleep(sleepTimeMillis);
} catch (InterruptedException e1) {}
long costTime = System.currentTimeMillis() - startTime;
if(costTime > TimeUnit.SECONDS.toMillis(maxWaitSeconds)) {
logger.warn("addPostComment: add timeout, post_id {}, millisecond time is {}", post.getId(), costTime);
throw new ServiceException(500, "添加评论超时");
}
continue;
}
break;
}
结果发现,还是有问题。这就纳闷了,后来询问以前做这个项目的人,他说这个项目是读写分离的,心想那估计是这个问题了,于是用redis来操作
//查询最大楼层号 + 1 int maxFloorNum = (int) countCache.incrementPostCommentFloorNum(post.getId(), 1);
public long incrementPostCommentFloorNum(Integer postId, Integer num) { logger.info("enter incrementPostCommentFloorNum. param postId is {}, num is {}", postId, num); // (1)校验forumCode if (null == postId || 1 > postId) { return 0; } String cacheKey = KeyBuilder.getKeySocialPostCommentFloorMaxNum(postId); long result = 0; // (2)判断缓存中是否有记录,没有记录则同步数据库数据,有则直接increment if (redisValueCache.setIfAbsent(cacheKey, 0, COMMENTS_NUM_IN_SEC, TimeUnit.MINUTES)) { Comments latestComment = commentsDAO.selectFirstByPostId(postId); int maxFloorNum = 1; if (latestComment != null) { maxFloorNum = latestComment.getFloorNum() + 1; } result = redisValueCache.increment(cacheKey, new Long(maxFloorNum), COMMENTS_NUM_IN_SEC, TimeUnit.MINUTES); } else { result = redisValueCache.increment(cacheKey, num, COMMENTS_NUM_IN_SEC, TimeUnit.MINUTES); } return result; }
至此问题解决,用到读写分离一定要注意!!!