MQ总结

MQ总结

MQ的作用

  • 削峰:顾名思义+允许异步
  • 解耦:要给多服务调接口,对接麻烦
  • 异步:要调多服务接口(超时)

Kafka高可用性

Kafka部署多个节点来支持高可用。每个主题有多个分区,分区下面又有一个leader副本和多个follow副本。
读写都在leader副本里,follow副本往leader副本同步数据。
kafka会将leader副本均匀分布在各个节点上,如果leader副本挂了,会在follow副本中选举一个新的leader副本。

Kafka重复消费

kafka保证每个分区的的消息是顺序的,并且会给消息一个offset。
默认消费端每隔一段时间会给kafka上报自己拉到最新的offset,那kafka重启之后就会在offset开始继续消费。
但是否要取消自动上报offset改为自己上报offset要看业务,如果每消费一条就上报一次,效率可能太低。
+ 生产一个唯一id,在消费的时候redis查一下消费过没
+ 数据库弄个唯一索引
+ 弄成重复消费也不要紧(幂等性)

Kafka丢数据与顺序性

  • 消费端弄丢了数据:消费端拉到了数据,然后就上报了offset,然而还没消费就挂掉了。
    最好保证幂等性,消费一批后才手动提交offset。
  • Kafka弄丢了数据:leader副本接收了数据,生产端收到了确认,还没follow副本pull,leader就挂了。
    修改配置,要求数据写入所有follow副本之后,才能认为是写成功了。
  • 保证消息的顺序性:每个需要顺序执行队列分到一个分区里,每个分区只用一个消费者消费

Kafka的消息语义

在消息投递与消费的常见语义有三种。而要完整实现某种语义,需要在生产端,Kafka端和消费端进行保证。

  • 至少一次:消息不会丢,但可能重复
  • 最多一次:消息可能会丢,但不会重复
  • 精确一次:消息即不丢也不重复

生产端

  • 至少一次:(默认)当网络问题导致没有收到提交确认,在旧版本生产端会进行重试
  • 最多一次:取消生产端的重试机制
  • 精确一次:在新版本的生产端,Kafka端会给每个生产端一个ID,并且通过消息ID进行去除。即便重复提交消息也只会有一条消息。

Kafka端

  • 至少一次:不晓得
  • 最多一次:生产端不等待确认消息或者只等待主副本确认消息
  • 精确一次:生产端等待主副本和全部从副本确认消息

消费端

  • 至少一次:先处理消息,再提交偏移量
  • 最多一次:先提交偏移量,再处理消息
  • 精确一次:
    • 处理结果与偏移量通过事务一起存储
      • 在数据库里利用事务
      • 在kafka里,偏移量是保存在一个主题里的,kafka支持往不同主题提交消息作为一个事务
    • 不一起存储则需要用分布式事务

kafka的事务的隔离级别有两种,读未提交和读已提交,可以分别用在最多一次和至少一次上。

消费积压

  1. 修复消费慢问题
  2. 建一个新的主题,分区是原来十倍
  3. 用个临时程序把积压的数据搬到新主题里
  4. 起十倍消费者消费新主题数据
  5. 恢复原来结构

SQS

SQS没有分区的概念,提供两种队列,标准队列和先进先出队列。
标准队列提供无上限的吞吐,但是不保证(但基本上)顺序。
先进先出队列保证顺序,但吞吐限三千。
SQS对消息提供了一个可见性超时,当客户端拉取消息后,在这段时间内客户端无法拉取此消息,超时后客户端可以重新拉取此消息。
所以客户端消费完消息后需要向SQS提交删除消息。如果时间短了可能导致重复消费,时间长了需要更长时间才能重新消费失败信息。

SQS源码

  • 链接工厂->链接->会话->队列->消费者->处理回调
  • 消费者->newSingleThreadExecutor->消息拉取->
    消息+处理回调=封装成一个对象,放在回调队列里->
  • 会话->newSingleThreadExecutor->回调队列

参考文章:

Kafka中的消息传递保证语义

Kafka 消息语义


MQ总结
https://cellargalaxy.github.io/posts/中间件/7.MQ总结/
作者
cellargalaxy
发布于
2020年6月1日
许可协议