缓存一致性问题
之前在文章列表读取,最新文章等接口的时候我们加了缓存,但是加了缓存会有一些问题,当我们修改或者用户浏览了文章,那么最新的修改和文章的浏览数量无法及时的更新,那么应该怎么做呢?
这里我们采用RocketMQ来解决这个问题。
安装rocketMQ
#docker 拉取
docker pull foxiswho/rocketmq:4.8.0
#启动nameserver
docker run -d -v /usr/local/rocketmq/logs:/opt/docker/rocketmq/logs \
--name rmqnamesrv \
-e "JAVA_OPT_EXT=-Xms512M -Xmx512M -Xmn128m" \
-p 9876:9876 \
foxiswho/rocketmq:4.8.0 \
sh mqnamesrv
#broker.conf
brokerIP1=192.168.200.100
namesrvAddr=192.168.200.100:9876
brokerName=broker_all
#启动broker
docker run -d -v /opt/docker/rocketmq/logs:/usr/local/rocketmq/logs -v /opt/docker/rocketmq/store:/usr/local/rocketmq/store \
-v /opt/docker/rocketmq/conf:/usr/local/rocketmq/conf \
--name rmqbroker \
-e "NAMESRV_ADDR=192.168.200.100:9876" \
-e "JAVA_OPT_EXT=-Xms512M -Xmx512M -Xmn128m" \
-p 10911:10911 -p 10912:10912 -p 10909:10909 \
foxiswho/rocketmq:4.8.0 \
sh mqbroker -c /usr/local/rocketmq/conf/broker.conf
#rocketmq-console-ng
docker pull styletang/rocketmq-console-ng
docker run --name rmqconsole --link rmqnamesrv:rmqnamesrv \
-e "JAVA_OPTS=-Drocketmq.namesrv.addr=192.168.200.100:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" \
-p 8180:8080 -t styletang/rocketmq-console-ng
#启动访问 http://192.168.200.100:8180/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
集成
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
1
2
3
4
5
6
2
3
4
5
6
添加对应的配置:
#rocketmq配置
rocketmq.name-server=192.168.200.100:9876
rocketmq.producer.group=blog_group
1
2
3
2
3
代码:
if (isEdit){
//发送一条消息给rocketmq 当前文章更新了,更新一下缓存吧
ArticleMessage articleMessage = new ArticleMessage();
articleMessage.setArticleId(article.getId());
rocketMQTemplate.convertAndSend("blog-update-article",articleMessage);
}
1
2
3
4
5
6
2
3
4
5
6
package com.mszlu.blog.service.mq;
import com.alibaba.fastjson.JSON;
import com.mszlu.blog.service.ArticleService;
import com.mszlu.blog.vo.ArticleMessage;
import com.mszlu.blog.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.Set;
/**
* @author B站:码神之路
*/
@Slf4j
@Component
@RocketMQMessageListener(topic = "blog-update-article",consumerGroup = "blog-update-article-group")
public class ArticleListener implements RocketMQListener<ArticleMessage> {
@Autowired
private ArticleService articleService;
@Autowired
private StringRedisTemplate redisTemplate;
@Override
public void onMessage(ArticleMessage message) {
log.info("收到的消息:{}",message);
//做什么了,更新缓存
//1. 更新查看文章详情的缓存
Long articleId = message.getArticleId();
String params = DigestUtils.md5Hex(articleId.toString());
String redisKey = "view_article::ArticleController::findArticleById::"+params;
Result articleResult = articleService.findArticleById(articleId);
redisTemplate.opsForValue().set(redisKey, JSON.toJSONString(articleResult), Duration.ofMillis(5 * 60 * 1000));
log.info("更新了缓存:{}",redisKey);
//2. 文章列表的缓存 不知道参数,解决办法 直接删除缓存
Set<String> keys = redisTemplate.keys("listArticle*");
keys.forEach(s -> {
redisTemplate.delete(s);
log.info("删除了文章列表的缓存:{}",s);
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51