消息队列(1)
序言
1.为什么要用消息队列?
消息队列的常见使用场景吧,其实场景有很多,但是比较核心的有3个:解耦、异步、削峰。
2.kafka、activemq、rabbitmq、rocketmq都有什么优点和缺点啊?
3.怎么保证消息队列的高可用?
4.如何保证消息的顺序性?
5.怎么保证消息不被重复消费?
上面在解决消息顺序问题时,引入了一个新的问题,就是消息重复。那么MQ是怎样解决消息重复的问题呢?还是“恰好”不解决。
造成消息的重复的根本原因是:网络不可达。只要通过网络交换数据,就无法避免这个问题。所以解决这个问题的办法就是不解决,转而绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?
1).消费端处理消息的业务逻辑保持幂等性
2).保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现
第1条很好理解,只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。第2条原理就是利用一张日志表来记录已经处理成功的消息的ID,如果新到的消息ID已经在日志表中,那么就不再处理这条消息。
我们可以看到第1条的解决方式,很明显应该在消费端实现,不属于消息系统要实现的功能。第2条可以消息系统实现,也可以业务端实现。正常情况下出现重复消息的概率不一定大,且由消息系统实现的话,肯定会对消息系统的吞吐量和高可用有影响,所以最好还是由业务端自己处理消息重复的问题,这也是MQ不解决消息重复的问题的原因。
MQ不保证消息不重复,如果你的业务需要保证严格的不重复消息,需要你自己在业务端去重。
6.如何保证消费的时候是幂等的?
其实还是得结合业务来思考,我这里给几个思路:
比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了,update 一下好吧。
比如你是写 Redis,那没问题了,反正每次都是 set,天然幂等性。
比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据的时候,里面加一个全局唯一的 id,类似订单 id 之类的东西,然后你这里消费到了之后,先根据这个 id 去比如 Redis 里查一下,之前消费过吗?如果没有消费过,你就处理,然后这个 id 写 Redis。如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。
比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。
当然,如何保证 MQ 的消费是幂等性的,需要结合具体的业务来看。
7.如何保证消息的可靠性传输?要是消息丢了怎么办?
生产者没有成功把消息发送到MQ
RabbitMQ接收到消息之后丢失了消息
8.如何解决消息队列积压几百万消息的问题?
9.如何设计消息队列?说下架构思路?