带你搞懂Kafka为何如此之快

首先来说一下我们为什么要使用消息系统


 

在没有使用消息系统之前,许多传统的系统业务对于消息的处理一般会采用串行方式或者并行方法;

例如,你去网站注册一个账号,网站服务器对我们的注册操作进行处理,下面是串行跟并行的处理方式。

串行方式:

用户注册例子:用户注册,将注册信息记录到数据库后,发送注册消息邮件,再发送注册短信验证,每个过程消耗50毫秒,一共就需要150毫秒

图片

并行方式:

 

并行方式与串行方式不同的就是,在数据库记录完注册的信息之后,发送消息跟发送邮件的动作是同步完成,而不是根据上一个动作完成后再完成下一个动作,大大缩短了用户的等待时间,如下图:

图片

消息系统


 

消息系统负责将数据从一个应用程序传送到另一个应用程序,这样应用程序就可以把重心放在数据产生,但是不必担心 如何共享它。分布式消息系统基于我们上面提到的消息队列的概念。

 

 

 

 

消息系统的分类


 

消息系统主要分为两类:点对点,与订阅-发布

 

点对点:

 

主要采用的队列的方式进行消息传递,如我->你 ,我生产面包(消息队列)之后你进行消费,当你吃完了面包(消息队列的数据),那么队列的数据就会被消费,也就是删除掉,等于我出售的面包由你进行消费吃完。

 

发布-订阅:

 

主要有三大组件:

主题:一个消息的分类,假如有一类的消息全部都是订单,一类全部都是关于用户的,一类全部都是关于订单的。那么就根据这些创建不同的主题存放不同的东西。

发布者:将消息通过主动推送的方式推送给消息系统

订阅者:可以采用拉,推的方式从消息系统中获取数据

 

 

 

 

kafka的应用场景以及架构


 

apache kafka是一个分布式发布-订阅消息系统和一个强大的消息队列,使用scala语言编写是一个分布式,分区的,多副本的,多订阅者的日志系统,可以用于搜索日志,监控日志,访问日志等。

 

kafka架构图:

图片

 

Prodecers:生产者端,主要用于生产数据。之后把产生的数据保存到kafka集群。

Consumers:kafka集群的消费者,从集群中对生产者产生的数据进行拉取消费。

Connectors:这个组件可以将kafka的主题连接到现有的应用程序或产生数据的系统。

Stream processors:允许应用程序作为流处理器(stream processor),从一个或者多个主题获取输入流,并生产一个输出流到一个或 者多个主题,能够有效的变化输入流为输出流。

 

kafka一些术语

 

Broker:kafka集群中包含一个或者多个服务实例,这种服务实例被称为Broker

Topic:每条发布到kafka集群的消息都有一个类别,这个类别就叫做Topic

Partition:Partition是一个物理上的概念,每个Topic包含一个或者多个Partition (分区)

Producer:负责发布消息到kafka的Broker中。

Consumer:消息消费者,向kafka的broker中读取消息的客户端

Consumer Group:每一个Consumer属于一个特定的Consumer Group(可以为每个Consumer指定 groupName)

 

架构关系图


 

图片

流程介绍:Zookeeper是一个分布式的,开放源码的,用户分布式的协调服务,生产者push数据到集群,消费者通过pull进行拉取,但不管是生产者还是消费者的动作都需要zookeeper的管理。他的作用就是,生产者push数据到kafka集群,就必须要找到kafka集群的节点在哪里,这些都是通过zookeeper去寻找的。消费者消费哪一条数据,也需要zookeeper的支持,从zookeeper获得offset,offset记录上一次消费的数据消费到哪里,这样就可以接着下一条数据进行消费。

 

kafka Partition offset


 

offset是一个long类型数字,它唯一标识了一条消息,消费者通过(offset,partition,topic)跟踪记录。

任何发布到此partition的消息都会被直接追加到log文件的尾部,每条消息在文件中的位置称为offset(偏移量)。记录到上一次消费的位置,之后跟踪到下一次接着上一次消费的位置进行继续消费。保证了每次都从下一条开始消费,不会重复消费也不会丢失消费。

 

 

图片

 

kafka为什么那么快主要从下面4个方面进行理解:


 

1.kafka的储存设计方面

 

在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。每个partition(目录)被平均分配到多个大小相等segment(段)数据文件中。但每个段segment file消息数量不一定相等,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。每一个sgement又包含了index文件和log文件,可以快速定位数据,通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。

 

2.利用Page cache+mmap

 

page cache用于缓存文件的页数据,页是逻辑上的概念,因此page cache是与文件系统同级的;他的作用就是加速数据的IO,写数据的时候首先写入缓存,将写入的页进行标记为dirty,之后向外部存储flush;读数据的时候就先读取缓存,没有读取到再去外部存储读取。page cache中的每个文件都是一棵基数树,树的每个节点都是一个页。根据文件内的偏移量就可以快速定位到所在的页。

为什么kafka要使用page cache 进行储存管理

1,JVM中一切都是对象,数据的对象储存会浪费空间

2,使用JVM管理,会降低吞吐量

3,如果系统程序崩溃管理的数据就会丢失,造成严重后果

mmap即是Memory Mapped Files 内存文件映射,可以把物理上的磁盘文件跟page cache进行映射,让进程可以读写内存,有助于数据读写与磁盘的交互。

 

3.kafka的批量压缩设计

 

在大企业中,数据的流动是极快的,对于消息队列很多的情况下,系统要面临的问题就是不仅仅是磁盘的IO,更多的是网络的IO。所以消息的压缩对于kafka的性能来说就显得尤其重要。

Kafka 中,压缩可能发生在两个地方:生产者端和 Broker 端,kafka采用批量压缩的方式,而不是采用单个消息队列压缩。如果对每一个消息都进行压缩,压缩的效率就会大大降低。kafka支持很多种压缩方式,允许使用递归的消息集合。

 

4.kafka的消息读写过程

 

1.Producer根据zookeeper连接到或者的broker,从zookeeper节点找到该partition的leader

2.producer把需要发送的消息发给该leader,leader把消息写入到log,follows从leader拉取消息,写入到本地的log之后向leader发送ACK,leader收到后向producer发送ACK

生产者把经过批量压缩的数据发送给broker之后,beocker就通过函数映射压缩文件的地址到内存,之后就可以根据这个函数进行写入的操作,写入的时候会直接进入到PageCache,之后由os的线程异步刷新到磁盘,达到一次性能优化。

kafka在读取数据的时候,会判断数据是否存在于page cache,如果存在的话就会直接从page cache中消费,所以消费实时数据的速度就会快很多。

 

5.ZeroCopy

 

在linux中有两个上下文,分别是内核态跟用户态,我们将一个File读取并发送出去需要经历4次Copy:

 

1.调用read,将文件拷贝到了kernel内核态

2.CPU控制 kernel态的数据copy到用户态

3.调用write时,user态下的内容会copy到内核态的socket的buffer中

4.最后将内核态socket buffer的数据copy到网卡设备中传送

 

缺点就是增加了上下文切换、浪费了2次无效拷贝

 

ZeroCopy技术:

 

请求kernel直接把disk的data传输给socket,而不是通过应用程序传输。Zero copy大大提高了应用程序的性能,减少不必要的内核缓冲区跟用户缓冲区间的拷贝,从而减少CPU的开销和减少了kernel和user模式的上下文切换,达到性能的提升

 

对应零拷贝技术有mmap及sendfile:

1.mmap:小文件传输快

2.sendfile:大文件传输比mmap快

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值