1ãåæ
ç¹èµåè½æç¸ä¿¡å¤§å®¶é½ä¸éçï¼æå¼æååãB ç«ãæé³ãå°çº¢ä¹¦çå ³äºç¤¾äº¤ç¸å ³çåè½åºæ¬é½æç¹èµè¿ä¸åè½ï¼æä»¥æ¬ç¯ï¼å±ä»¬å°±æ¥åæä¸ä¸ç¹èµåè½å¦ä½æ¥å®ç°ã
é¦å ç¹èµè¯å®æ¯å¯¹æä¸ç±»æ°æ®è¿è¡ç¹èµï¼å¦ï¼B ç«å°±æè§é¢ç¹èµãè¯è®ºç¹èµã卿ç¹èµçãæä»¥ï¼æç §æä»¬å¸¸è§çå¥è·¯ï¼æ¯ä¸æ¯å°±åºè¯¥æè§é¢ç¹èµæ¥å£ï¼è¯è®ºç¹èµæ¥å£ï¼å¨æç¹èµæ¥å£çï¼ä½äºå®æç妿¤åï¼
ä½ çæè¿æ ·è®¾è®¡ï¼æ¯å¦å¯è¡ï¼
- æ°æ®idï¼è§é¢ãè¯è®ºçidï¼
- æ°æ®ç±»åï¼è§é¢ãè¯è®ºçï¼
- ç¹èµç¶æï¼trueï¼falseï¼
è¿æ ·éè¿ä¸åçåæ°ï¼å°å¤ä¸ªä¸åæ°æ®çç¹èµæ¥å£å½å°ä¸ä¸ªæ¥å£å½ä¸å®ç°ï¼è¿æ ·æ¯ä¸æ¯åå°äºä¸å¿ è¦çåä½ä»£ç ãä½éä¹èæ¥çé®é¢ä¹æ¯æ¾èæè§çï¼ä»¥åç¹èµåè½çæµéè¢«åæ£å°ä¸ä¸ªæå¤ä¸ªæ¥å£å½ä¸ï¼èç°å¨é½å½å°ä¸ä¸ªæ¥å£æ¥å®ç°ï¼é£ææçæµéå°±é½ä¼æå°ä¸ä¸ªç¹èµæ¥å£å½ä¸ï¼è¿å¯¹æ¥å£æ§è½å°±è¦æ±å¾é«äºã
ç°å¨ç¥éæ¥å£æä¹è®¾è®¡äºï¼é£åæ¥ççç¹èµè¡¨å¦ä½è®¾è®¡ï¼
æ ¹æ®æ¥å£ï¼æä»¬å¯ä»¥ç¡®å®è¿å ä¸ªåæ®µ
æ°æ®IDç¹èµç¶æ
ä¸ºå¥æ²¡ææ°æ®ç±»åï¼
æä»¬åæ³ä¸ä¸ï¼æ¥å£æ¥å ¥æ°æ®ç±»ç±»åæ¯ä¸ºäºéé æ´å¤çä¸åæ°æ®çç¹èµä¸å¡ãèç¹èµçè®°å½è¡¨æä¸ä¸ªç¹èµçæ°æ®IDï¼å°±å¯ä»¥éå®é£æ¡æ°æ®è¢«ç¹èµäºï¼æä»¥æ éæ°æ®ç±»åIDã
å½ç¶ä¸ºäºç¡®ä¿ç¥éç¨æ·ç¹èµäºé£æ¡æ°æ®ï¼æä»¥è¿éè¦å¦ä¸å段ï¼
ç¨æ·ID
æä»¥æåï¼æä»¬çç¹å¨è¡¨ SQL å°±æ¯ä¸é¢è¿æ ·ï¼
sqlå¤å¶ä»£ç
CREATE TABLE `sb_like` ( `id` bigint(20) NOT NULL, `item_id` bigint(20) NOT NULL COMMENT 'ç¹èµæ¡ç®id', `user_id` bigint(20) NOT NULL COMMENT 'ç¨æ·id', `like` tinyint(1) NOT NULL COMMENT 'æ¯å¦ç¹èµï¼trueç¹èµï¼falseæªç¹èµ', `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `un` (`item_id`,`user_id`), KEY `k` (`item_id`,`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_german2_ci
说æï¼
item_idï¼å¿ é¡»æ¯å ¨å±å¯ä¸IDï¼ä¾å¦ï¼éªè±IDï¼ï¼ä¹å³ä¸è½æ¯èªå¢ï¼å 为è¿å¼ ç¹èµè¡¨æ¯ææä¸å¡æ°æ®çç¹èµè®°å½ï¼è§é¢ãè¯è®ºã卿çï¼ãidï¼å段æå¥½ä¹æ¯å ¨å±å¯ä¸IDï¼å 为åæå¯è½éè¦è¿è¡åè¡¨ï¼æ¯ç«ç¹èµè®°å½æ¯ä¸ä¸ªå¢é¿è¯å¿«çæ°æ®éï¼å¦æç¨èªå¢IDï¼åæå¾é¾è¿ç§»ã
2ãå®ç°
ç°å¨æ ¹æ®ä¸é¢çåæï¼å¯ä»¥å¾åºç¹èµè¯·æ±çç®åæ°æ®æµåå¦ä¸å¾ï¼
å¯ä»¥çå°å¦æç³»ç»ä¸çä¸å¡æ°æ®è¶æ¥è¶å¤çè¯ï¼ç¹èµæ¥å£ç访é®éå°ä¼åå¾è¶æ¥è¶å¤§ï¼ä»èåæä¸ä¸ªé«é¢è®¿é®æ¥å£ï¼å½ç¶ï¼ç¹èµæ¬èº«å°±æ¯ä¸ä¸ªé«é¢çå¨ä½ï¼ã
æä»¥ï¼é¢å¯¹ä¸ä¸ªé«é¢æ¥å£ï¼å±ä»¬çç¹èµè®°å½è¯å®æ¯ä¸è½ç´æ¥å ¥ MySQL çï¼æä»¥è¿éå±ä»¬çç¹èµæ°æ®ç¬¬ä¸æ¥è¯å®æ¯å ¥ Redisã
ä¸ä¸ªæ¯åºäºç£çIOæä½ï¼MySQLï¼ï¼ä¸ä¸ªæ¯åºäºå åæä½ï¼Redisï¼ã
é£ï¼æ¢ç¶å¼å ¥ Redisï¼è¯å®åä¼å¼ç³åºä¸äºå ¶å®é®é¢ï¼å¦ï¼
- 使ç¨ä»ä¹æ°æ®ç±»ååå¨ç¹èµæ°æ®
- Redis æ°æ®å¦ä½åæ¥å° MySQL
- æ¥è¯¢ç¨æ·ç¹èµï¼ä¸å¡æ°æ®çç¹èµéä¼åå¾å¤æå¾å¤
é对è¿ä¸ä¸ªé®é¢ï¼ä¹å¥½è§£å³ï¼ææè§£å³çå¤§è´æè·¯è±äºå¼ å¾ï¼ç¸ä¿¡ä¸å¾èåè¨ï¼
注ï¼Redis çå卿°æ®ç±»å为 hash
okï¼ä¸é¢å°±æ¯æä»¬çç¼ç å®ç°ç¯èäºï¼å æ¥åç¹èµæ¥å£ï¼è¿ä¸ªé常好å®ç°ã
2.1 ç¹èµæ¥å£å®ç°
1ï¼controller
ä½ç½®ï¼cn.j3code.community.api.v1.controller
javaå¤å¶ä»£ç @Slf4j
@ResponseResult
@AllArgsConstructor
@RestController
@RequestMapping(UrlPrefixConstants.WEB_V1 + "/like")
public class LikeController {
private final LikeService likeService;
/**
* ç¹èµ
* @param request
*/
@PostMapping("/")
public void like(@Validated @RequestBody LikeRequest request) {
likeService.like(request);
}
}
LikeRequest 对象
ä½ç½®ï¼cn.j3code.community.api.v1.request
javaå¤å¶ä»£ç @Data
public class LikeRequest {
@NotNull(message = "æ¡ç®idä¸ä¸ºç©º")
private Long itemId;
@NotNull(message = "ç¹èµä¸ä¸ºç©º")
private Boolean like;
@NotNull(message = "ç±»åä¸ä¸ºç©º")
private CommentTypeEnum type;
}
CommentTypeEnum æä¸¾
ä½ç½®ï¼cn.j3code.config.enums
javaå¤å¶ä»£ç @Getter
public enum CommentTypeEnum {
COMMODITY(1, "ååè¯è®º"),
POST_COMMENT(2, "å¸åè¯è®º"),
POST(3, "å¸å"),
;
@EnumValue
private Integer value;
private String description;
CommentTypeEnum(Integer value, String description) {
this.value = value;
this.description = description;
}
}
2ï¼service
ä½ç½®ï¼cn.j3code.community.service
javaå¤å¶ä»£ç public interface LikeService extends IService<Like> {
void like(LikeRequest request);
}
@Slf4j
@AllArgsConstructor
@Service
public class LikeServiceImpl extends ServiceImpl<LikeMapper, Like>
implements LikeService {
private final RedisTemplate<String, Object> redisTemplate;
@Override
public void like(LikeRequest request) {
redisTemplate.opsForHash().put(
SbUtil.getItemLikeKey(request.getType().getValue() + ":" + request.getItemId()),
Objects.requireNonNull(SecurityUtil.getUserId(), "è·åç»å½äººä¿¡æ¯åºéï¼").toString(),
request.getLike());
}
}
æ¯ä¸æ¯é常ç®åï¼åªéè¦ç»è£ 好 hash ç»æçæ°æ®ï¼è®¿é®ä¸ä¸ Redis å³å¯ã
2.2 ç¹èµæ°æ®åæ¥æ°æ®åºå®ç°
å颿们æå°è¿ï¼æä¹ 忝éè¿å®æ¶ä»»å¡è¿è¡çï¼æä»¥è¿éæä¸ç¹ç¹é®é¢å°±æ¯å¦æå¨å®æ¶ä»»å¡è¿æªæ§è¡çæ¶åï¼Redis æäºï¼é£è¿æ®µæ¶é´çç¹èµè®°å½å°ä¼ä¸¢å¤±ãä¸çº¿çæ¶åï¼Redis çæä¹ ååè½è¦è®°å¾é 好ï¼AOF/RDBï¼ã
ç°å¨ï¼æä»¬æ¥åæåæç¹èµæ°æ®åæ¥å°æ°æ®åºçæµç¨ï¼
- è·åå¯¹åºæ°æ®ç±»åçææç¹èµ key
- æ ¹æ®è·åå°ç keyï¼è·åææçç¹èµè®°å½ï¼æ°æ®æ ¼å¼ä¸º Map<ä¸å¡æ°æ®IDï¼Map<ç¨æ·IDï¼ç¹èµç¶æ>>
- ç»å Redis ç¹èµè®°å½ + MySQL æä¹ åè®°å½ï¼è®¡ç®åºå䏿¡æ°æ®çæç»ç¹èµç¶æåæ°æ®çç¹èµæ°é
- ç§»é¤ redis ä¸ï¼å·²ç»åæ¥çæ°æ®
- æ´æ°ä¸å¡æ°æ®ç¹èµæ°é
- æå ¥ç¨æ·ç¹èµè®°å½æ°æ®
è¿éï¼å¯è½2ã3ç¹å¤§å®¶æç¹ä¸å¥½çè§£ï¼æ²¡å ³ç³»ï¼æå å¼ æµç¨å¾æ´ä½æ¥çæè¿ä¸ªæµç¨ï¼å忥åæä½ 们çæçç¹ï¼
å¨å¾ä¸ï¼æå·²ç»æè½è§£éçé®é¢é½å·²ç»è§£éæ¸ æ¥äºï¼ä¸é¢å°±ç代ç å®ç°å§ï¼
å 为ç¹èµä¸å¡æå¾å¤ï¼æä»¥å¯¹åºç宿¶ä»»å¡è¯å®ä¹æ¯ä¸åçï¼è¿éæä»¥æ¬é¡¹ç®çå¸å为ä¾ï¼æ¥å®ç°å¸åæ°æ®ç¹èµæ°æ®ç忥ã
1ï¼schedule
ä½ç½®ï¼cn.j3code.community.schedule
javaå¤å¶ä»£ç @Slf4j
@Component
@AllArgsConstructor
public class PostLikeSchedule {
private final PostService postService;
/**
* 忥å¸åç¹èµ
*/
@DistributedLock
@Scheduled(cron = "11 0/9 * * * ?")
public void syncPostLike(){
postService.syncPostLike();
}
}
2ï¼service
ä½ç½®ï¼cn.j3code.community.service
javaå¤å¶ä»£ç public interface PostService extends IService<Post> {
void syncPostLike();
}
@Slf4j
@AllArgsConstructor
@Service
public class PostServiceImpl extends ServiceImpl<PostMapper, Post>
implements PostService {
private final LikeServiceImpl likeService;
private final RedisTemplate<String, Object> redisTemplate;
private final TransactionTemplate transactionTemplate;
@Override
public void syncPostLike() {
// è·åå¸åç¹èµ key
List<String> keys = new ArrayList<>(redisTemplate.keys(SbUtil.getItemLikeKey(CommentTypeEnum.POST.getValue() + ":*")));
if (CollectionUtils.isEmpty(keys)) {
return;
}
Set<Long> commentIdList = keys.stream().map(key -> Long.valueOf(key.substring(key.lastIndexOf(":") + 1)))
.collect(Collectors.toSet());
// æ¹éæ¥ç redis è¯è®ºidï¼çç¹èµæ°æ®
ItemLikeBO itemLikeBO = likeService.getItemLikeCount(new ArrayList<>(commentIdList), CommentTypeEnum.POST, Boolean.TRUE);
Map<Long, Integer> itemLikeCount = itemLikeBO.getItemLikeCount();
/**
* å¸åid 对åºï¼ç¨æ·id å ç¹èµç¶æ ç map
*/
Map<Long, Map<Long, Boolean>> postToUserLikeMap = itemLikeBO.getItemIdToUserLikeMap();
// å¾
ä¿®æ¹çè¯è®ºçç¹èµæ°ééå
List<Post> updatePostList = new ArrayList<>();
// å¾
æå
¥çç¹èµéå
List<Like> saveLikeList = new ArrayList<>();
postToUserLikeMap.forEach((postId, likeMap) -> {
Post post = new Post();
post.setId(postId);
post.setLikeCount(itemLikeCount.get(postId));
updatePostList.add(post);
likeMap.forEach((key, value) -> {
Like like = new Like();
like.setId(SnowFlakeUtil.getId());
like.setItemId(postId);
like.setUserId(key);
like.setLike(value);
like.setCreateTime(LocalDateTime.now());
like.setUpdateTime(LocalDateTime.now());
saveLikeList.add(like);
});
});
Map<Long, Post> postMap = lambdaQuery()
.in(Post::getId, postToUserLikeMap.keySet()).list()
.stream().collect(Collectors.toMap(Post::getId, item -> item));
// ç¹èµæ°éçäº æ°æ®åº + redis
updatePostList.forEach(item ->
item.setLikeCount(item.getLikeCount() + postMap.get(item.getId()).getLikeCount()));
String format = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
log.info(format + "-忥ç¹èµæ°æ®ï¼updatePostList={}ï¼saveLikeList={}",
JSON.toJSONString(updatePostList),
JSON.toJSONString(saveLikeList));
// ä¿®æ¹æ°æ®åº
MyTransactionTemplate.execute(transactionTemplate, accept -> {
CollUtil.split(updatePostList, 100).forEach(this::updateBatchById);
CollUtil.split(saveLikeList, 100).forEach(likeService::saveOrUpdateByDuplicate);
}, format + "-忥å¸åç¹èµé»è¾åºéï¼");
}
}
å ¶ä¸ï¼likeService.getItemLikeCount ç代ç å°±æ¯ä¸å¾ä¸ç第3ã4ã5çå®ç°ï¼å®æ¯ç¹èµé»è¾çå ¬ç¨æ¹æ³ï¼åææ¹éç¹èµåæ¥ãå ¶å®ç±»å忥坹åºç3ã4ã5é»è¾é½æ¯è°ç¨è¯¥æ¹æ³å®ç°çã代ç å¦ä¸ï¼
3ï¼getItemLikeCount æ¹æ³å®ç°
ä½ç½®ï¼cn.j3code.community.service
javaå¤å¶ä»£ç public interface LikeService extends IService<Like> {
/**
*
* @param itemIdList æ¡ç®idéå
* @param type æ¡ç®çæ°æ®ç±»å
* @param redisDataRemove ç»è®¡å®åï¼æ¯å¦ç§»é¤redisä¸çæ°æ®
* @return
*/
ItemLikeBO getItemLikeCount(List<Long> itemIdList, CommentTypeEnum type, Boolean redisDataRemove);
}
@Slf4j
@AllArgsConstructor
@Service
public class LikeServiceImpl extends ServiceImpl<LikeMapper, Like>
implements LikeService {
private final RedisTemplate<String, Object> redisTemplate;
@Override
public ItemLikeBO getItemLikeCount(List<Long> itemIdList, CommentTypeEnum type, Boolean redisDataRemove) {
ItemLikeBO itemLikeBO = new ItemLikeBO();
Map<Long, Integer> result = new HashMap<>();
itemIdList.forEach(itemId -> result.put(itemId, 0));
// æ¹éæ¥ç redis è¯è®ºidï¼çç¹èµæ°æ®
List<Object> executePipelined = redisTemplate.executePipelined(new SessionCallback<>() {
@Override
public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
for (Long itemId : itemIdList) {
redisOperations.opsForHash().entries((K) SbUtil.getItemLikeKey(type.getValue() + ":" + itemId));
}
return null;
}
});
/**
* è¯è®ºid 对åºï¼ç¨æ·id å ç¹èµç¶æ ç map
*/
Map<Long, Map<Long, Boolean>> commentToUserLikeMap = new HashMap<>();
for (int i = 0; i < itemIdList.size(); i++) {
if (Objects.isNull(executePipelined.get(i))) {
continue;
}
Long commentId = itemIdList.get(i);
Map<String, Boolean> likeMap = (Map<String, Boolean>) executePipelined.get(i);
Map<Long, Boolean> lb = new HashMap<>();
likeMap.forEach((k, v) -> lb.put(Long.valueOf(k), v));
commentToUserLikeMap.put(commentId, lb);
if (redisDataRemove) {
/**
* è¿é伿ä¸ç¹ç¹é®é¢ï¼å°±æ¯å¦æå¨è·åç¹èµ ä¸ å é¤ç¹èµ çæ¶é´ç©ºéä¹é´ï¼åä¸ä¸ªç¨æ·åæä½äºåä¸ä¸ªè¯è®ºçç¹èµ
* é£è¿å°ä¼å¯¼è´æ°æ®ä¸¢å¤±
* è§£å³æ¹æ³ï¼
* 1ãå é
* 2ãæ¹ç¨ MQ æ¹å¼
*/
// å é¤ä¸ä¸ redis ä¸ç ç¹èµ è®°å½
redisTemplate.opsForHash().delete(
SbUtil.getItemLikeKey(type.getValue() + ":" + commentId),
likeMap.keySet().stream().map(Object::toString).toArray(Object[]::new));
}
}
for (int i = 0; i < itemIdList.size(); i++) {
Map<Long, Boolean> redisUserLikeMap = commentToUserLikeMap.get(itemIdList.get(i));
if (Objects.nonNull(redisUserLikeMap) && CollectionUtils.isNotEmpty(redisUserLikeMap.keySet())) {
// æ¥è¯¢æ°æ®åºä¸ï¼è¯¥è¯è®ºçç¹èµè®°å½
Map<Long, Boolean> dbUserLikeMap = lambdaQuery()
.eq(Like::getItemId, itemIdList.get(i))
.eq(Like::getLike, Boolean.TRUE)
.in(Like::getUserId, redisUserLikeMap.keySet())
.list().stream().collect(Collectors.toMap(Like::getUserId, Like::getLike));
// redis ä¸ æ°æ®åºç¹èµè®°å½ ç»å
AtomicInteger redisLikeCount = new AtomicInteger(0);
for (Map.Entry<Long, Boolean> entry : redisUserLikeMap.entrySet()) {
// æ°æ®åºåå¨ç¹èµï¼redis åæ¶ç¹èµï¼é£ç¹èµæ°éåä¸
if (dbUserLikeMap.containsKey(entry.getKey()) && Boolean.FALSE.equals(entry.getValue())) {
redisLikeCount.set(redisLikeCount.get() - 1);
}
// æ°æ®åºåå¨ç¹èµï¼redis åå¨ç¹èµï¼é£ Redis ç¹èµç¶æå为 falseï¼ä¸è®°å½æ»ç¹èµæ°éä¸
if (dbUserLikeMap.containsKey(entry.getKey()) && Boolean.TRUE.equals(entry.getValue())) {
entry.setValue(Boolean.FALSE);
}
}
redisLikeCount.set(redisLikeCount.get() +
Integer.parseInt(redisUserLikeMap.values().stream().filter(like -> like).count() + "")
);
result.put(itemIdList.get(i), redisLikeCount.get());
}
}
itemLikeBO.setItemLikeCount(result);
itemLikeBO.setItemIdToUserLikeMap(commentToUserLikeMap);
return itemLikeBO;
}
}
代ç å®ç°çé»è¾åºæ¬åæä¸å¾ä¸ç»çæµç¨ä¸è´ï¼èä¸æä»£ç æ³¨éä¹åå¾å¾æ¸ æ¥ï¼ç¸ä¿¡ä½ 们åºè¯¥è½çæã
2.3 æ°æ®æ¥è¯¢åå¡«ç¹èµè®°å½
飿åä¸ä¸ªåè½å°±æ¯æ¥è¯¢ä¸å¡æ°æ®çæ¶åæä»¬ä¸ä» è¦å§MySQLä¸çç¹èµæ°æ®æ¥åºæ¥ï¼è¿è¦æ Redis ä¸çæ°æ®ä¸åæ¥åºæ¥è¿è¡ç»è£ ï¼æåæææ°æ®åæ¾å°é¡µé¢ã
ä¸è¿ï¼è¿ä¸ªé»è¾ä¸æ¯å¾é¾ï¼å 为æäº 2.2 èçå ¬å ±æ¹æ³çå®ç°ï¼æä»¥è¿ä¸æ¥å°ä¼åå¾ç®åäºã
åæè¯¥é»è¾ä¹åï¼æä»¬å æ¥ççï¼é¡µé¢è¦æ¾ç¤ºç¹èµçé£äºæ°æ®ï¼é¡µé¢å¦ä¸ï¼
- å½åç»å½äººç¹èµç¶æ
- ä¸å¡æ°æ®çç¹èµæ°é
okï¼æä»¬å æ¥åæç¨æ·ç¹èµç¶æçè·åæµç¨ï¼
- å°æ¥è¯¢å°çä¸å¡æ°æ®éå转为 Map<ä¸å¡IDï¼ç¨æ·ç¹èµç¶æ>ï¼åå§æ åµä¸ï¼ç¶æé½ä¸º false
- æ ¹æ®ä¸å¡IDãç¨æ·IDãç¹èµç¶æï¼trueï¼ï¼æ¥è¯¢MySQLçç¹èµè®°å½ï¼å°å¯¹åºçæ°æ®åå¡«å° ç¬¬ä¸æ¥ç Map ä¸
- åéè¿ç®¡éæä½ï¼æ¹éè®¿é® Redisï¼æ¾å° hash key为ä¸å¡idï¼å±æ§ key 为 ç¨æ·id çç¹èµè®°å½ï¼å°æ¾å°çæ°æ®ç´æ¥è¦çå° Map ä¸
- æç»ï¼Map ä¸çæ°æ®ï¼å°±æ¯ç¨æ·æ¯å¦ç¹èµä¸å¡çæ è¯äºã
èç¹èµæ°éæå°±ä¸åæä¸å¡æµç¨äºï¼å 为 2.2 èå·²ç»åæè¿äºå°±æ¯ getItemLikeCount æ¹æ³çå®ç°ï¼åªä¸è¿è¿éç redisDataRemove åæ°ä¸º false ï¼ä¸éè¦ç§»é¤ redis çæ°æ®ï¼å ä¸ºè¿æ¯ä¸ä¸ªæ¥è¯¢ï¼è䏿¯åæ¥ã
ä¸é¢ï¼æ¥ççæçæ¥è¯¢ä¸å¡æ°æ®å表伪代ç å®ç°ï¼
ç¨ä¼ªä»£ç å®ç°æ¯å 为æ¥è¯¢çæµç¨åºæ¬å°±æ¯å æ¥ä¸å¡æ°æ®ï¼ç¶ååå¡«ç¹èµæ°æ®ï¼èå䏿¥å°±æ²¡å¿ è¦å大家说äºï¼æç¨ä¼ªä»£ç ä½ç°åå¡«ç¹èµçæ°æ®å³å¯ï¼ç¸ä¿¡å¤§å®¶é½æã
javaå¤å¶ä»£ç public IPage<PostVO> page(PostPageRequest request) {
// å
æ¥è¯¢ MySQL çä¸å¡æ°æ®
// ç¨æ·è¯è®ºç¹èµç¶æ
Map<Long, Boolean> itemIdToLikeMap = likeService.getItemLikeState(voiPage.getRecords().stream().map(PostVO::getId).collect(Collectors.toList()), CommentTypeEnum.POST);
// redis ä¸è¯è®ºç¹èµæ°é
Map<Long, Integer> itemIdToLikeCountMap = likeService.getItemLikeCount(voiPage.getRecords().stream().map(PostVO::getId).collect(Collectors.toList()), CommentTypeEnum.POST, Boolean.FALSE)
.getItemLikeCount();
// å¡«å
è¯è®ºç¹èµæ°éåå½åç¨æ·ç¹èµç¶æï¼ç¨æ·ä¿¡æ¯
ä¸å¡æ°æ®å表.forEach(postVO -> {
设置ä¸å¡æ°æ®ç¹èµæ°æ®(ä¸å¡MySQLç¹èµæ°é + itemIdToLikeCountMap.get(postVO.getId()));
设置ä¸å¡æ°æ®ç¨æ·ç¹èµç¶æ(itemIdToLikeMap.get(postVO.getId()));
});
}
getItemLikeState æ¹æ³å®ç°ï¼
javaå¤å¶ä»£ç public Map<Long, Boolean> getItemLikeState(List<Long> itemIdList, CommentTypeEnum type) {
Map<Long, Boolean> result = new HashMap<>();
itemIdList.forEach(itemId -> result.put(itemId, Boolean.FALSE));
if (Objects.isNull(SecurityUtil.getUserId())) {
// æªç»å½
return result;
}
if (CollectionUtils.isEmpty(itemIdList)) {
return result;
}
// æ¥çæ°æ®åºä¸æ¯å¦æç¨æ·ç¹èµè®°å½
lambdaQuery()
.eq(Like::getUserId, SecurityUtil.getUserId())
.eq(Like::getLike, Boolean.TRUE)
.in(Like::getItemId, itemIdList)
.list().forEach(likeObj -> {
if (likeObj.getLike()) {
result.put(likeObj.getItemId(), Boolean.TRUE);
}
});
// æ¥ç redis ç¨æ·ç¹èµè®°å½
List<Object> executePipelined = redisTemplate.executePipelined(new SessionCallback<>() {
@Override
public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
for (Long itemId : itemIdList) {
redisOperations.opsForHash().get(
(K) SbUtil.getItemLikeKey(type.getValue() + ":" + itemId),
SecurityUtil.getUserId().toString());
}
return null;
}
});
for (int i = 0; i < itemIdList.size(); i++) {
if (Objects.nonNull(executePipelined.get(i))) {
result.put(itemIdList.get(i), (Boolean) executePipelined.get(i));
}
}
return result;
}
è¿ä¸ªæ¹æ³ï¼å°±æ¯æä¸é¢åæç代ç å®ç°äºã
å°æ¤ï¼æä»¬æ´ä¸ªçä¸ä¸ªä¸å¡ç¹èµåè½çå®ç°å°±ç®å®æäºï¼å½ç¶å ¶ä¸è¯å®æ¯æåä¸å¥½çç¹åéè¦æ©å çç¹ï¼
- ä¸å¥½çç¹ï¼å¦ä½è§£å³æ¥è¯¢ Redis æ°æ®ä¸ç§»é¤ Redis æ°æ®ä¹é´åå¨çæ°æ®å·®ï¼æè 说åå°æ¶é´é´é
- ä¸å¥½çç¹ï¼å¦ä½è§£å³åæ¥ç¹èµæ°æ®å°MySQLåºéï¼è导è´ç¹èµè®°å½ä¸¢å¤±é®é¢ï¼ç®åï¼æ¥å¿æ¢å¤ï¼
- æ©å çç¹ï¼ç¨æ·ç¹èµä¹åï¼å¯ä»¥åéç¸å ³ç MQ æ¶æ¯ï¼åç¥ç¨æ·ï¼æç¤ºç¨æ·ä¿¡æ¯æç¥åº¦
妿è¿äºå¤§å®¶æå¥½ç建议ï¼å¯ä»¥è¯è®ºéèèã