分布式消息系统 Kafka
kafka概述
Apache Kafka 是一个快速、可扩展的、高吞吐的、可容错的分布式“发布-订阅”消息系统,
使用 Scala 与 Java 语言编写,能够将消息从一个端点传递到另一个端点,较之传统的消息中
间件(例如 ActiveMQ、RabbitMQ),Kafka 具有高吞吐量、内置分区、支持消息副本和高容
错的特性,非常适合大规模消息处理应用程序。
Kafka 官网: http://kafka.apache.org/
kafka系统架构
kafka几个特性中可扩展的、可容错都是因为kafka架构中有zookeeper参与的原因。
应用场景
Kafka 的应用场景很多,这里就举几个最常见的场景。
- 消息系统 Messaging
- Web 站点活动追踪 Website Activity Tracking
- 数据监控 Metrics
- 日志聚合 Log Aggregation
- 流处理 Stream Processiong
kafka 高吞吐率实现
Kafka 与其它 MQ 相比,其最大的特点就是高吞吐率。为了增加存储能力,Kafka 将所有的消息都写入到了低速大容的硬盘。按理说,这将导致性能损失,但实际上,kafka 仍可保持超高的吞吐率,性能并未受到影响。其主要采用了如下的方式实现了高吞吐率。
- 顺序读写:Kafka 将消息写入到了分区 partition 中,而分区中消息是顺序读写的。顺序读写要远快于随机读写。
- 零拷贝:生产者、消费者对于 kafka 中消息的操作是采用零拷贝实现的。
- 批量发送:Kafka 允许使用批量消息发送模式。
- 消息压缩:Kafka 支持对消息集合进行压缩。
名词解释
topic(主题)
topic是一个逻辑上的概念,代表着一个消息主题,消费者订阅不同的主题来进行消费,在逻辑上给一个消息进行分类。
partition(分区)
partition是物理上的一个概念,代表着消息存放的物理上的一个分区,体现在/kafka_logs文件夹中命名为topic-分区编号。如topic名为test的第一个分区为test-0文件夹。
在kafka中,单个partition是kafka并行操作的最小单元。
partition的分布
partition在各个broker中是均匀分布的,前提是partition数量是broker的倍数。如果小于或者不是倍数,就会导致各个broker的压力不均。
partition数量
在资源足够的情况下,partition越多速度越快。但是随着partition的数量增多,会出现下面问题。
- 越多的分区需要打开更多的文件句柄
- 更多的分区会导致端对端的延迟
- 越多的partition意味着需要更多的内存
- 越多的partition会导致更长时间的恢复期
partition与消费者之间的关系
partition只会对应一个消费者分组之中的一个消费者
假设分区数量为M,消费者数量为N
- 当M>1,N=1时,所有分区都从属于一个消费者
- 当M>1,N>1时,分区会均匀分布于消费者
- 当N>M时,会出现闲置的消费者
segment
segment 是一个逻辑概念,其由两类物理文件组成,分别为“.index”文件和“.log”文件。“.log”文件中存放的是消息,而“.index”文件中存放的是“.log”文件中消息的索引。每一个segment大小最大值是相同的,但是大小是不同的。
segment 文件命名规则
segment文件为20位长的前补0的数字,代表着创建该文件时,topic已经存储的消息数量。
举个例子,topic刚创建之后可以ll查看一下,是00000000000000000000.log,
当已经存储180条数据,再插入第181条时发现要超过最大值放不下了,这是就会创建下一个segment,命名为00000000000000000180.log
再把这第181条数据放在00000000000000000180.log中,index文件中写入,offset是0,地址是指向刚才00000000000000000180.log文件中的数据。
segment中消息查找的过程
例如读取offset=368776的message,需要通过下面2个步骤查找。
第一步查找segment file
上述图2为例,其中00000000000000000000.index表示最开始的文件,起始偏移量(offset)为0.第二个文件00000000000000368769.index的消息量起始偏移量为368770 = 368769 + 1.同样,第三个文件00000000000000737337.index的起始偏移量为737338=737337 + 1,其他后续文件依次类推,以起始偏移量命名并排序这些文件,只要根据offset 二分查找文件列表,就可以快速定位到具体文件。
当offset=368776时定位到00000000000000368769.index|log
第二步通过segment file查找message
通过第一步定位到segment file,当offset=368776时,依次定位到00000000000000368769.index的元数据物理位置和 00000000000000368769.log的物理偏移地址,然后再通过00000000000000368769.log顺序查找直到 offset=368776为止。
从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间