1ãåæ
ç¹èμåè1/2æç ̧ä¿¡å§å¶é1/2ä ̧éçï1/4æå1/4æåãB ç«ãæé³ãå°çº¹¦çå ³äºç¤3/4äºç ̧å ³çåè1/2åºæ¬é1/2æç¹èμè¿ä ̧åè1/2ï1/4æä»¥æ¬ç ̄ï1/4å±ä»¬å°±æ¥åæä ̧ä ̧¹èμåè1/2å¦ä1/2æ¥å®®ç°ã
é¦to â¹èμè ̄to ̄¹æä ̧ç±»æ°æ è¿è¡ç¹èμï1/4å¦ï1/4B ç«oh±æ§é¢ç¹èμãè ̄è ºç¹èμãå ̈æç¹èμçãæ ä»¥ï1/4æç §æä»¬to®̧è§å¥· ̄ï1/4æ ̄ä ̧æ ̄å°±ohºè ̄¥æ§é¢ùèμæ¥ãï1/4è ̄è§¹èμæ®®®¥ãï1/4å ̈æç¹èμæ¥å£çï1/4ä1/2äºå æç宦æ¤ï1/4
ä1/2 çæè¿æ ·è®3/4è¡ï1/4æ ̄å¦å ̄计ï1/4
- æ°æ®idï1/4è§é¢ãè ̄论çidï1/4
- æ°æ®ç±»åï1/4è§é¢ãè ̄论çï1/4
- ç¹èμç¶æï1/4trueï1/4falseï1/4
è¿æ ·éè¿ä ̧åæ°ï1/4å¤ä ̧êä°æ â¹èμæ¥å£å1/2å°ä ̧ä ̧êæ¥å£å1/2ä ̧ðï1®/4è¿æ ·æ ̄ä ̧å°úä ̧å¿ è¦çåä1/2代ç ãä1/2éä¹èæ¥çé é¢ä¹æ ̄æ3/4èæ§ï1/4以åç¹èμåè1/2çæμéè®®¢ « yæ°ä ̧ä ̧ªæå¤ä ̧ªææ¥å1/2ä ̧ï1/4èç°å ̈é1/2å1/2å°ä ̧ä ̧ªææ¥ææ¥å ç°ï1/4飿çæμéå°±é1/2ä1/4æå°ä ̧ä ̧ªç¹èμæ¥å£å£å1/2ä ̧ï1/4è¿å ̄¹æ£æ§è1/2å®°±è¦æ±å3/4é«äºã
ç°å ̈ç¥éæ¥å£æä¹è 3/4è¡äºï1/4é£åæ¥ççç¹èμè¡ ̈å¦ä1/2è 3/4è®®®®¡ï1/4
æ æ®¥ï1/4æä"¬å ̄ä"¥á ®®è¿å ä̧ªåæ®μ
Æææ ID箹èμç¶æ
ä ̧ºå¥æ²¡ææ°æ®ç±»åï1/4
æä"¬yæ³ä ̧ä ̧ï1/4æ±"åæ ̧°æ ±"ç"åæ ̄ä ̧ºúéé æ ́å¤çä ̧âæ°æ çùçâ°æ ̧å¤ ̧ä ̧êç¹èμçæ°æ IDï1/4å°±å ̄ä"¥éå 飿¡æ°æ 碫ç¹èμäºï1/4æä»¥æ éæ°æ®®®®®ç®±»åIDã®
å1/2ç¶ä ̧ºäºç¡®ä¿ç¥éç ̈æ·ç¹èμäºé£æ¡æ°æ ï1/4æä»¥è¿éè¦å¦ä ̧åæ®®μï1/4
ç ̈æ·ID
æä»¥æåï1/4æä»¬çç¹å ̈è¡ ̈ SQL å°±æ ̄ä ̧é¢è¿æ ·ï1/4
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
è ̄ ́æï1/4
item_idï1/4å¿ é¡»æ ̄å ̈å±å ̄ä ̧IDï1/4ä3/4å¦ï1/4éªè±IDï1/4ï1/4ä¹å³ä ̧è1/2æ ̄èªå¢ï1/4å ̧ºè¿å1/4 ç¹èμè¡ ̈æ ̈æ ̧è¿å1/4 �æä ̧å°æ â¹èμè°å1/2ï1/4è®§é¢ãè ̄论ãå ̈æçï1/4ãidï1/4åæ μæå¥1/2乿®®̄å ̈å±å ̄ä ̧IDï1/4å ̧ºyy ̄è1/2éè¦è¿è¡è¡ ̈ï1/4æ ̄ç«èμè®°å1/2æ ̄ä ̧äªå¢é¿è ̄å¿æ®éï1/4妿ç ̈èªå¢IDï1/4åæå3/4é3/4è¿ç§»ã
2nd®ç°
§°å ̈æ ¹æ ̧é¢çåæï1/4å ̄以å3/4åºç¹èμè ̄·æ±çç®åæ°æ®®æμyy¦ä ̧å3/4ï1/4
to ̄以çå¦æç³»ä ̧ä ̧áæ°æ è¶æ¥è¶å§è ̄ï1/4ç¹èμæ¥å£çè¿é éå°ä1/4åå3/4è¶æ¥è¶§ï1/4ä»èåæä ̧ä ̧ªé«é¢è¿é æ¥å£ï1/4å1/2ç¶ï1/4ç¹èμæ®®¬èº®«oh°±æ ̄ä ̧ä̧ªé«é®®¢çå ̈ä1/2ï1/4ã
æä»¥ï1/4é¢å ̄¹ä ̧ä ̧ªé«é¢æ£ï1/4å±ä»¬ç¹èμè®°å1/2è ̄å æ ̄ä ̧è1/2ç ́æ¥å ¥ MySQL çï1/4æä»¥è¿éå±ä»¬ç¹èμæ°æ ̧殥è ̄宿 ̄宥 Redisã
ä ̧ä ̧ªæ ̄åºäºç£çIOæä1/2ï1/4MySQLï1/4ï1/4a ̧ä ̧§ªæ ̄åºäºå åæä1/2ï1/4Redisï1/4ã
é£ï1/4æ¢ç¶å1/4å ¥ Redisï1/4è ̄å åä1/4å1/4ç³åºä ̧äºå é®®é¢ï1/4宦ï1/4
- ä1/2¿ç ̈ä»ä¹æ°æ ç±»yyy ̈ç¹èμæ°æ®®
- Redis æ°æ å¦ä1/2åæ®¥å° MySQL
- æ¥è ̄¢ç ̈æ·ç¹èμï1/4ä ̧塿°æ®çç¹èμéä1/4åå3/4夿3/4夤
éå ̄¹è¿ä ̧ä ̧ªé®é¢ï1/4ä¹å¥1/2è§£å³ï1/4ææ§£å³ç大è ́æ· ̄è±äºå1/4 å3/4ï1/4ç ̧ä¿¡ä ̧å3/4èåè ̈ï1/4
æ³ ̈ï1/4Redis çyy ̈æ°æ®ç±»yä ̧º hash
okï1/4ä ̧é¢å°±æ ̄æä»¬çç1/4ç to ðç ̄èäºï1/4⧪éå ̧̧å£1/®2å ç®°ã
2.1 ç¹èμæ¥ãå®ç°
1ï1/4controller
ä1/2ç1/2®ï1/4cn.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 to ̄¹è±¡
ä1/2ç1/2®ï1/4cn.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 æä ̧3/4
ä1/2ç1/2®ï1/4cn.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ï1/4service
ä1/2ç1/2®ï1/4cn.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());
}
}
æ ̄ä ̧æ ̄éå ̧ç åï1/4åªéè¦ç®»è å£1/2 hash ç»æçæ°æ®ï1/4访é®ä ̧ä ̧ Redis ̙å ̄ã
2.2 ç¹èμæ°æ yæ°æ®®úå®ç°
åé¢æä»¬æ°¿ï1/4æä¹ åæ ̄é¨¿å æ¶ä»»å®¡è¿è¡çï1/4æä»¥è¿éæä ̧ùç¹é é¢å°±æ ̦̄æå ̈å æ¶ä»»»å¨¿æ§è§áçæ¶åï1/4Redis æºï1/4é£è¿æ®μæ¶é®́ç§¹èμè®°å1/2å°ä1/4ä ̧¢å®¤±ãä ̧ú¿çæ¶åï1/4Redis çæä¹ yyy1/2è¦è®°å3/4é å¥1/2ï1/4AOF/RDBï1/4ã
§°å ̈ï1/4æä"¬æææç¹èμæ°æ yæ°æ°æ åºçæμç®®̈ï1/4
- è·yy ̄¹åºæ°æ®ç±»YÇÆÆÇ¹èμ Key
- æ ¹æ è·yyİç keyï1/4è·åæçç¹èμè°å1/2ï1/4æ°æ æ 1/4å1/4ä ̧º Map<ä ̧塿°æ IDï1/4Map<ç ̈æ·IDï1/4ç¹èμç¶æ®®®>>®
- ç»to Redis ç¹èμè°å1/2 + MySQL æä¹ yè°å1/2ï1/4è¡ç åºyä ̧æ°æ°æ çæç»ç¹èμç®®®¶ææ°æ ç箹èμæ®®°é
- ç§»é¤ redis ä ̧ï1/4å·²ç»åæ¥çæ°æ®
- æ°ä ̧塿°æ ç¹èμæ®°é
- æå ¥ç ̈æ·ç¹èμè®°å1/2æ°æ®
è¿éï1/4å ̄è1/22ã3ùå§å¶æùä ̧宥1/2çè§£ï1/4æ²¡å ³ç³»ï1/4æå å1/4 æμç ̈å3/4æ ́ä1/2æ¥çæ¿ä ̧ªæμç ̈ï1/4忥åæä1/2 们çæç¹ï1/4
to ̈å3/4ä ̧ï1/4æå·²ç»æè1/2è§£éçé é¢é1/2å·²ç»è§£éæ ̧ æ¥äºï1/4ä ̧鮢就ç代ç çï1®/4
to ä ̧ºç¹èμä ̧塿å3/4å¤ï1/4æä»¥å ̄¹åºçå æ¶ä»»å¡è ̄ùæ ̄ä®̧åçï1/4è¿éæä»¥æ¬é¡¹ç®̧åä®̧ºä3/4ï1/4楮å çåæ°æ ç¹èμæ°æ çåæ®®¥ã
1ï1/4schedule
ä1/2ç1/2®ï1/4cn.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ï1/4service
ä1/2ç1/2®ï1/4cn.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 + "-忥å¸åç¹èµé»è¾åºéï¼");
}
}
to ¶ä ̧ï1/4likeService.getItemLikeCount ç代ç ð±æ ̄ä ̧å3/4ä ̧第3ã4ã5çå ç°ï1/4å æ ̄ç¹èμé»è3/4çå ¬ç ̈æ¹æ³ï1/4åæ¹éç¹èμ忥ããå ¶å ç±»yyy¥å ̄¹å§3ã4ã5é»è3/4é1®/2æ°ç ̈è ̄¹æ³å®®®ç°çãä»£ç æä ̧ï1/4
3ï1/4getItemLikeCount æ¹æ³å®ç°
ä1/2ç1/2®ï1/4cn.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;
}
}
代ç å ç°çé»è3/4åºæ¬åæä ̧å3/4ä ̧ç»çæμç ̈ä ̧è ́ï1/4èä ̧æä»£ç æ³ ̈éä¹åå3®/4æ ̧ æ¥ï1/4ç ̧ä¿¡ä1/2 们åºè ̄¥è1/2çæã
2.3 æ°æ®æ¥è ̄¢yy¡«ç¹èμè®°å1/2
飿ä ̧ä ̧ªåè1/2å°±æ ̄æ¥è ̄¢ä ̧å°æ çæ¶åæä"¬ä ̧ä" è¦å§MySQLä ̧çç¹èμæ°æ æºæ¥ï1/4è¿è¦æ Redis ä ̧çæ°æ ä ̧åæºæ¥è¿è¡ç»è£ ï1/4æ°æ°æ®®®®åæ3/4å°é¡μé¢ã
ä ̧è¿ï1/4è¿ä ̧ªé»è3/4ä ̧æ ̄å3/4é3/4ï1/4å ̧ºæäº 2.2 èçå ±æ¹æ³çå ç°ï1/4æä»¥è¿ä ̧æ¥å®°ä1/4åå3/4ç®åºã
åæè ̄¥é»è3/4ä¹åï1/4æä»¬å æ¥ççï1/4é¡μé¢è¦æ3/4示ç¹èμçé£äºæ°æ®ï1/4é¡μé¢å¦ä ̧ï1/4
- å1/2åç»å1/2人ç¹èμç¶æ
- ä ̧塿°æ çç¹èμæ®°é
okï1/4æä»¬å æ¥åæç ̈æ·ç¹èμç¶æçè·åæμç ̈ï1/4
- å°æ¥è ̄¢å°çä ̧å°æ°æ éåè1/2¬ä ̧º Map<ä ̧å¡IDï1/4ç ̈æ·ç¹èμç¶æ>ï1/4yå§æ®åμä ̧ï1/4ç¶æé1/2ä ̧º false
- ®I don't want to IDãç ̈æ· IDãç¹èμç¶æï1/4trueï1/4ï1/4æ¥è ̄¢MySQLçç¹èμè®°å1/2ï1/4å°å ̄¹yºçæ°æ yy¡«oh° 第ä ̧殥ç Map ̧
- åéè¿ç¡éæä1/2ï1/4æ¹éè¿é® Redisï1/4æ3/4å° hash keyä ̧ºä ̧å¡idï1/4屿§ key ä ̧º ç ̈æ·id çùèμè°å1/2ï1/4å°æ3/4å°çæ°æ ç® ́殥议¦çå° Map ä ̧
- æç»ï1/4Map ä ̧çæ°æ ï1/4å°±æ ̄ç ̈æ·æ ̄å¦ç¹èμä ̧å¡çæ®è ̄äºã
èç¹èμæ°éæå°±ä ̧åæä ̧塿μç ̈äºï1/4å ̧º 2.2 èå·²ç»yæ¿ä°±æ ̄ getItemLikeCount æ¹æ³çå ðï1/4åªä ̧è¿éç redisDataRemove åæ°ä ̧º false ï1/4ä ̧éè¦ç§»é¤ redis çæ°æ ï1/4å®̧ºè¿æ ̄ä ̧ä ̧ªæ¥è ̄¢ï1/4èä ̧æ ̄åæ®¥ã
ä ̧é¢ï1/4æ¥ççæçæ¥è ̄¢ä ̧塿°æ®åè¡ ̈ä1/4ªä»£ç å®ç°ï1/4
ç ̈ä1/4ªä»£ç to®ðæ ̄to ̧ºæ¥è ̄¢çæμç ̈åºæ¬å°±æ ̄å æ¥ä̧塿°æ ï1/4ç¶yyy¡«ç¹èμæ°æ ï1/4èåä ̧æ¥ oh±æ²¡y¿ èy¶® è ̄ ́äºï1/4æç ̈ä1/4ªä»£ç ä1/2ç°yyġ«ç¹èμçæ°æ å³å ̄ï1/4ç̧ä¿¡Ť§å®¶é1/2æã®®®
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 æ¹æ³å®ç°ï1/4
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;
}
è¿ä ̧ªæ¹æ³ï1/4å°±æ ̄æä ̧é¢åæç代ç å®ç°äºã
å°æ¤ï1/4æä"¬æ ́ä ̧ªçä ̧ä ̧ªä ̧å¡ç¹èμåè1/2çå ç°å°±ç to æäºï1/4å1/2ç¶å ¶ä ̧è ̄å æ ̄æä®̧宥1/2çç¹åéè¦æ©to®ç箹ï1/4
- ä ̧å¥1/2ç¹ï1/4å¦ä1/2è§£å³æ¥è ̄¢ Redis æ°æ ä ̧ç§»é¤ Redis æ°æ ä¹é ́yňçæ°æ å·®ï1/4æè è ̄ ́y°æ®®®¶é ́é ́é
- ä ̧å¥1/2çç¹ï1/4å¦ä1/2è§£å³y楹èμæ°æ å°MySQLåºéï1/4èå ̄1/4è ́ç¹èμè®°å1/2ä ̧¢å¤±é 鮢ï1/4ç®åï1/4æ®¥å¿æ¢å¤ï1/4
- ©æ å çç¹ï1/4ç ̈æ·ç¹èμä¹åï1/4å ̄以åéç ̧å ³ç MQ æ¶æ ̄ï1/4åç¥ç ̈æ·ï1/4æç¤ºç ̈æ·ä¿¡æ ̄æç¥åº¦
y¦æ¿ä§å¶æå¥1/2ç建è ï1/4å® ̄以è ̄论éèèã®®