1. Kafka基本概念
- 话题topic: 特定类型的消息流,话题是消息的分类名。物理上不同topic的消息分开存储,逻辑上一个Topic消息可以保存在一个或多个broker上,但用户只需要指定指定消息的topic即可生产或消费数据而不必关系数据存于何处
- 生产者producer:能够发布消息到话题的任何对象
- kafka集群:已经发布的消息保存的服务器
- 代理broker:kafka集群中的服务器
- 分片partition:Partition:topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队列
- 消费组 consumer group:每个consumer属于一个特定的Consumer Group,可以为每个Consumer指定group name,如果不指定,则属于默认的group。每一个consumer实例都属于一个consumer group,每一条消息只会被同一个consumer group里的一个consumer实例消费。每条消息可以被多个consumer group消费
- segment:partition物理上由多个segment组成
- offset:每个partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到partition中。partition中的每个消息都有一个连续的序列号叫做offset,用于partition唯一标识一条消息
2. Topic,Partition,Segment,Offset
topic和Partition关系
- topic在逻辑上可以认为是一个queue,每条消息都必须指定它的topic
- 为了使Kafka吞吐率可以线性提高,物理上把Topic分成一个或多个Partition,每个Partition在物理上对应一个文件夹,该文件夹下存储这个Partition的所有消息和索引文件。
Partition的存储分布
- 参考http://tech.meituan.com/kafka-fs-design-theory.html
- 目录:在config/server.properties的log.dirs中。同一个topic下有多个不同partition,每个partition是一个目录,目录命名是topic名称+有序序号。
- Partition中文件存储方式
- 每个partition相当于一个巨型文件被平均分配到多个大小相同的segment段数据文件中。但每个段segmentfile的消息数量不一定相等。
- 每个partition只需要支持顺序读写就行了,segment文件生命周期由服务端配置参数决定。
Partition中segment文件存储结构
- segment file组成:由两大部分组成,分别为index file和data file。这两个文件一一对应,后缀.index和.log,分别表示segment索引文件、数据文件
- segment命名规则:partion全局的第一个segment从0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset值。这种命名很重要,有助于通过offset查找message。
- 一个片段segment的index和data file的对应关系,索引中存储大量元数据,数据文件存储大量消息,索引文件中元数据指向对应数据文件中message的物理偏移地址。
Segment数据文件组成
- segment data file由许多message组成
- 如何在Partition中通过offset查找message
- 通过二分查找offset,找到该offset所在的segment文件
- 在所找到的segment文件中,顺序到在index文件中的元数据物理位置和log文件中物理偏移地址。
- segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间
- Partition的好处
- 实现并发:传统的队列,为了保证数据的有序性,只能锁定一个队列。而kafka由于采用Partition的方式,则可以实现并发。
- 实现并发的设计:将一个topic中的所有分片partition分配给一个consumer group中的消费者们。这样的话,每个分片就可以被consumer group中的准确的某个消费者消费。
- 注意:确保一个consumer group中消费者的个数不要多于分片的个数
- kafka的有序性只能保证某个分片内的有序,不能保证分片之间的有效性。如果要想保证所有数据的有序,那么可以只有一个分片。
摘录来自: kafka.apache.org. “Apache Kafka”。 iBooks.
3. 生产者 Producer
1. 负载均衡
- 由producer客户端决定消息被路由到哪个partition。producer将会和Topic下所有partition leader保持socket连接;消息由producer直接通过socket发送到broker,中间不会经过任何”路由层”.路由策略比如random, key-hash。
2. 异步发送
将多条消息暂且在客户端buffer起来,并将他们批量的发送到broker,小数据IO太多,会拖慢整体的网络延迟,批量延迟发送事实上提升了网络效率。不过这也有一定的隐患,比如说当producer失效时,那些尚未发送的消息将会丢失
3. 消息传送保证机制
有几种方式:
1) at most once: 最多一次,这个和JMS中”非持久化”消息类似.发送一次,无论成败,将不会重发.
2) at least once: 消息至少发送一次,如果消息未能接受成功,可能会重发,直到接收成功.
3) exactly once: 消息只会发送一次
4. 消费者 Consumer
- 通常来讲,消息有两种模式:a.队列 b.发布订阅。队列的话,一条消息只能被一个消费者消费。发布订阅的话,消息被所有消费者消费。如果所有consumer实例属于一个consumer group,则实现队列。如果每个consumer group只有一个consumer实例,则实现发布订阅。
- consumer端向broker发送”fetch”请求,并告知其获取消息的offset;此后consumer将会获得一定条数的消息;consumer端也可以重置offset来重新消费消息.
- Consumer与Consumer Group
- 每个consumer实例都属于一个consumer group。每个消息只能被同一个consumer group里的一个consumer实例消费,但不同consumer group可以同时消费同一条消息
5. 系统级别
1. kafka的broker是无状态的
- kafka代理是无状态的,意味着消费者必须维护已消费的状态信息。
- 从代理broker删除消息很棘手,因为代理不知道消费者是否已经使用了该消息。kafka使用一个简单的基于时间的SLA应用于保留策略。当消息在代理中超过一定时间以后,将会自动删除。
- 好处是:消费者可以故意倒回到老的偏移量再次消费数据。
2. broker数据删除
- 不管消息被消费与否,kafka集群会保留所有消息。由于磁盘限制,kafka提供两种策略删除旧数据:一种基于时间,一种基于partition文件大小。可以通过config/server.properties配置
3. ZooKeeper与Kafka
- zookeeper的关注问题:
- 所有分布式系统的一个常见问题是:如何在任一时间点确定哪些服务器活着并且在工作中
- 面对网络失败,带宽限制,可变延迟连接,安全问题,跨多个数据中心时可能发生错误时,如何可靠做这些事情
4. Kafka设计目标
- 以时间复杂度O(1)的方式提供消息持久化能力
- 高吞吐率
- 支持Kafka Server间的消息分区,及分布式消费,同时保证每个Partition内的消息顺序传输
- 同时保持离线数据处理和实时数据处理。
- 支持在线水平扩展
5. 为何使用消息系统
- 解耦
- 扩展性
- 灵活性&峰值处理能力
- 顺序保证
- 异步通信
- demo
参考文章: