六个核心角色
product 生产者(数据提供者)
topic 消息类别(每条由product发布到kafka的消息都有一个topic,不同的topic消息分开储存)
partition 分区 物理概念(每个topic都至少有一个或很多个partition)
broker 服务器(kafka集群的一个节点)
consumer group 消费者组别
consumer 消费者
角色理解
topic&partition
可以吧topic理解陈一个先进先出的传送带(queue队列),你需要在发布消息到卡夫卡的时候确定你需要吧你的消息发布的哪个队列中
partition是为了提高卡夫卡的吞吐率,每个topic都会有若干个portion,每个partition 代表着一个物理环境下的文件夹,文件夹里面储存着改partition的所有消息和对应的索引
product
消息生产者吧消息push到卡夫卡的时候,会根据制定好的partition规则吧消息存储到对应的partition 中,这样就实现了负载均衡,同时也提高了IO性能
consumer group
消费者小组要和消息的消费方式结合理解:
同一个topic的同一条消息只能被同一个consumer group 的一个consumer消费
多个consumer group 能够同是消费同一条消息
这样就可以实现一个广播模式或者独播模式
独播: 把所有的consumer放入到同一个consumer group里面,那me该条消息只能被一个consumer消费
广播: 把每一个consumer都建立一个独立的consumer group,那么所有的consumer都可以消费到这条消息
交易保证(消息传输和接收方案)
方案
At most once 消息可能会丢,但绝不会重复传输
At least one 消息绝不会丢,但可能会重复传输
Exactly once 每条消息肯定会被传输一次且仅传输一次,很多时候这是用户所想要的。
上游(product->broker)
当Producer向broker发送消息时,一旦这条消息被commit,因数replication的存在,它就不会丢。但是如果Producer发送数据给broker后,遇到网络问题而造成通信中断,那Producer就无法判断该条消息是否已经commit。虽然Kafka无法确定网络故障期间发生了什么,但是Producer可以生成一种类似于主键的东西,发生故障时幂等性的重试多次,这样就做到了Exactly once。截止到目前(Kafka 0.8.2版本,2015-03-04),这一Feature还并未实现,有希望在Kafka未来的版本中实现。(所以目前默认情况下一条消息从Producer到broker是确保了At least once,可通过设置Producer异步发送实现At most once)。
下游(broker->consumer)
consumer读取到broker的消息的时候可以有两种选择
直接commit,通知卡夫卡处理完成,然后继续业务逻辑,这样的好处是不会多次传输,但是数据会丢失,因为有可能在逻辑处理的时候出现crash,那么这条消息就会miss
处理完业务逻辑后再commit,这样数据不会丢失,但是有可能会出现多次重复,因为,如果在业务处理完成,commit之前出现crash,那么下一次去读取的时候还是会去读取该条消息,再次消费,就会出现重复消费的情况
如果一定要做到Exactly once,就需要协调offset和实际操作的输出。精典的做法是引入两阶段提交。如果能让offset和操作输入存在同一个地方,会更简洁和通用。这种方式可能更好,因为许多输出系统可能不支持两阶段提交。比如,Consumer拿到数据后可能把数据放到HDFS,如果把最新的offset和数据本身一起写到HDFS,那就可以保证数据的输出和offset的更新要么都完成,要么都不完成,间接实现Exactly once。(目前就high level API而言,offset是存于Zookeeper中的,无法存于HDFS(分布式文件系统),而low level API的offset是由自己去维护的,可以将之存于HDFS中)
消息地址问题
发布消息和消费消息都需要知道消息需要放到哪里,需要知道消息在哪
发布消息的时候,需要把消息放入到partition中,这个partition有一个地址参数offset(set->不可重复)
卡夫卡的消息无论是否已经消费,是不会进行删除的
consumer消费消息是根据offset去消费的,理论是每次消费过后都会递增该consumer持有的offset,也就是可以消费下一条消息
故此我们可以把consumer持有的offset值改小来再次消费某些消息,如果你需要的话