kafka 生产者消费者设计思考

生产者

负载均衡

生产者直接发送消息给分区leader,而不需要通过中间者进行转发。

这意味着生产者需要知道哪些服务器是存活的,以及主题分区leader在哪里的元数据请求。同时这也意味着生产者可以根据情况决定发给哪个broker,那么既可以随机负载,也可以进行散列

批量发送

生产者会尝试收集数据,然后在单次请求中发送大量数据,以牺牲少量额外延迟来换取更好的吞吐量。

消费者

push or pull?

kafka选择了pull。这是因为基于push的系统由broker控制着数据传输的速率,尽可能使消费者更快消费,但是如果消费者消费速度远低于生产速度,那这就成为一种拒绝服务攻击了。而消费者pull则能很好根据实际情况去pull消费,消费快就快pull,消费慢就慢pull

不过pull也会陷入轮询的陷阱。为了解决这种问题,kafka在pull request中设置参数使允许堵塞在长轮询中,直到数据到达

消费到哪里了?

确定消费到哪里了,并不是一个简单的问题。如果broker在发送消息后,立刻认为消息已经被消费了,那么在传输未到达等原因引发的消费未处理情况会使得这样的认为并不正确

如果采用消费者ack的模式,也就是消费者消费完成之后发送确定消息,那么如果消费者在发送ack的时候也失败了,这就会导致重复消费问题。此外,对每个消息进行状态维护也会对性能造成影响

为了避免这些问题,kafka将消息划分到有序的分区中,那么只要记录每个分区被每个消费者组消费数据即可。并且还可以支持回退到之前被消费的消息,以允许重复消费

那么kafka是如何解决重复消费的问题的呢?很可惜,kafka最多只能支撑生产者不发送重复的消息,如果是上述场景中消费者没有ack成功导致的重复消费,还是要进行额外幂等处理的

消息传递机制

  • 至多一次:消息可能会丢失,并永远不会重新传递
  • 至少一次:消息不会丢失,但可能被重新传递
  • 只有一次:每个消息仅传递一次,既不会丢失,也不会重复

kafka支持生产者若没有收到ack,能重新发送消息,这样能保证至少一次的传递机制。并且还添加了(0.11.0.0之后)幂等,也就保证重发不会出现重复条目。

此外还提供了一个"事务",也就是支持发送消息到多个topic partitions的能力,要么都写入成功,要么都不成功

实现幂等的方法是为每个生产者分配id,并采用生产者发送的序列号去去重

从消费者角度来说,当消费者控制消息处理位置

  • 读取消息后,更新已处理,最后处理消息。

    这保证了至多一次。但如果消费者在消费失败后,反馈消费失败之前宕机,那么就会导致存在消息没有被消费

  • 读取消息后,处理消息,最后更新已处理。

    保证了至少一次。如果在消费成功之后宕机,那么将会重复收到已经处理过的消息

为了达成只有一次的情况,我们可以利用kafka事务功能,在事务被中止之后将消费者处理位置恢复到之前

Ref

  1. https://kafka.apache.org/documentation/#theproducer
相关推荐
ShareBeHappy_Qin5 分钟前
ZooKeeper 中的 ZAB 一致性协议与 Zookeeper 设计目的、使用场景、相关概念(数据模型、myid、事务 ID、版本、监听器、ACL、角色)
分布式·zookeeper·云原生
黄名富9 小时前
Kafka 日志存储 — 日志索引
java·分布式·微服务·kafka
DM很小众9 小时前
Kafka 和 MQ 的区别
分布式·kafka
sjsjsbbsbsn10 小时前
基于注解实现去重表消息防止重复消费
java·spring boot·分布式·spring cloud·java-rocketmq·java-rabbitmq
重生之Java再爱我一次11 小时前
Hadoop集群搭建
大数据·hadoop·分布式
中东大鹅12 小时前
MongoDB的索引与聚合
数据库·hadoop·分布式·mongodb
狮歌~资深攻城狮14 小时前
TiDB出现后,大数据技术的未来方向
数据库·数据仓库·分布式·数据分析·tidb
狮歌~资深攻城狮14 小时前
TiDB 和信创:如何推动国产化数据库的发展?
数据库·数据仓库·分布式·数据分析·tidb
明达技术15 小时前
分布式 IO 模块与伺服电机:拉丝机高效生产的 “黄金搭档”
分布式
weisian15117 小时前
消息队列篇--原理篇--Pulsar(Namespace,BookKeeper,类似Kafka甚至更好的消息队列)
分布式·kafka