前言:
在这一篇文章当中我会以RcoketMQ来对其的使用的场景进行一个仔细地说明,这个里面也会涉及到一些额外的知识,看完之后对面试而言的话那么就是直接拿捏,当然在看这篇文章之前要先看MQ的基础知识-CSDN博客 毕竟基础才是王道,下面就是开始我们的正菜
在我的基础的那篇文章中就说了MQ的作用就是 异步 削峰 解耦,我们也直到我们生产者将消息发送到MQ之后会被Broker进行持久化保证消息不丢失,但是我们的生产者是怎么知道我们消息成功发送到MQ的,当MQ发送消息给消费者进行消费者进行消费的时候,那MQ是怎么知道我的消息已经被消费者消费了,下面的话就会揭晓这个神秘的面纱
准备步骤:
第一步:引入依赖
<!-- RocketMQ Spring Boot Starter -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.2.1</version>
</dependency>
第二步:配置文件
rocketmq:
name-server: 127.0.0.1:9876
producer:
group: my-producer-group
consumer:
group: my-consumer-group
第三步:生产者以及消费者
生产者:
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MessageProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
public void sendMessage(String topic, String message) {
rocketMQTemplate.convertAndSend(topic, message);
System.out.println("Message sent: " + message);
}
}
消费者:
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;
@Service
@RocketMQMessageListener(topic = "my-topic", consumerGroup = "my-consumer-group")
public class MessageConsumer implements RocketMQListener<String> {
@Override
public void onMessage(String message) {
System.out.println("Received message: " + message);
}
}
MQ是怎么保证消息不丢失的:
其实保证消息不丢失有两个原因:第一个就是刚刚说的Broker将生产者发送的消息持久化到磁盘中
第二个ACK确认机制(MQ的ACK以及消费者的ACK)
导致问题:
其实这个就是会导致一些问题就会导致消费者的重复的消费问题,那么这个就可能会使得客户在购买商品的时候会一个订单会扣两次款,这个就是一个非常严重的问题
解决方案:
也就是说消费者进行一个幂等的处理,幂等就是进行多次的行为所导致的结果其实最后的结果都是不变的这个就是一个幂等的概念: 1.进行分布式锁:只有一个客户端可以获得分布式锁 2.使用数据库的唯一的索引,这个对数据进行相关的 insert update操作的时候只有一个客户端可以进行修改
额外的知识:
1.事务型消息:
这个其实就是说就是保证最终一致性(就是说对于这个操作是不需要实时性),这个也就是说只要保证这个操作最后能够完成就行了:
账户服务进行扣款的时候其实就是说因为这个用户时无感的,所以我只要保证最终能够扣款成功就行了
实现原理(官网提供的):
2.顺序消息:
这个就是说保证我们发送消息以及消费消息的时候就是按照顺序进行的,在一些场景下必须是这样的,如:我们在发送订单的状态消息的时候,比如:订单有 未支付 支付中 已支付这三个状态,那么生产者将消息进行发送之后.消费者如果消费的消息为 已支付 未支付 支付中这个时候就会产生问题的,尤其在修改订单的状态的时候
实现原理:
这个本质上其实就是说我生产者只向一个队列中发送消息,然后消费者只消费这个队列中的消息,特别说明 :这个只能保证局部有序但是不能保证全局有序