Kafka
什么是kafka?
-
kafka是一个开源的分布式事件流平台,被数千家公司用于高性能数据管道、流分析、数据集成和任务关键型应用程序
-
事件流是人体中枢神经系统的数字等价物。它是“常在”世界的技术基础,企业越来越多地被软件定义和自动化,而软件的使用者则是更多的软件。
-
从技术上讲,事件流是以事件流的形式从事件源(如数据库、传感器、移动设备、云服务和软件应用程序)实时捕获数据的实践;持久地存储这些事件流以供以后检索;操作、处理、,以及对事件流作出实时和回顾性的反应;并且根据需要将事件流路由到不同的目的地技术。
-
因此,事件流确保了数据的连续流动和解释,从而使正确的信息在正确的时间、正确的地点出现
- 事件流应用场景
* 在证券交易所、银行和保险业中,处理实时支付和金融交易的能力过强。
* 实时跟踪和监控汽车、卡车、车队和货物,如物流和汽车行业。
* 从物联网设备或其他设备(如工厂和风电场)持续捕获和分析传感器数据。
* 收集并立即响应客户的互动和订单,如零售业、酒店和旅游业以及移动应用程序。
* 对住院病人进行监护,预测病情变化,确保紧急情况下及时治疗。
* 连接、存储和提供公司不同部门产生的数据。
* 作为数据平台、事件驱动架构和微服务的基础。
kafka有哪些特点?
kafka的基本架构?
- kafka的主要组件和术语
* event: 一个事件记录了世界上或你的生意中“发生了什么事”的事实。在文档中也称为记录或消息。当你读或写数据给kafka,你这样做的形式是事件。从概念上讲,事件具有键、值、时间戳和可选的元数据头
* Producers: 是那些将事件发布(写入)到Kafka的客户机应用程序
* Consumers: 消费者是那些订阅(读取和处理)这些事件的应用程序。
在Kafka中,生产者和消费者完全解耦,彼此不可知,这是实现Kafka所熟知的高可伸缩性的关键设计元素。例如,生产者从不需要等待消费者。卡夫卡提供了各种各样的保证,比如能够精确地处理一次事件
* Topics: 类似于文件系统中的文件夹,事件就是该文件夹中的文件;事件被组织并持久地存储在Topic中。
* 一个Topic可以有零个、一个或多个生产者向其写入事件,也可以有零个、一个或多个消费者订阅这些事件
* Partition: 是物理上的概念,此处是kafka将一个topic的存放到多个partition,
kafka的工作原理?
- kafka 由两部分构成:servers和clients
- 通过TCP网络协议进行通信
- Servers
* 以集群的形式运行,可以包含一个或者多个server,这些server可以部署在多个云region或者数据中心
* 其中一些服务器形成了存储层,称为代理。
* 其他服务器运行Kafka Connect以持续导入和导出数据作为事件流,从而将Kafka与现有系统(如关系数据库以及其他Kafka集群)集成。
* 为了让您实现任务关键型用例,Kafka集群具有高度的可伸缩性和容错性:如果它的任何一台服务器发生故障,其他服务器将接管它们的工作,以确保连续操作而不丢失任何数据。
- Clients
* 它们允许您编写分布式应用程序和微服务
* 这些应用程序和微服务以并行、大规模和容错的方式读取、写入和处理事件流
* 即使在出现网络问题或机器故障的情况下也是如此。
* kafka包括一些如上描述的Clients,这是由kafka社区提供的几十个客户端扩充的:客户端可以用于java和scala,包括更高级别的kafka流库,如GO、Python、C/C++、以及许多其他编程语言以及REST API
kafka消息会不会丢失,如何保证不丢失?
- kafka有三种语义
at most once
at least once
exectly-once
-
当Consumer消费消息,保存offset后,消息没有来得及处理(或者说处理结果没有输出),Consumer挂了,新的Consumer会从offset之后开始消费,这是at most once 语义
-
当Consumer消费消息,消息处理输出了,但是没来得及保存offset,Consumer挂了,新的Consumer会重复消费没保存offset的那条消息,这是at least once语义
-
exectly-once 每个消息都会有一个id,Consumer消费消息,保存消费到的offset,消息处理后保存处理的消息的id及相关信息,无论在哪种情况Consumer挂了,都会将offset的消息id和已经处理的消息的id及相关信息对比,判断消息是否被成功消费处理,这可以实现exectly-once的语义
-
在kafka-stream中,一个topic将消息发送到另外一个topic是可以保证exectly-once;如果Consumer集成的是外部系统,则依赖于外部系统对消息ID的存放和判断。
从生产者的角度看: * 使用in-sync方式,可以设置至少有一个副本同步成功,才返回发送成功,保证即使leader失败,消息也不会丢失。
kafka如何存储数据?
kafka如何保证高可用?
-
大部分的分布式系统采用投票的方式,选择leader,保证高可用。例如:容忍故障节点为1,需要3个节点,容忍故障节点为2,需要5个节点;这种方法一般用在管理节点或者元数据节点的选择上,而不用在数据的多副本上,因为,这会导致磁盘空间成倍增加,吞吐量变为原来的1/n
-
kafka使用了不同的方法,kafka没有进行多数投票,而是动态地维护一组同步副本(ISR),这些副本被领导者捕获。只有这一组的成员才有资格被选为领导人。在所有同步复制副本都接收到写入操作之前,不会认为对Kafka分区的写入操作已提交。无论何时更改,此ISR集都会保留到ZooKeeper。因此,ISR中的任何复制品都有资格当选领导人。这是卡夫卡使用模型的一个重要因素,在kafka使用模型中,有许多分区,确保领导层的平衡非常重要。有了这个ISR模型和f+1副本,Kafka主题可以容忍f失败而不丢失提交的消息。
创建大量topic会不会影响kafka性能?
kafka如何发送消息,如何分配发送线程?
kafka如何消费消息,如何分配消费线程?
kafka与rocketmq与rabbitmq相比有哪些优缺点?
kafka如何rebalance
- Rebalance 本质上是一种协议,规定了一个 Consumer Group 下的所有 consumer 如何达成一致,来分配订阅 Topic 的每个分区
- Rebalance 的触发条件有3个。
组成员个数发生变化。例如有新的 consumer 实例加入该消费组或者离开组。
订阅的 Topic 个数发生变化。
订阅 Topic 的分区数发生变化
-
Rebalance 过程分为两步:Join 和 Sync
-
Join 顾名思义就是加入组。这一步中,所有成员都向coordinator发送JoinGroup请求,请求加入消费组。一旦所有成员都发送了JoinGroup请求,coordinator会从中选择一个consumer担任leader的角色,并把组成员信息以及订阅信息发给leader——注意leader和coordinator不是一个概念。leader负责消费分配方案的制定
-
Sync,这一步leader开始分配消费方案,即哪个consumer负责消费哪些topic的哪些partition。一旦完成分配,leader会将这个方案封装进SyncGroup请求中发给coordinator,非leader也会发SyncGroup请求,只是内容为空。coordinator接收到分配方案之后会把方案塞进SyncGroup的response中发给各个consumer。这样组内的所有成员就都知道自己应该消费哪些分区了
-
每个Consumer都要定期向coordinator发送心跳:session.timeout.ms进行配置,默认为:10秒 Kafka Rebalance 机制
ISR原理
- kafka动态维护了一个同步状态的副本的集合(a set of In-Sync Replicas),简称ISR
- 在这个集合中的节点都是和leader保持高度一致的,任何一条消息只有被这个集合中的每个节点读取并追加到日志中,才会向外部通知说“这个消息已经被提交”。
- 只有当消息被所有的副本加入到日志中时,才算是“committed”,只有committed的消息才会发送给consumer,这样就不用担心一旦leader down掉了消息会丢失
- 消息从leader复制到follower, 我们可以通过决定producer是否等待消息被提交的通知(ack)来区分同步复制和异步复制。
-
如果等待ack则为同步,如果不需要等待所有follower复制完成即回传ack则为异步模式
-
同步复制:
1.producer联系zk识别leader
2.向leader发送消息
3.leadr收到消息写入到本地log
4.follower从leader pull消息
5.follower向本地写入log
6.follower向leader发送ack消息
7.leader收到所有follower的ack消息
8.leader向producer回传ack
- 异步复制:
和同步复制的区别在于,leader写入本地log之后,直接向client回传ack消息,不需要等待所有follower复制完成。
kafka的应用场景
- Messaging
- Website Activity Tracking
- Metrics
- Log Aggregation
- Stream Processing
- Event Sourcing
- Commit Log
kafka为什么要在topic里加入分区的概念
- 实现了负载均衡和水平扩展
- 是Kafka高吞吐率的重要保证之一
kafka 如何保证高性能
- 将写磁盘的过程变为顺序写
- 充分利用Page Cache
* Page Cache,其中文名称为页高速缓冲存储器,简称页高缓。page cache的大小为一页,通常为4K。在Linux读写文件时,它用于缓存文件的逻辑内容,从而加快对磁盘上映像和数据的访问。 是Linux操作系统的一个特色。
使用Page Cache的好处如下
- I/O Scheduler会将连续的小块写组装成大块的物理写从而提高性能
- I/O Scheduler会尝试将一些写操作重新按顺序排好,从而减少磁盘头的移动时间
- 充分利用所有空闲内存
- 读操作可直接在Page Cache内进行。如果消费和生产速度相当,甚至不需要通过物理磁盘(直接通过Page Cache)交换数据
* Kafka收到数据后,写磁盘时只是将数据写入Page Cache,并不保证数据一定完全写入磁盘。从这一点看,可能会造成机器宕机时,Page Cache内的数据未写入磁盘从而造成数据丢失。但是这种丢失只发生在机器断电等造成操作系统不工作的场景,而这种场景完全可以由Kafka层面的复制机制去解决。如果为了保证这种情况下数据不丢失而强制将Page Cache中的数据Flush到磁盘,反而会降低性能。
* 如果数据消费速度与生产速度相当,甚至不需要通过物理磁盘交换数据,而是直接通过Page Cache交换数据。同时,Follower从Leader Fetch数据时,也可通过Page Cache完成
- 零拷贝
* Linux 2.4+内核通过sendfile系统调用,提供了零拷贝。数据通过DMA拷贝到内核态Buffer后,直接通过DMA拷贝到NIC Buffer,无需CPU拷贝。这也是零拷贝这一说法的来源。除了减少数据拷贝外,因为整个读文件-网络发送由一个sendfile调用完成,整个过程只有两次上下文切换,因此大大提高了性能。
* 从具体实现来看,Kafka的数据传输通过Java NIO的FileChannel的transferTo和transferFrom方法实现零拷贝
备注:从文件到socket的数据传输过程(有两次系统调用)
1. 操作系统从磁盘读数据到内核空间的pagecache;
2. 应用从内核空间读取数据到用户空间的buffer;The application reads the data from kernel space into a user-space buffer
3. 应用程序将数据写回内核空间到套接字缓冲区 The application writes the data back into kernel space into a socket buffer
4. 操作系统从套接字缓冲区复制数据到NIC buffer The operating system copies the data from the socket buffer to the NIC buffer where it is sent over the network
- 端-压缩和解压缩
* 发送端压缩,消费者解压缩
* 支持GZIP,LZ4以及标准的压缩协议
如何判断kafka 节点存活
- 从如下两个方面判断节点是否存活
是否与zk维持session
如果是follower必须和复制leader,并且不能与leader相差太远,如果follower与leader滞后台远,则leader会将follower剔除,滞后参数为:replica.lag.time.max.ms