Kafka Consumer
Push VS Pull
An initial question we considered is whether consumers should pull data from brokers or brokers should push data to the consumer. In this respect Kafka follows a more traditional design, shared by most messaging systems, where data is pushed to the broker from the producer and pulled from the broker by the consumer.
Kafka遵循传统设计,也是被大多数消息系统所采用的,即,producer push数据到broker,consumer从broker那里pull数据。
A push-based system has difficulty dealing with diverse consumers as the broker controls the rate at which data is transferred. The goal is generally for the consumer to be able to consume at the maximum possible rate; unfortunately, in a push system this means the consumer tends to be overwhelmed when its rate of consumption falls below the rate of production.
基于push的系统在面对不同的消费者的时候需要控制数据传输的速率这是很困难的,一般消费者都是以最大速率去消费的,不幸的是这对于push系统来说意味着当消费的速率低于生产的速率时消费者有崩溃的倾向。而基于pull的系统就有很好的属性,消费者可以简单的落后,并且在可能的时候迎头赶上。在消费者感觉快要崩溃的时候可以缓和一下,获取传输速率完全靠消费者机灵。
基于pull的系统的另一个优势在于broker可以将自己的数据批量的发送给消费者。而基于push的系统必须选择是立即发送请求还是累积更多的数据再发请求,而且发送以后它不知道消费者是否能很快的处理它。基于pull的系统就能够很好的解决这个问题,因为消费者总是拉取在当前日志的位置之后的所有可用的消息。
基于pull的系统有一个缺陷就是如果broker没有数据,消费者会一直循环等待,有效的繁忙的等待直到有数据到达。为了避免这个问题, 我们可以让消费者在请求的时候以“长轮询”的形式阻塞,直到有数据到达。
Consumer Position
大部分的消息系统在broker中维护关于消息是否已经被消费的元数据。因此,一个消息被分发给消费者以后broker可以理解处理或者等到消费者确认。
或许你还没有意识到让broker和consumer就消息是否已经被消息达成一致是一个很重要的问题。如果每次消息被分发出去以后broker就立即将这条消息标记为consumed,这个时候如果消费者处理消息失败了(可能是因为它宕机了或者请求超时了或者其它的原因),那么这条消息就丢失了。为了解决这个问题,许多消息系统增加一个确认特性,这就意味着在消息被发送以后只能将它们标记为sent而不是consumed,broker会等待来自消费者的确认,之后才会将这条消息标记为consumed。这个策略虽然解决了丢失消息的问题,但是又带来了新的问题。首先,如果消费者已经处理完消息,但是在它发送确认之前它失败了,那么这种情况下会导致消息被消费两次。第二个问题跟性能有关,现在broker对于每条消息必须维护多个状态(首先锁定它以至于它不会被分发第二次,然后永久的标记它为consumed以至于它肯能会被删除)。棘手的问题必须被处理,比如消息发送后没有确认。
Kafka handles this differently. Our topic is divided into a set of totally ordered partitions, each of which is consumed by exactly one consumer within each subscribing consumer group at any given time. This means that the position of a consumer in each partition is just a single integer, the offset of the next message to consume. This makes the state about what has been consumed very small, just one number for each partition. This state can be periodically checkpointed. This makes the equivalent of message acknowledgements very cheap.
Kafka对这些问题的处理不同,主题被划分为一系列有序的分区,在任意时刻,一个分区只能被订阅这个主题的每个消费者组中的一个消费者消费。这就意味着,消费者的位置在每个分区中仅仅是一个整数,这个整数就是即将要消费的下一个消息的offset(偏移量)。这使得标记关于消息是否已经被消费的状态变得很简单,每个分区仅仅一个数。这个状态可以周期性的被检查。这跟消息确认是等价的,而且也是非常廉价的。
消费者可以故意倒回到一个旧的offset去重新消费数据。当然,这一点违反了队列的公共契约,但事实上这是许多消费者的一个基本特性。例如,如果消费者的代码有bug,并且在一些消息被消费以后才发现,那么消费者可以重新消费这些消息以修复这个bug。
参考 http://kafka.apache.org/documentation/#design
Kafka Consumer的更多相关文章
- 【原创】Kafka Consumer多线程实例
Kafka 0.9版本开始推出了Java版本的consumer,优化了coordinator的设计以及摆脱了对zookeeper的依赖.社区最近也在探讨正式用这套consumer API替换Scala ...
- Kafka设计解析(四)- Kafka Consumer设计解析
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/08/09/KafkaColumn4 摘要 本文主要介绍了Kafka High Level Con ...
- 【原创】kafka consumer源代码分析
顾名思义,就是kafka的consumer api包. 一.ConsumerConfig.scala Kafka consumer的配置类,除了一些默认值常量及验证参数的方法之外,就是consumer ...
- Understanding Kafka Consumer Groups and Consumer Lag
In this post, we will dive into the consumer side of this application ecosystem, which means looking ...
- Kafka consumer处理大消息数据问题
案例分析 处理kafka consumer的程序的时候,发现如下错误: ERROR [2016-07-22 07:16:02,466] com.flow.kafka.consumer.main.Kaf ...
- 【原创】Kafka Consumer多线程实例续篇
在上一篇<Kafka Consumer多线程实例>中我们讨论了KafkaConsumer多线程的两种写法:多KafkaConsumer多线程以及单KafkaConsumer多线程.在第二种 ...
- 读Kafka Consumer源码
最近一直在关注阿里的一个开源项目:OpenMessaging OpenMessaging, which includes the establishment of industry guideline ...
- kafka consumer 配置详解
1.Consumer Group 与 topic 订阅 每个Consumer 进程都会划归到一个逻辑的Consumer Group中,逻辑的订阅者是Consumer Group.所以一条message ...
- kafka consumer 0.8.2.1示例代码
package test_kafka; import java.util.ArrayList; import java.util.HashMap; import java.util.List; imp ...
- Kafka consumer group位移0ffset重设
本文阐述如何使用Kafka自带的kafka-consumer-groups.sh脚本随意设置消费者组(consumer group)的位移.需要特别强调的是, 这是0.11.0.0版本提供的新功能且只 ...
随机推荐
- Codeforces 626F Group Projects(滚动数组+差分dp)
F. Group Projects time limit per test:2 seconds memory limit per test:256 megabytes input:standard i ...
- LCS最长公共子序列~dp学习~4
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1513 Palindrome Time Limit: 4000/2000 MS (Java/Others ...
- 将数据按照gzip当时解压的工具类
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; impo ...
- 微信小程序实现滚动加载更多
1.需要用到的组件和api scroll-view(可滚动视图区域) wx.showToast(OBJECT)显示消息提示窗----显示loading小菊花用的 2.需要用到的属性 3.scrol-v ...
- 自定义省市选择器 微信小程序多列选择器
由于微信小程序的选择器为省市区选择器共3列 如我仅需要省市2列的选择器 就需要我们另寻他法找来找去没有合适的 只能自己写了 1. 首先我们把所需要的省数据 市县数据放在一个 p_c.js 文件里面,使 ...
- 使用Git将本地项目或代码上传到GitHub上
1.要托管到github,那你就应该要有一个属于你自己的github帐号,所以你应该先到github.com注册.打开浏览器在地址栏输入地址:github.com 填写用户名.邮箱.密码,点击Sign ...
- 【django基础补充之URL,视图,模版】
一.url路由配置 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个URL调用这段代 ...
- Linux终端连接Linux服务器
我们经常需要通过类UNIX下连接我们的Linux服务器.比如我的Mac下经常需要连接上Linux服务器.一般系统都提供了ssh支持,可以直接连接: 通过命令: ssh root@120.25.12.9 ...
- ::在c++中什么意思
(1)表示“域操作符” 例:声明了一个类A,类A里声明了一个成员函数void f(),但没有在类的声明里给出f的定义,那么在类外定义f时, 就要写成void A::f(),表示这个f()函数是类A的成 ...
- Hadoop问题:启动hadoop 2.6遇到的datanode启动不了
问题描述:第一次启动输入jps都有,第二次没有datanode 日志如下: 查看日志如下: -- ::, INFO org.mortbay.log: Started HttpServer2$Selec ...