RabbitMQ常见的5中工作模式
简单工作模式:
再发送消息的时候不用指定交换机,直接发送给queue就可以(虽然我们没有指定但它是有一个默认的交换机)
工作队列模式:
我们也不指定交换机,它也有默认的。他和简单工作模式的区别在于多了一个消费者,但他只能有一个消费者拿到生产者的消息
订阅模型分类/分裂模式:
当交换机绑定了queue之后,消费者去对接queue,生产者生产的消息就能被多个绑定的消费者拿到
路由模式:
除了要绑定queue和交换机的关系外还要绑定交换机和rottingKey的关系,在生产者发送消息时除了带上交换机以外还要带上rottingKey,rabbitmq就知道自动去匹配outtingKey,把消息转换到对应的queue上
通配符模式:
比路由模式更加灵活的一种方式
MQ的好处
异步、流量削峰、解耦
消息丢失
RabbitMQ消息丢失分成三个方向
1mq:
消息到达了mq之后,消费者也没来得及拉取数据,mq就挂了,由于mq是将这个消息保存到内存中,内存中的没了消息就丢了。可以把mq改成持久化
2消费者端:
默认是ack自动应答,只要这个消息一旦到达了消费者后,消费者机会立即给mq响应一个ack,此时mq会删除这条消息,但是有可能这个消费者在消费这个消息的过程中有消费失败的结果,但由于消费者是自动应答导致这个消息已经被mq删除了,所以就丢了。可以改成ack手动应答,当消费者消费消息成功后才响应ack
3生产者端:
确认机制,基于回调来完成,在发送消息之后有两个回调方法,来标识消费者是否到达了mq端
Kafka
消息丢失的原因:
生产者向leader写了数据,leader还没来得及就把这个消息同步给follower,此时消费者也没去leader中拉取数据然后leader挂掉了,zookeeper就会让follower去进行leader选举,但是这些follower无论谁成为了leader,他们里面都没有丢失的那条消息,就造成了消息丢失
解决方案:
配置acks = all 表示只有当所有节点都接受到数据之后才会给生产者响应成功
配置retries = MAX 写成一个很大的数
保证当前的leader至少有一个follower
消息重复消费
kafka
生产者生产消息会产生offset,递增的整数。这个整数用来记录当前发送到第多少个消息,他们正常的流程消费者在消费完消息后,基于offset的自动提交机制会把他消费到的offset提交到zookeeper,zookeeper会通知kafka拿到消费者的消费情况,如果此时消费者挂了之后kafka会基于他手上的offset再发送下一条消息,但因为是自动提交有可能在他触发向zookeeper提交前就挂了,此时kafka就不知道消费者的准确消费信息,于是就把消费者消费过的数据再发给消费者,此时就消息重复消费了
解决:
改成手动提交offset
加上setnx以防offset由于网络抖动掉了
RabbitMQ
相应的这个ack恰好被丢弃了,可这个消息明明被消费过了,但mq里面还有消息,mq就会自动的重试