Kafka是由Linkedin公司开发的一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据。
kafka具有众多良好的特性:
- 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒
- 可扩展性: kafka集群支持热扩展
- 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
- 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)
- 高并发:支持数千个客户端同时读写
那么Kafka为什么如此一枝独秀?
系统架构
Kafka如此优良的特性来源于它良好的架构设计:
在上图中:
- Producer:消息的生产者;
- Kafka Cluster:运行Kafka实例的集群;
- Broker:一个kafka实例,可认为就是一台服务器;
- Topic:消息的分类主题;
- Partition:消息的分区,是指同一个topic的消息被分成了多个部分,减小了单独brokr的压力,实现负载均衡,不同分区的数据是不同的;(注:分区的好处除了负载均衡,还有就是便于水平扩展)
- Follower、Leader:前者是备份,后者是主体,只有当主体出现故障时,才会选择一个备份(replica)作为新的主体;(注:主体和备份必定不在同一个实例上)
- Consumer (Group):消息的消费者,多个消费者组成一个Group,kafka规定同一个Topic的消息只能被同一个消费者组的消费者消费;(提高吞吐量!)
- Zookeeper:保存集群的信息,保证分布式系统的可用性;
工作流程
发送数据的流程如下:
从上图可知有几点需要注意:
- 信息是往Leader传输的;
- follower是主动pull消息的;
- 只有follower完成了backup,才算是一次正常的消息发送;(保证消息不会丢失)
有一个问题,消息发送到哪一个partition呢?
- 如果消息中指定了Partition id,那就发送到对应的partition;
- 如果没有,那就消息的key进行hash一下;
- 如果id和key都没有,那就随机;
另外,kafka备份策略的的可以配置的,ACK可以配置为:0、1、all。
- 0表示不需要ACK,安全性低效率高;
- 1表示需要一个ACK才会继续下一条;(一个follower接收就可以)
- all表示所有的follower都完成才会继续下一条,效率最低;
**保存数据时,**kafka预先在磁盘开辟一块空间,而后顺序写入数据(比随机快多了),上文说topic是以partition的形式分布于集群中的,而partition表现为一个一个的文件夹,其中包含了多个segment文件夹,而segment下包含.index .log .timeindex文件(后者为新增的版本特性)。
其中,index和timeindex为索引文件,log为实际存储message的文件。注意到每一个文件前都有一串序号,这就是kafka提高查找效率的方式——分段+索引。
log文件存储了message的三个重要属性:offset、消息大小、真正的消息数据。
那么消费者是如何读取到特定的消息的呢?
需要注意的是:(怎么通知的?)
- 消费者拉取数据时,也是从leader拉;
- 多个partition可以被一个consumer消费,但是反之不行;
在读取消息时,需要通过offset从partiton中读取到相应的消息体,例如查找offset为368801的message,具体的过程详见:Kafka基本原理。
这套机制是建立在offset为有序的基础上,利用segment+有序offset+稀疏索引+二分查找+顺序查找等多种手段来高效的查找数据!那么消费者如何知道自己消费了多少?以前,是放在zookeeper中,但可能造成重复消费,现在是存放在kafka集群的__consumer_offsets这个专有topic中。
有一篇讲解kafkapartition和consumer之间的关系:stackflow
通信模式
目前流行的消息队列的通信模式主要有两种:点对点模式、发布订阅模式。
- 点对点模式
该模型的特点是发送到队列的消息被一个且只有一个消费者进行处理。消息进入消息队列后,由消费者主动去拉取或轮询进而获得消息,这个模型的优点就在于由消费者来控制拉取消息的频率,缺点是需要额外的线程去监控是否有消息可用。(Kafka就是用的这个模型)
- 发布订阅模式
发布订阅模式类似与报纸发行商与顾客:**当有新的消息放入消息队列中时,队列会将消息推送给订阅过该类消息的消费者。**优点即是不需要额外线程去感知消息是否存在,缺点就在于推送的速度是一个值得权衡的问题。
其他
为什么kafka只支持增加分区数量,而不能减小分区数量?
——减小分区数量有一个问题就在于,如何保证消息的可靠性?将数据移动至其他分区,又需要考虑offset的有序性,进一步讨论可查看为什么不能减小分区数量。
Zookeeper
Zookeeper是Apache软件基金会的一个专为大型分布式计算机提供分布式配置服务、同步服务和命名注册的开源软件。
ookeeper的命名空间形似文件系统,以KV形式存储:
注:一个分布式系统最多满足CAP理论中的其中两项;
注:BASE理论是指Basically Avaliable、Soft-state(软状态,即运行分布式系允许分布式系统出现中间状态)、Eventually Consistent(最终一致性)。(该理论是指虽然无法达到强一致性,但是要实现最终一致性)
详情可见:Zookeeper