diff --git a/han-note-note/han-note-note-biz/pom.xml b/han-note-note/han-note-note-biz/pom.xml
index 605257b..8272190 100644
--- a/han-note-note/han-note-note-biz/pom.xml
+++ b/han-note-note/han-note-note-biz/pom.xml
@@ -112,6 +112,12 @@
caffeine
+
+
+ org.apache.rocketmq
+ rocketmq-spring-boot-starter
+
+
diff --git a/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/comsumer/DelayDeleteNoteRedisCacheConsumer.java b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/comsumer/DelayDeleteNoteRedisCacheConsumer.java
new file mode 100644
index 0000000..ffb2efb
--- /dev/null
+++ b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/comsumer/DelayDeleteNoteRedisCacheConsumer.java
@@ -0,0 +1,31 @@
+package com.hanserwei.hannote.note.biz.comsumer;
+
+import com.hanserwei.hannote.note.biz.constant.MQConstants;
+import com.hanserwei.hannote.note.biz.constant.RedisKeyConstants;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+@Component
+@Slf4j
+@RocketMQMessageListener(consumerGroup = "han_note_group_" + MQConstants.TOPIC_DELAY_DELETE_NOTE_REDIS_CACHE, // Group
+ topic = MQConstants.TOPIC_DELAY_DELETE_NOTE_REDIS_CACHE // 消费的主题 Topic
+ )
+public class DelayDeleteNoteRedisCacheConsumer implements RocketMQListener {
+
+ @Resource
+ private RedisTemplate redisTemplate;
+
+ @Override
+ public void onMessage(String body) {
+ Long noteId = Long.valueOf(body);
+ log.info("## 延迟消息消费成功, noteId: {}", noteId);
+
+ // 删除 Redis 笔记缓存
+ String noteDetailRedisKey = RedisKeyConstants.buildNoteDetailKey(noteId);
+ redisTemplate.delete(noteDetailRedisKey);
+ }
+}
\ No newline at end of file
diff --git a/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/comsumer/DeleteNoteLocalCacheConsumer.java b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/comsumer/DeleteNoteLocalCacheConsumer.java
new file mode 100644
index 0000000..2f0a3fd
--- /dev/null
+++ b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/comsumer/DeleteNoteLocalCacheConsumer.java
@@ -0,0 +1,23 @@
+package com.hanserwei.hannote.note.biz.comsumer;
+
+import com.hanserwei.hannote.note.biz.constant.MQConstants;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.spring.annotation.MessageModel;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.stereotype.Component;
+
+@Component
+@Slf4j
+@RocketMQMessageListener(
+ consumerGroup = "han_note_group",
+ topic = MQConstants.TOPIC_DELETE_NOTE_LOCAL_CACHE,
+ messageModel = MessageModel.BROADCASTING
+)
+public class DeleteNoteLocalCacheConsumer implements RocketMQListener {
+ @Override
+ public void onMessage(String body) {
+ Long noteId = Long.valueOf(body);
+ log.info("## 消费者消费成功, noteId: {}", noteId);
+ }
+}
diff --git a/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/config/RocketMQConfig.java b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/config/RocketMQConfig.java
new file mode 100644
index 0000000..f290020
--- /dev/null
+++ b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/config/RocketMQConfig.java
@@ -0,0 +1,10 @@
+package com.hanserwei.hannote.note.biz.config;
+
+import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+@Configuration
+@Import(RocketMQAutoConfiguration.class)
+public class RocketMQConfig {
+}
\ No newline at end of file
diff --git a/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/constant/MQConstants.java b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/constant/MQConstants.java
new file mode 100644
index 0000000..dc40c77
--- /dev/null
+++ b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/constant/MQConstants.java
@@ -0,0 +1,14 @@
+package com.hanserwei.hannote.note.biz.constant;
+
+public interface MQConstants {
+
+ /**
+ * Topic 主题:删除笔记的本地缓存
+ */
+ String TOPIC_DELETE_NOTE_LOCAL_CACHE = "DeleteNoteLocalCacheTopic";
+
+ /**
+ * Topic 主题:延迟双删 Redis 笔记缓存
+ */
+ String TOPIC_DELAY_DELETE_NOTE_REDIS_CACHE = "DelayDeleteNoteRedisCacheTopic";
+}
\ No newline at end of file
diff --git a/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/service/impl/NoteServiceImpl.java b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/service/impl/NoteServiceImpl.java
index 2bb6ea8..41d97ac 100644
--- a/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/service/impl/NoteServiceImpl.java
+++ b/han-note-note/han-note-note-biz/src/main/java/com/hanserwei/hannote/note/biz/service/impl/NoteServiceImpl.java
@@ -11,6 +11,7 @@ import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder;
import com.hanserwei.framework.common.exception.ApiException;
import com.hanserwei.framework.common.response.Response;
import com.hanserwei.framework.common.utils.JsonUtils;
+import com.hanserwei.hannote.note.biz.constant.MQConstants;
import com.hanserwei.hannote.note.biz.constant.RedisKeyConstants;
import com.hanserwei.hannote.note.biz.domain.dataobject.NoteDO;
import com.hanserwei.hannote.note.biz.domain.dataobject.TopicDO;
@@ -33,7 +34,12 @@ import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -60,6 +66,8 @@ public class NoteServiceImpl extends ServiceImpl implement
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Resource
private RedisTemplate redisTemplate;
+ @Resource
+ private RocketMQTemplate rocketMQTemplate;
/**
* 笔记详情本地缓存
@@ -344,6 +352,10 @@ public class NoteServiceImpl extends ServiceImpl implement
}
}
+ // 删除 Redis 缓存
+ String noteDetailRedisKey = RedisKeyConstants.buildNoteDetailKey(noteId);
+ redisTemplate.delete(noteDetailRedisKey);
+
// 更新笔记元数据表
String content = updateNoteReqVO.getContent();
NoteDO noteDO = NoteDO.builder()
@@ -361,13 +373,39 @@ public class NoteServiceImpl extends ServiceImpl implement
if (!updateResult){
throw new ApiException(ResponseCodeEnum.NOTE_UPDATE_FAIL);
}
+
+ // 一致性保证:延迟双删策略
+ // 异步发送延时消息
+ Message message = MessageBuilder.withPayload(String.valueOf(noteId))
+ .build();
+
+ rocketMQTemplate.asyncSend(MQConstants.TOPIC_DELAY_DELETE_NOTE_REDIS_CACHE, message,
+ new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ log.info("## 延时删除 Redis 笔记缓存消息发送成功...");
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ log.error("## 延时删除 Redis 笔记缓存消息发送失败...", e);
+ }
+ },
+ 3000, // 超时时间(毫秒)
+ 1 // 延迟级别,1 表示延时 1s
+ );
+
// 删除Redis缓存
- String noteDetailRedisKey = RedisKeyConstants.buildNoteDetailKey(noteId);
+ noteDetailRedisKey = RedisKeyConstants.buildNoteDetailKey(noteId);
redisTemplate.delete(noteDetailRedisKey);
// 删除本地缓存
LOCAL_CACHE.invalidate(noteId);
+ // 同步发送广播模式 MQ,将所有实例中的本地缓存都删除掉
+ rocketMQTemplate.syncSend(MQConstants.TOPIC_DELETE_NOTE_LOCAL_CACHE, noteId);
+ log.info("====> MQ:删除笔记本地缓存发送成功...");
+
// 笔记内容更新
// 查询此篇笔记内容对应的 UUID
NoteDO noteDO1 = this.getById(noteId);
diff --git a/pom.xml b/pom.xml
index 010df35..d0c6ea2 100755
--- a/pom.xml
+++ b/pom.xml
@@ -60,6 +60,8 @@
0.9.16
5.9.0
3.9.4
+ 2.3.4
+ 5.3.2
@@ -265,6 +267,22 @@
caffeine
${caffeine.version}
+
+
+ org.apache.rocketmq
+ rocketmq-spring-boot-starter
+ ${rocketmq-spring-boot.version}
+
+
+ org.apache.rocketmq
+ rocketmq-client
+ ${rocketmq-client.version}
+
+
+ org.apache.rocketmq
+ rocketmq-acl
+ ${rocketmq-client.version}
+