作者| liuhehe123
来源| CSDN博客 责编| Carol
出品| CSDN云计算(ID:CSDNcloud)
封图| CSDN下载于视觉中国
无论是已经接触过 Kafka 还是刚入坑的小伙伴,都应该时不时回头了解一下 Kafka ,有时候会有不少新收获。今天这份 Kafka 的介绍,建议再认真阅读一遍哦~
Kafka在设计之初就考虑的问题:
吞吐量/延时
消息持久化
负载均衡和持久化
伸缩性
吞吐量
kafka是如何做到高吞吐量和低延时的呢?
kafka的写入操作是很快的,这主要得益于它对磁盘的使用方法不同。虽然kafka会持久化所有数据到磁盘,但本质上每次写入操作其实都只是把数据写入到操作系统的页缓存中,然后由操作系统自行决定什么时候把页缓存中的数据写回磁盘。
先说kafka是咋实现的,kafka依靠下列4点达到了高吞吐量、低延时的设计目标:
大量使用操作系统叶缓存,内存操作速度快且命中率高。
kafka不直接参与物理I/O操作,而是交给最擅长此事的操作系统来完成。
采用追加写入的方式,摒弃了缓慢的磁盘随机读写操作。
使用以sendfile为代表的的零拷贝技术加强网络间的数据传输效率。
前三个都是使用页缓存的好处,页缓存是在内存中分配的,所以写入消息很快。使得kafka不必直接与底层文件系统打交道。另外采用追加的方式写入,避免了磁盘随机写操作。
零拷贝:
简而言之,就是避免让CPU做大量的数据拷贝技术,采用不使用CPU时间的技术进行系统内核缓冲区之间的数据拷贝。
从上图中可以看出,共产生了四次数据拷贝,即使使用了DMA来处理了与硬件的通讯,CPU仍然需要处理两次数据拷贝,与此同时,在用户态与内核态也发生了多次上下文切换,无疑也加重了CPU负担。
1、让数据传输不需要经过user space
我们减少拷贝次数的一种方法是调用mmap()来代替read调用:
buf = mmap(diskfd, len);
write(sockfd, buf, len);
应用程序调用mmap(),磁盘上的数据会通过DMA被拷贝的内核缓冲区,接着操作系统会把这段内核缓冲区与应用程序共享,这样就不需要把内核缓冲区的内容往用户空间拷贝。应用程序再调用write(),操作系统直接将内核缓冲区的内容拷贝到socket缓冲区中,这一切都发生在内核态,最后,socket缓冲区再把数据发到网卡去。
2、sendfile
使用sendfile不仅减少了数据拷贝的次数,还减少了上下文切换,数据传送始终只发生在kernel space。下图为使用DMA的sendfile零拷贝技术图。
消息持久化
kafka是要持久化消息的,而且要将消息持久化到磁盘上的。
先说这样做的好处(为什么要持久化):
解耦消息发送与消息消费:通过将消息持久化使得生产者不再需要直接和消费者方耦合,它只是简单地把消息生产出来并交由kafka服务器保存起来即可。
实现灵活的消息处理(便于消息重演):很多kafka下游子系统(消费方)都会有这样的需求——对于已经处理过的消息可能在未来的某个时间点重新处理一次,即所谓的消息重演(message replay)。
那么kafka持久化是咋做的呢?
对比一下:
普通的系统实现持久化时可能先尽量使用内存,当内存资源耗尽时,再一次性地把数据 “刷盘”;kafka则反其道行之,所有数据都会立即被写入到文件系统的持久化日志中,之后kafka服务器才会返回结果给客户端,通知客户端消息写入成功。这样做即实时保存了数据,又减少了kafka程序对于内存的消耗,从而将节省出的内存留给页缓存使用,进一步提升整体性能。
这里解释下:kafka在吞吐量中说使用页缓存,持久化又说尽量减少对内存的消耗,这是咋回事?
总的来说,Kafka不会保持尽可能多的内容在内存空间,而是尽可能把内容直接写入到磁盘。所有的数据都及时的以追加的方式写入到文件系统的持久化日志中,而不必要把内存中的内容刷新到磁盘中。
负载均衡和故障转移
kafka作为一个完备的分布式系统,肯定也是要满足负载均衡和故障转移处理操作的。
负载均衡:kafka的负载均衡是通过智能化的分区领导者选举来实现的。可以在集群中的所有机器上以均等的机会分散各个partition的leader,从而整体上实现了负载均衡。【后面进行补充】
故障转移(使用zookeeper):即当服务器意外中止时,整个集群能够快速检测到他失效了,并立即将该服务器上的应用或服务转移到其他机器上。kafka使用的是会话机制来解决的。每台kafka服务器启动后会以会话的形式把自己注册到zookeeper服务器上,一旦该服务器运转出现问题,与zookeeper的会话便不能维持从而超时失效,此时kafka会选举出一台新的服务器赖万全代替这台服务器继续提供服务。
伸缩性
伸缩性指的是:向分布式系统系统中增加额外的计算资源时提升吞吐量的能力。
如果服务器是无状态的,状态的保存和管理交给专门的协调服务来做,比如 zookeeper ,那么整个集群的服务器之间就不需要再进行繁重的状态共享,这极大地降低了维护复杂度。
Kafka 正式采用了这一思想——每台kafka的服务器上的状态统一交由Zookeeper保管。而扩展kafka集群就很容易:启动一台新的kafka服务器即可。
需要说明的一点是,kafka服务器并不是所有状态都不保存,他只是保存了很轻量级的内部状态,所以整个集群间维护状态一致性的代价很低。
来看看kafka的基本概念和术语
目前kafka最新的版本是 2.4。
1、broker、topic、partition、offset、replica、leader和follower
下面是Kafka的大致架构图:
Kafka服务器官方称呼为:broker。
先来说说Kafka的消息格式是啥样的?
消息由三部分组成:消息头部、key 和 value。
消息头:包括CRC码、消息版本、属性、时间戳、键长度和消息体长度等信息。
Key: 消息键, 对消息做partition时使用,即决定消息被保存在某个topic下的那个partition。
Value:消息体,保存实际的消息数据。
Timestamp: 消息发送时间戳。
2、kafka的Topic和Partition 到底是个什么东西?
Topic(主题): topic代表了一类消息,也可以认为消息被发送到的地方。比如业务A使用一个topic, 业务B使用另外一个topic。相当于 柴鸡蛋和茶叶蛋这样简单分下。
Partition(分区)???? 一个Topic可以由多个partition组成,而kafka的partition是不可修改的有序消息序列。分区是物理层面的,用户是看不到的,用户不用管这些消息怎么取出来的,之所以做分区,主要是为了提高系统的吞吐量。
3、offset
一个(生产的)消息的写入offset位移值, 一个是消费者端的消费位移offset。他俩是不同的概念。
消费该partition的消费者位移会随着消费进度不断前移,不过终究不可能超过该分区的最新一条消息的位移。
kafka的一条消息其实就是一个三元组:
4、replica
kafka的冗余机制,备份多份日志,这些备份日志在kafka中被称为副本(replica),他们存在就是为了 防止数据丢失的。
5、leader和follower
leader提供对外服务,follower与leader保持同步,follower存在的目的就是用来充当leader的候补。
6、ISR(同步副本集合)
kafka为partition动态维护了一个replica集合,该集合中的所有replica保存的消息日志都与leader replica 保持同步状态。
记住,只有这个集合(ISR)中的replica才能被选为leader,也只有这个集合中的所有replica都接受到了同一条消息,Kafka才会将消息置于 “已提交” 状态,即认为这条消息发送成功。
【这里不要与producer端搞混,producer端的参数acks设置 0、all/-1 、1的情况,会在后面的文章补充。】
7、kafka使用场景
消息传输
网站行为日志跟踪
日志收集
流式处理
零拷贝部分参考作者以及链接:
作者:卡巴拉的树 https://www.jianshu.com/p/fad3339e3448
本文来源 CSDN 博客,原文链接:
https://blog.csdn.net/liuhehe123/article/details/105429934
同时,欢迎所有开发者扫描下方二维码填写《开发者与AI大调查》,只需2分钟,即可收获价值299元的“ AI开发者万人大会”在线直播门票!
推荐阅读:小网站的容器化(下):网站容器化的各种姿势,先跟着撸一波代码再说!
你知道吗?其实Oracle直方图自动统计算法存在这些缺陷!(附验证步骤)
详解以太坊虚拟机(EVM)的数据存储机制
比特币当赎金,WannaRen勒索病毒二度来袭!平台抗住日访问量7亿次,研发品控流程全公开“手把手撕开LeetCode翻译,扒各种算法套路的裤子”北京四环堵车引发的智能交通大构想
真香,朕在看了!