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
相关推荐
邪恶的贝利亚14 分钟前
从红黑树到哈希表:原理对比与典型场景应用解析(分布式以及布隆过滤器)
数据结构·分布式·散列表
宝哥大数据3 小时前
面试题: Kafka能够高效且写入速度快的原因
分布式·kafka
胖头鱼的鱼缸(尹海文)3 小时前
数据库管理-第313期 分布式挑战单机,OceanBase单机版试玩(20250411)
数据库·分布式·oceanbase
Blossom.1183 小时前
KWDB创作者计划— KWDB技术范式革命:从数据存储到认知进化的架构跃迁
数据库·分布式·oracle·架构·自动化·kwdb·流式计算拓扑
lilye664 小时前
程序化广告行业(85/89):多行业广告投放资质全解析
kafka·memcache
老友@6 小时前
RabbitMQ 深度解析:从基础到高级应用的全面指南
运维·分布式·rabbitmq
早睡3357 小时前
spark-SOL简介
大数据·分布式·spark
企鹅不耐热.8 小时前
Spark-SQL
大数据·分布式·spark
风铃儿~9 小时前
Java微服务流量控制与保护技术全解析:负载均衡、线程隔离与三大限流算法
java·分布式·算法·微服务·负载均衡
菜就多练吧9 小时前
zk(Zookeeper)实现分布式锁
分布式·zookeeper·云原生