美文网首页
关于消息

关于消息

作者: kar_joe | 来源:发表于2020-01-11 19:40 被阅读0次

生产者根据消息key以及“路由策略”将消息发往对应topic分区,消息数据在broker服务端按照指定备份策略“持久化”保存起来,消费者不断从服务端拉取消息消费,并提交“消费位移”,整个过程需要关注消息的“重复消费”以及“丢失”问题。

路由策略

hash、轮询or自己实现
Java客户端默认的生产者路由策略的实现类org.apache.kafka.clients.producer.internals.DefaultPartitioner。默认策略为:如果指定了partition就直接发送到该分区;如果没有指定分区但是指定了key,就按照key的hash值选择分区;如果partition和key都没有指定就使用轮询策略。而且如果key不为null,那么计算得到的分区号会是所有分区中的任意一个;如果key为null并且有可用分区时,那么计算得到的分区号仅为可用分区中的任意一个。
注意kafka只保证分区层面的消息有序性,topic层面并不保证。

消息持久化

Kafka 只对“已提交”的消息(committed message)做“有限度”的持久化保证。
Topic分区Partion,每个分区又有多个副本Repication,消息在broker中持久化到日志文件,多个follower副本异步从leader副本中同步消息。
如何持久化:每一个topic的分区对应一个目录,该分区的消息追加写到该目录下日志文件,用户可以分配日志保留策略和切割策略。由于采用了顺序写,也就是WAL技术(类似mysql里redolog的使用),性能较高。

消费位移提交

每个消息在服务端对应一个位移Offset,服务端利用位移查找消息。另外消费者需要将自己消费位移在合适时机提交,下次消费时从上次消费位移之后继续消费,即使有宕机。
老版本位移提交依赖于zk,由于zk其实不适合频繁写入,所以新版本kafka,把位移管理重新实现;消费者将消费位移信息写入特殊topic :__consumer_offsets。位移主题的 Key 中保存 3 部分内容::<Group ID,主题名,分区号 >

  • 自动提交
    消费者poll时提交上一次的位移,另外也有后台线程每隔xx时间(auto.commit.interval.ms)提交一次位移,保证最小的提交间隔。
  • 手动提交(同步提交、异步提交)
    注意关注CommitFailedException异常
  • 细粒度提交
    commitSync(Map<TopicPartition, OffsetAndMetadata>)

消息丢失

  1. 生产者异步发送,消息还没发出时就挂掉
    需要关注异常回调
  2. 消息poll后就先提交位移,消息的处理过程中消费者挂掉
    消息处理完成才提交位移(也会引入重复消费)
  3. unclean配置为true,让落后的broker成为leader,丢失消息
    在可用性与数据一致性之间做出抉择,若不允许数据丢失,则unclean配置置为false。
    另外在生产端以及broker服务端合理配置,设置ack=all,并保证replication.factor > min.insync.replicas>1,保证数据一直冗余备份
  4. 老版本broker分区之间数据同步机制导致
    社区在 0.11 版本正式引入了 Leader Epoch 概念,来规避因高水位更新错配导致的各种不一致问题。

消息重复消费

  1. 网络问题导致生产端未收到broker回复的ack,引起重发
  2. 消费者消费过程中挂掉,未提交消费位移,导致重复消费
  3. 消费reblance,一个正在消费信息时reblance,消息被另一个消费者又消费
    可以采用幂等性producer,并且在消费端业务处理逻辑上也支持幂等性

消息交付可靠性保障

消息交付有三种语义:

  1. 最多一次
  2. 至少一次
  3. 精准一次
    kafka默认是至少一次语义,想要实现精准一次,需要保证幂等性。幂等性就是任意多次执行所产生的影响均与一次执行的影响相同。
    kafka提供了幂等性producer以及事务性producer。幂等性producer底层保证了消息去重,但是其只保证了单分区,单会话上的幂等性。kafka用事务性producer解决上述局限,Kafka 自 0.11 版本开始提供了对事务的支持,目前主要是在 read committed 隔离级别上做事情。它能保证多条消息原子性地写入到目标分区,同时也能保证 Consumer 只能看到事务成功提交的消息。
producer.initTransactions();
try {
            producer.beginTransaction();
            producer.send(record1);
            producer.send(record2);
            producer.commitTransaction();
} catch (KafkaException e) {
            producer.abortTransaction();
}

另外即使kafka保证了消息唯一性,在极端情况下消费端也还会有重复消费问题,消费代码逻辑也需要保证幂等性。
另外补充一点,RocketMQ也实现了事务,但是其事务更倾向于保证本地其他操作与发送消息操作之间原子性。kafka的事务更倾向于保证多条消息原子性地写入到目标分区。

需要注意的细节

  • 生产者批量发送、消费者批量拉取
    提升吞吐量,降低网络损耗,但是提高了延时

  • 压缩
    时间换空间,cpu换io;同样提升吞吐量,降低网络损耗,但是提高了延时
    尽量避免生产端与消费端采用不同压缩算法,这样会造成broker端解压再重新压缩
    正常情况下,broker只解压对消息做简单校验。

  • broker端对采用零拷贝技术(从PageCache到socket缓冲区)
    提升broker端处理效率,提升吞吐量、降低延时。
    尽量保证生产者、消费者、broker服务端版本一致,防止零拷贝技术失效。

相关文章

  • 关于消息

    生产者根据消息key以及“路由策略”将消息发往对应topic分区,消息数据在broker服务端按照指定备份策略“持...

  • 关于QQ消息

    不想再对他这么执着了,那并不代表什么,对于一个数字,不用去看,记在心里就好了。不想再为这个事情烦恼,必须要去成长,...

  • 关于消息队列

    关于消息队列

  • 关于的消息

    二月的最后一天! 纪念一下! 时间是检验真理的唯一标准! 漆黑的夜,晚安! …

  • 关于iOS消息转发

    今天去YY面试,问起了消息转发,竟然一时答不出来。现在把iOS消息转发的流程过一遍。首先我们要知道消息转发都有哪些...

  • 关于秒回消息

    一直以来都认为,秒回一个人并不是说要把他放在什么重要的位置,或者是怎样重要的人,只是觉得,秒回是一种最基本的礼貌。...

  • 关于Slack消息模式

  • 关于消息队列(笔记)

    分享一个高手的解释,化抽象为具体,化繁为简,牛逼牛逼[消息队列的使用场景是怎样的? - 祁达方的回答 - 知乎](...

  • 关于币圈消息

    消息很多,有营养的没有几个,除非是有真正意义的不可控制的重大利好或利空,所谓的消息都是用来配合收割的,币圈媒体鸡贼...

  • 关于RocketMQ顺序消息

    RocketMQ是一款 分布式、队列模型的消息中间件,由阿里巴巴团队研发,借鉴参考了JMS规范的MQ实现,更参考了...

网友评论

      本文标题:关于消息

      本文链接:https://www.haomeiwen.com/subject/fzdbactx.html