1. Kafka
Kafka 是一种高吞吐量、分布式、基于发布/订阅的消息系统,最初由 LinkedIn 公司开发,使用 Scala语言编写,目前是Apache的开源项目。
特点:
高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作。
可扩展性:kafka集群支持热扩展
持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)
高并发:支持数千个客户端同时读写
应用场景
日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、HBase、Solr等。
消息系统:解耦和生产者和消费者、缓存消息等。
用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
流式处理:比如 Spark streaming 和 Flink
2、Kafka架构
几个核心概念:
1. Broker:Kafka服务器,负责消息存储和转发
2. Topic:消息类别,Kafka按照topic来分类消息
3. Partition:topic的分区,一个 topic 可以包含多个 partition,topic消息保存在各个 partition上
4. Offset:消息在日志中的位置,可以理解是消息在 partition上的偏移量,也是代表该消息的唯一序号
5. Producer:消息生产者
6. Consumer:消息消费者
7. Consumer Group:消费者分组,每个Consumer必须属于一个group
8. Replica: partition 的副本,保障 partition 的高可用。
9. Leader: replica 中的一个角色, producer 和 consumer 只跟 leader 交互。
10. Follower: replica 中的一个角色,从 leader 中复制数据。
11. Controller: kafka 集群中的其中一个服务器,用来进行 leader election 以及 各种 failover。
12. Zookeeper:保存着集群broker、topic、partition等meta数据;另外,还负责broker 故障发现,partition leader选举,负载均衡等功能
3. Kafka高效数据存储设计
partition的数据文件(offset,MessageSize,data)
partition中的每条Message包含了以下三个属性:offset,MessageSize,data,其中offset表 示 Message 在这个 partition 中的偏移量,offset 不是该 Message 在 partition 数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了partition中的一条Message,可以认为offset是partition中 Message 的 id;MessageSize 表示消息内容 data 的大小;data 为 Message 的具体内容。
数据文件分段segment(顺序读写、分段命令、二分查找)
partition物理上由多个segment文件组成,每个segment大小相等,顺序读写。每个segment 数据文件以该段中最小的offset命名,文件扩展名为.log。这样在查找指定offset的Message的时候,用二分查找就可以定位到该Message在哪个segment数据文件中。
数据文件索引(分段索引、稀疏存储)
Kafka 为每个分段后的数据文件建立了索引文件,文件名与数据文件的名字是一样的,只是文件扩 展名为.index。index 文件中并没有为数据文件中的每条 Message 建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以 将索引文件保留在内存中。
4.Kafka 生产者
负载均衡(partition会均衡分布到不同broker上)
由于消息 topic 由多个 partition 组成,且 partition 会均衡分布到不同 broker 上,因此,为了有效利用broker集群的性能,提高消息的吞吐量,producer可以通过随机或者hash等方式,将消息平均发送到多个partition上,以实现负载均衡。
批量发送
是提高消息吞吐量重要的方式,Producer 端可以在内存中合并多条消息后,以一次请求的方式发送了批量的消息给 broker,从而大大减少 broker 存储消息的 IO 操作次数。但也一定程度上影响 了消息的实时性,相当于以时延代价,换取更好的吞吐量。
压缩(GZIP或Snappy)
Producer端可以通过GZIP或Snappy格式对消息集合进行压缩。Producer端进行压缩之后,在 Consumer 端需进行解压。压缩的好处就是减少传输的数据量,减轻对网络传输的压力,在对大数据处理上,瓶颈往往体现在网络上而不是CPU(压缩和解压会耗掉部分CPU资源)。
5. Kafka消费者
Consumer Group
同一 Consumer Group 中的多个 Consumer 实例,不同时消费同一个 partition,等效于队列模式。
partition内消息是有序的,Consumer通过pull方式消费消息。Kafka不删除已消费的消息
对于partition,顺序读写磁盘数据,以时间复杂度O(1)方式提供消息持久化能力。
6、 Kafka 是如何实现高吞吐率的?
写操作
1. 写入内核区内存: 直接写入os cache里,也就是写入内存中,接下来由操作系统自己决定什么时候把os cache里的数据真的刷入磁盘文件中,相当于写内存而不是写磁盘;
2. 顺序写:仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。
分发操作
3. 零拷贝: 直接让操作系统的cache中的数据发送到网卡后传输给下游的消费者,中间跳过了两次拷贝数据的步骤,Socket缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到Socket缓存。
4. 批量压缩:Producer端可以通过GZIP或Snappy格式对消息集合进行压缩。Producer端进行压缩之后,在 Consumer 端需进行解压。压缩的好处就是减少传输的数据量,减轻对网络传输的压力,在对大数据处理上,瓶颈往往体现在网络上而不是CPU(压缩和解压会耗掉部分CPU资源)。
5. 批量发送: 提高消息吞吐量重要的方式,Producer 端可以在内存中合并多条消息后,以一次请求的方式发送了批量的消息给 broker,从而大大减少 broker 存储消息的 IO 操作次数。但也一定程度上影响 了消息的实时性,相当于以时延代价,换取更好的吞吐量。
存储
6. 分区patition分段segment + 索引index
分布式系统分区分桶的设计思想:Kafka 的 message 是按 topic 分类存储的,topic 中的数据又是按照一个一个的 partition 即分区存储到不同broker节点。每个partition对应了操作系统上的一个文件夹,partition实际上又是按照segment分段存储的。为了进一步的查询优化,Kafka又默认为分段后的数据文件建立了索引文件,就是文件系统上的.index文件。
这种分区分段+索引的设计,不仅提升了数据读取的效率,同时也提高了数据操作的并行度。
7、Kafka 的高可靠性是怎么实现的?
Topic 分区副本:提高容错
从 0.8.0 版本开始Kafka引入了分区副本,一般设置为3。Kafka 的分区多副本架构是 Kafka 可靠性保证的核心,把消息写入多个副本可以使 Kafka 在发生崩溃时仍能保证消息的持久性。
在众多的分区副本里面有一个副本是 Leader,其余的副本是 follower,所有的读写操作都是经过 Leader 进行的,同时 follower 会定期地去 leader 上的复制数据。当 Leader 挂了的时候,其中一个 follower 会重新成为新的 Leader。通过分区副本,引入了数据冗余,同时也提供了 Kafka 的数据可靠性。
Producer 往 Broker 发送消息:消息确认机制保证可靠性
通过 Producer 往 Kafka 对应的主题发送消息时, Kafka 在 Producer 里面提供了消息确认机制来保证可靠性。即通过配置来决定消息发送到对应分区的几个副本才算消息发送成功。
Leader 选举:当Leader挂点之后重新选举出新Leader
在ISR(in-sync replicas)列表中,每个分区的 leader 会维护一个 ISR 列表,ISR 列表里面就是 follower 副本的 Borker 编号,只有跟得上 Leader 的 follower 副本才能加入到 ISR 里面。所以当 Leader 挂掉了,而且 unclean.leader.election.enable=false
的情况下,Kafka 会从 ISR 列表中选择第一个 follower 作为新的 Leader,因为这个分区拥有最新的已经 committed 的消息。通过这个可以保证已经 committed 的消息的数据可靠性。
8、Kafka 的数据一致性是怎么实现的?
一致性定义:若某条消息对Consumer可见,那么即使Leader宕机了,在新Leader上数据依然可以被读到
HighWaterMark简称HW:Partition的高水位,取一个partition对应的ISR中最小的LEO作为HW,消费者最多只能消费到HW所在的位置,另外每个replica都有highWatermark,leader和follower各自负责更新自己的highWatermark状态,highWatermark <= leader. LogEndOffset
对于Leader新写入的msg,Consumer不能立刻消费,Leader会等待该消息被所有ISR中的replica同步后,更新HW,此时该消息才能被Consumer消费,即Consumer最多只能消费到HW位置
这样就保证了如果Leader Broker失效,该消息仍然可以从新选举的Leader中获取。对于来自内部Broker的读取请求,没有HW的限制。同时,Follower也会维护一份自己的HW,Folloer.HW = min(Leader.HW, Follower.offset)
9.Kafka 是如何做到消息的有序性?
kafka 中的每个 partition 中的消息在写入时都是有序的,而且单独一个 partition 只能由一个消费者去消费,可以在里面保证消息的顺序性。但是分区之间的消息是不保证有序的。
10.Kafka为什么要分区?
分区对于 Kafka 集群的好处是:实现负载均衡。
分区对于消费者来说,可以提高并发度,提高效率。
11、ISR、OSR、AR 是什么?
这些都是关于副本的术语。
ISR:In-Sync Replicas 副本同步队列
OSR:Out-of-Sync Replicas
AR:Assigned Replicas 所有副本
ISR是由leader维护,follower从leader同步数据有一些延迟,超过相应的阈值会把 follower 剔除出 ISR, 存入OSR(Out-of-Sync Replicas )列表,新加入的follower也会先存放在OSR中。AR = ISR + OSR。