kafka 是什么?
Apache Kafka是由Apache开发的一种发布订阅消息系统,它是一个分布式的、分区的和重复的日志服务。
Kafka的优缺点?
优点:
- 高性能:性能卓越,单机写入TPS约在百万条/秒,最大的优点,就是吞吐量高;
- 可用性:非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用;
- 可扩展:Kafka集群可以透明的扩展,增加新的服务器进集群。
缺点:
- 重复消息:Kafka保证每条消息至少送达一次,虽然几率很小,但一条消息可能被送达多次;
- 消息乱序:Kafka某一个固定的Partition内部的消息是保证有序的,如果一个Topic有多个Partition,partition之间的消息送达不保证有序;
- 复杂性:Kafka需要Zookeeper的支持,Topic一般需要人工创建,部署和维护比一般MQ成本更高。
kafka的使用场景?
1)日志收集
可以用Kafka收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer。
2)消息系统
解耦生产者和消费者、缓存消息等。
3)用户活动跟踪
kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后消费者通过订阅这些topic来做实时的监控分析,亦可保存到数据库。
4)运营指标
kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
5)大数据实时计算
kafka被应用到大数据处理,如与spark、storm等整合。
Kafka的架构设计?
Kafka 架构分为以下几个部分:
1.Producer (消息生产者)
Producer 就是向 kafka broker 发消息的客户端。
2)Consumer (消息消费者)
Consumer 就是 kafka broker 取消息的客户端。
3)Topic(主题)
Topic可以理解为一个队列,一个 Topic 又分为一个或多个分区。
4)Broker(消息中介)
一台 kafka 服务器就是一个 broker,一个集群由多个 broker 组成,一个 broker 可以容纳多个 topic。
5)Partition(分区)
为了实现扩展性,一个非常大的 topic 可以分布到多个 broker上,每个 partition 是一个有序的队列。
partition 中的每条消息都会被分配一个有序的id(offset)。将消息发给 consumer,kafka 只保证按一个 partition 中的消息的顺序,不保证一个 topic 的整体(多个 partition 间)的顺序。
6)Offset(偏移量)
kafka 的存储文件都是按照 offset.kafka 来命名,用 offset 做名字的好处是方便查找。例如你想找位于 2049 的位置,只要找到 2048.kafka 的文件即可。当然 the first offset 就是 00000000000.kafka。
Zookeeper 对于 Kafka 的作用?
zookeeper在kafka中扮演了重要的角色,kafka使用zookeeper进行元数据管理,保存broker注册信息,包括主题(Topic)、分区(Partition)信息等,选择分区leader,在低版本kafka消费者的offset信息也会保存在zookeeper中。
如图使用zookeeper客户端PrettyZoo查看内容如下:
Kafka中的broker 是干什么的?
broker 是消息的代理,Producers往Brokers里面的指定Topic中写消息,Consumers从Brokers里面拉取指定Topic的消息,然后进行业务处理,broker在中间起到一个代理保存消息的中转站。
Kafka消息是采用Pull模式,还是Push模式?
kafka遵循了pull模式也就是靠靠消费者主动拉取。
Kafka遵循了一种大部分消息系统共同的传统的设计:producer将消息推送到broker,consumer从broker拉取消息。
Kafka 分区的目的?
分区对于 Kafka 集群的好处是:实现负载均衡,分区对于消费者来说,可以提高并发度,提高效率。
为什么Kafka不支持读写分离?
在 Kafka 中生产者写入消息与消费者读取消息的操作都是与 leader 副本进行交互的,从 而实现的是一种主写主读的生产消费模型。
Kafka 并不支持主写从读,因为主写从读有 2 个很明 显的缺点:
1)数据一致性问题
数据从主节点转到从节点必然会有一个延时的时间窗口,这个时间 窗口会导致主从节点之间的数据不一致。
2)延时问题
类似 Redis 这种组件,数据从写入主节点到同步至从节点中的过程需要经 历网络→主节点内存→网络→从节点内存这几个阶段,整个过程会耗费一定的时间。
而在 Kafka 中,主从同步会比 Redis 更加耗时,它需要经历网络→主节点内存→主节点磁盘→网络→从节 点内存→从节点磁盘这几个阶段,对延时敏感的应用而言,主写从读的功能并不太适用。
kafka如何实现高吞吐量和性能?
主要通过以下几点:
1、页缓存技术
Kafka 是基于操作系统 的页缓存(page cache)来实现文件写入的,我们也可以称之为 os cache,意思就是操作系统自己管理的缓存。
Kafka 在写入磁盘文件的时候,可以直接写入这个 os cache 里,也就是仅仅写入内存中,接下来由操作系统自己决定什么时候把 os cache 里的数据真的刷入磁盘文件中。
通过这一个步骤,就可以将磁盘文件写性能提升很多了,因为其实这里相当于是在写内存,不是在写磁盘,原理图如下:
2、磁盘顺序写
另一个主要功能是 kafka 写数据的时候,是以磁盘顺序写的方式来写的,也就是说仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。
普通的机械磁盘如果你要是随机写的话确实性能极差,也就是随便找到文件的某个位置来写数据。
但是如果你是 追加文件末尾 按照顺序的方式来写数据的话,那么这种磁盘顺序写的性能基本上可以跟写内存的性能相差无几,如下图所示:
基于上面两点,kafka 就实现了写入数据的超高性能
3、零拷贝
先来看看非零拷贝的情况,如下图所示:
可以看到数据的拷贝从内存拷贝到 Kafka 服务进程那块,又拷贝到 Socket 缓存那块,整个过程耗费的时间比较高。
Kafka 利用了 Linux 的 sendFile 技术(NIO),省去了进程切换和一次数据拷贝,让性能变得更好,如下图所示:
通过 零拷贝技术,就不需要把 os cache 里的数据拷贝到应用缓存,再从应用缓存拷贝到 Socket 缓存了,两次拷贝都省略了,所以叫做零拷贝。
4、分区分段+索引
Kafka 的 message 是按 topic分 类存储的,topic 中的数据又是按照一个一个的 partition 即分区存储到不同 broker 节点。每个 partition 对应了操作系统上的一个文件夹,partition 实际上又是按照segment分段存储的。
通过这种分区分段的设计,Kafka 的 message 消息实际上是分布式存储在一个一个小的 segment 中的,每次文件操作也是直接操作的 segment。为了进一步的查询优化,Kafka 又默认为分段后的数据文件建立了索引文件,就是文件系统上的.index文件。这种分区分段+索引的设计,不仅提升了数据读取的效率,同时也提高了数据操作的并行度。
Kafka生产者发送消息有哪些模式?
总共有三种模式:
1.发后即忘(fire-and-forget)
它只管往 Kafka 里面发送消息,但是不关心消息是否正确到达,这种方式的效率最高,但是可靠性也最差,比如当发生某些不可充实异常的时候会造成消息的丢失
2.同步(sync)
producer.send()返回一个Future对象,调用get()方法变回进行同步等待,就知道消息是否发送成功,发送一条消息需要等上个消息发送成功后才可以继续发送
3.异步(async)
Kafka支持 producer.send() 传入一个回调函数,消息不管成功或者失败都会调用这个回调函数,这样就算是异步发送,我们也知道消息的发送情况,然后再回调函数中选择记录日志还是重试都取决于调用方
数据传输的事务有几种?
数据传输的事务定义通常有以下三种级别:
1)最多一次
消息不会被重复发送,最多被传输一次,但也有可能一次不传输
2)最少一次
消息不会被漏发送,最少被传输一次,但也有可能被重复传输
3)精确的一次(Exactly once)
不会漏传输也不会重复传输,每个消息都传输被
Kafka 的消息消费方式有哪些?
一般消息消费有两种模式,推和拉。Kafka的消费是属于拉模式的,而此模式的消息消费方式有两种,点对点和发布订阅。
点对点:如果所有消费者属于同一个消费组,那么所有的消息都会被均匀的投递给每一个消费者,每条消息只会被其中一个消费者消费。
发布订阅:如果所有消费者属于不同的消费组,那么所有的消息都会被投递给每一个消费者,每个消费者都会收到该消息。
Kafka 如何保证消息的消费顺序?
出现顺序乱的原因或背景:
1)同一个订单队列,被多个消费者消费,就会导致顺序错乱;
2)同一个订单号的不同行为,被分配到不同的队列里,被不同的消费者消费,也会造成错乱。
解决思路:
1)相同行为的消息存放到同一个MQ服务器中;
2)最终只会有单个消费者去消费。
kafka 中的每个 partition 中的消息在写入时都是有序的,而且单独一个 partition 只能由一个消费者去消费,可以在里面保证消息的顺序性,但是分区之间的消息是不保证有序的。
Kafka 如何保证消息不丢失?
生产者(Producer) 调用send方法发送消息之后,消息可能因为网络问题并没有发送过去。
所以,我们不能默认在调用send方法发送消息之后消息发送成功了。为了确定消息是发送成功,我们要判断消息发送的结果。但是要注意的是 Kafka 生产者(Producer) 使用 send 方法发送消息实际上是异步的操作,我们可以通过 get()方法获取调用结果,但是这样也让它变为了同步操作。
示例代码如下:
ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topic, o); future.addCallback(result -> logger.info("生产者成功发送消息到topic:{} partition:{}的消息", result.getRecordMetadata().topic(), result.getRecordMetadata().partition()), ex -> logger.error("生产者发送消失败,原因:{}", ex.getMessage()));
如果消息发送失败的话,我们检查失败的原因之后重新发送即可。
备注:另外这里推荐为 Producer 的retries (重试次数)设置一个比较合理的值,一般是 3 ,但是为了保证消息不丢失的话一般会设置比较大一点。
Kafka 如何保证消息不重复消费?
Kafka出现重复消费的原因:
1)kafka是通过offset来标记消费的。默认情况下,消费完成后会自动提交offset,避免重复消费。
Kafka消费端的自动提交逻辑有一个默认的5秒间隔,也就是说在5秒之后的下一次向Broker拉取消息的时候提交。
所以在Consumer消费的过程中,应用程序被强制kill掉或者宕机,可能会导致Offset没提交,从而产生重复提交的问题。
2)Kafka里面有一个Partition Balance机制,就是把多个Partition均衡的分配给多个消费者。
Consumer端会从分配的Partition里面去消费消息,如果Consumer在默认的5分钟内没办法处理完这一批消息。
就会触发Kafka的Rebalance机制,从而导致Offset自动提交失败。
而在重新Rebalance之后,Consumer还是会从之前没提交的Offset位置开始消费,也会导致消息重复消费的问题。
解决办法:
1)消费消息服务做幂等校验
比如 Redis 的set、MySQL 的主键等天然的幂等功能,这种方法最有效。
2)提高消费端的处理性
提高消费端的处理性能避免触发Balance,比如可以用异步的方式来处理消息,缩短单个消息消费的市场,或者还可以调整消息处理的超时时间,还可以减少一次性从Broker上拉取数据的条数。
如何调优 Kafka?
对于 Kafka 而言,常见的优化目标是吞吐量、延时、持久性和可用性,可以从以下3个方面来考虑:
- Producer 端:增加 batch.size、linger.ms,启用压缩,关闭重试等;
- Broker 端:增加 num.replica.fetchers,提升 Follower 同步 TPS,避免 Broker Full GC 等;
- Consumer:增加 fetch.min.bytes 等。
Kafka如何实现延迟队列?
Kafka并没有使用JDK自带的Timer或者DelayQueue来实现延迟的功能,而是基于时间轮自定义了一个用于实现延迟功能的定时器(SystemTimer)。JDK的Timer和DelayQueue插入和删除操作的平均时间复杂度为O(nlog(n)),并不能满足Kafka的高性能要求,而基于时间轮可以将插入和删除操作的时间复杂度都降为O(1)。时间轮的应用并非Kafka独有,其应用场景还有很多,在Netty、Akka、Quartz、Zookeeper等组件中都存在时间轮的踪影。
Kafka 监控都有哪些?
三种kafka监控程序分别为:
1)Kafka Web Conslole
使用Kafka Web Console,可以监控:
Brokers列表
Kafka 集群中 Topic列表,及对应的Partition、LogSiz e等信息
点击Topic,可以浏览对应的Consumer Groups、Offset、Lag等信息
2)Kafka Manager
Kafka Manager雅虎开源的Kafka集群管理工具。
3)KafkaOffsetMonitor
- KafkaOffsetMonitor可以实时监控:
- Kafka集群状态
- Topic、Consumer Group列表
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》