为什么使用消息队列?
异步处理
同样的时间可以做更多的事情,实现快速响应
系统解耦
比如订单和库存系统是高耦合,使用mq,订单系统写消息到mq,库存系统从mq拉取数据,从而实现解耦。
流量削峰
通过MQ接收大量的请求,在平滑地将消息发送给DB,达到解耦,缓解压力。跟“水库”一样。
如何保证消息队列的高可用?
kafka
由多个broker(kafka
实例)组成,每个broker是一个节点;创建一个topic(消息的主题),可以划分多个partition(topic分区),每个partition可以作用于不同的broker上,每个partition就放一部分数据,每个partition可以设置相应的副本来做高可用。
分区可以解决存储问题,副本解决高可用问题。
如何保证消息不被重复消费?或者说,如何保证消息消费的幂等性?
消费者幂等性
幂等性
依赖数据库的主键或唯一键
自己写一个去重表(日志表),当前操作的这个业务一定要和去重表在同一事务中
依赖redis去重
更新的时候,可以带版本更新
修改version字段
生产者幂等性:
生产者发送消息会携带pid和这条消息的序号,在paration存储消息,pid,序号。如果生产这没有收到broker的ack确认,重复发送,broker会检查对应的pid和序号是否存储。
如何保证消息的顺序性?
生产这写入消息到topic,kafka将根据不同的策略将数据分配到不同的分区中。
轮询分区策略
随机分区策略
按key分区分配策略
轮询,随机都会导致一个问题,生产到kafka的数据是乱序存储的。按key分区可以实现局部有序,但会造成数据倾斜,所以按照实际情况来取舍。
如何保证消息的可靠性传输?或者说,如何处理消息丢失的问题?
消费端弄丢数据:
你没有消费到这个消息,但kafka以为你消费好了,造成消息丢失。关闭自动提交offset,自己手动提交offset
kafka弄丢了数据:
kafka的某个broker宕机了,重新选举partition的leader,leader宕机了,重新选个follower称为leader,数据会少了一些。
要求每个partition至少由2个副本
在producer端设置acks=all。要求每条数据,必须是写入所有replica之后,才能认为是写成功了
producer端设置retries=max(很大值)。写入失败,就无限重试。
说一下kafka
的ack
机制
ack为0时,不等待broker确认,直接发送下一条数据,性能最高,但可能会存在数据丢失的情况。
ack为1时,等待leader副本确认接收后,才会发送下一条数据,性能中等
ack为-1或者all时,等待所有副本已经将数据同步后,才会发送下一条数据,性能最慢
kafka
如何实现单播和多播
单播
一条消息只能被某一个消费者消费的模式称为单播。要实现消息单播,只要让这些消费者属于同一个消费组即可。当生产者发送一条消息时,两个消费者中只有一个能搜到消息。
多播
让多个消费者分别属于不同的消费组就可以实现多播。
广播
每个消费者属于不同的消费组
kafka
体系结构
一个topic下有多个分区
一个分区有多个副本,但是只有一个leader,其他follow。读写在leader,follow是备份容灾。
消息积压
新建一个topic,可以有多个分区,可以启用多个consumer。把之前topic的consumer收到的消息不处理,直接发给新的topic。
评论区