kafka是一个高性能,高可靠性的消息系统,具体来说:

  • kakfa维护了不同topics的消息流
  • 支持对消息流的发布/订阅
  • 通过多服务器备份进行FT
  • 高效I/O,batch和compression
  • 对消费者和生产者解耦

另外,kafka还提供了消息存储的功能,一定程度上可以当一个分布式存储系统用,它将数据存储在disk上

kafka架构

kafka_core

Kafka主要组成部分:

  • Broker:kafka集群的服务器,类似于node的概念,一个broker上可以有多个topics
  • Topic:每条发布到kafka的消息都有一个类别,这个类别就是topic
  • Commit Log:由message,offset等组成
  • Producer:生产者,向broker发消息
  • Consumer:消费者,从broker取消息
  • offset:在partition中的每条信息都会被分配一个唯一的顺序id叫做offset,consumer会track这个offset
  • Partitions:topics在物理上的分组,每个topic可能分成多个partition,每个partition都是有序的队列,kafka只保证一个partition的顺序,而不能保证partition间的顺序,具体消息会到哪个partition,由hash算法或者round robin决定
  • Zookeeper:用来存储和维护集群配置信息,选举算法和集群切换;在0.8以前还支持追踪offset,后面被取代

kafka_cluster

在这个图中只有一个topic:zerg.hydra,它包括三个partition,分别是P0,P1,P2,每个partition在不同broker上又有replication,这里每个partition有3个replica,但其中只有一个是leader(图中边框加粗),对这个partition所有的读写只能走leader,针对每个partition的读写都可以并发进行。

Kafka特性

保证:

  • kafka保证了每个topic的partition的内容会按照其发送的顺序增加
  • consumer看到信息的顺序和其存储在log中的顺序相同
  • 如果想保证全局顺序,有两种方案:只使用一个parttion;在consumer应用中增加全局顺序的处理(例如在storm的topology中)

消息传递:

At Least Once(default):消息不会丢失但可能被多次递送,为了做到这个,需要满足:

  • 在发送信息的时候保证信息的持久性
  • 在读取信息时保证持久性
  • produce发送但没收到ack时->检查最近的commit值
  • consumer要保存offset

消息传递的方式:

  • 消息广播:把消息发送给所有consumer
  • 订阅发布:消息发送个单个consumer

通过consumer group的方式实现

consumer_group

对于订阅发布,每个consumer对应一个独立的consumer group即可,而对于广播,则可以把所有的consumer放在一个consumer group里。不论每个group里有多少个consumer thread(小于等于partitions),对应多个partition,这个consumer thread总会消费全部的partition。因此,最好的设计便是consumer group下的thread与partition数量相等,这样效率最高。

发送信息:

  • 可以选择同步/异步,同步在发送时会进入阻塞,异步可以实现高吞吐率
  • 异步时将信息batching化
  • 当queue满之后异步producer可能造成消息的丢失

发现leader:

  • producers:不与zookeeper直接接触,而是通过bootstraping的方式,让boostrap server(broker)通知producer有哪些存活的broker以及如何找到对应的partition leader。而boostrap broker是通过zk来知道的。

Rebalancing:

每个topic的partition对应的conusmer是在运行时动态分配的,这个过程会造成rebalancing(因为机器会坏或者consumer会因为一些原因挂掉)会发生rebalance的情况包括:

  • consumer加入或离开consumer group(例:通过createMessageStreams()为topic注册consumer)
  • broker加入或离开(例:当broker无法发送heartbeat给zookeeper)
  • topic由于filter而造成的 ”加入/离开“

为什么kafka那么快?

  • Zero Copy的使用:即使用sendfile()系统调用代替了传统I/O中的read()和write(),使数据由MDA从磁盘直接读取到内核buffer中,然后从内核buffer直接复制到socket buffer(而不用从kernel buffer->application buffer->socket buffer),减少了其中的copy和上下文切换
  • I/O过程中batch化数据
  • 串行硬盘写入
  • 大量依赖linux PageCache(页缓存):自动使用机器上的所有可用内存
  • 可扩展性强

注意:

每次启动kafka前需要先启动zookeeper,kafka和zookeeper都需要在每台机子上都运行start程序(不同于hdfs)