kafka原理解析之-高性能内幕

2 篇文章 0 订阅
1 篇文章 0 订阅

一、日志持久化设计

1. partition的持久化队列结构:数据按先后顺序依次追加在文件末尾,读写操作分开,如下图所示。

在这里插入图片描述

这种结构有如下优势:

  • 所有的操作复杂度都是O(1),读操作不会阻塞写操作,读操作之间也不会互相影响。
  • 由于性能和数据大小完全分离开来——服务器现在可以充分利用大量廉价、低转速的1+TB
    SATA硬盘,通过顺序写的方式追加数据。虽然这些硬盘的寻址性能很差,但他们在大规模读写方面的性能是可以接受的

注:使用6个7200rpm、SATA接口、RAID-5的磁盘阵列在JBOD配置下的顺序写入的性能约为600MB/秒,但随机写入的性能仅约为100k/秒,相差6000倍以上。

2. 利用操作系统pagecache:现代操作系统都提供了 read-ahead 和 write-behind 技术,

  • read-ahead: 是以大的 data block 为单位预先读取数据到pagecache,如果磁盘使用更倾向于顺序读取,那么read-ahead可以有效的使用每次从磁盘中读取到的有用数据预先填充 cache 。
  • write-behind:是将多个小型的逻辑写入pagecache,然后合并成一次大型的物理磁盘写入。
  • kafka所有数据一开始就被写入到文件系统的持久化日志中,而不用在in-process cache空间不足的时候 flush 到磁盘。实际上,数据被直接插入到了内核的 pagecache 中。

二、 网络传输设计

1. 大量小型I/O操作优化

小型的 I/O 操作发生在客户端和服务端之间以及服务端自身的持久化操作中,为了避免这种情况,网络请求将多个消息打包成一组,而不是每次发送一条消息,从而使整组消息分担网络中往返的开销。

  • Consumer :每个请求都在 log 中指定了对应的 offset,并接收从该位置开始的一大块数,每次获取多个大型有序的消息块。
  • Provider: kafka 生产者会尝试在内存中汇总数据,并用一次请求批次提交信息。 批处理,可以配置指定的消息数量,也可以指定等待特定的延迟时间(如64k 或10ms),这允许汇总更多的数据后再发送,在服务器端也会减少更多的IO操作。

这个简单的优化对速度有着数量级的提升。批处理允许更大的网络数据包,更大的顺序读写磁盘操作,连续的内存块等等,所有这些都使 KafKa
将随机流消息顺序写入到磁盘, 再由 consumers 进行消费。

2. 文件拷贝优化

文件拷贝主要发生在consumer消费数据时需要从磁盘读取数据并通过网络发送给consumer。 存在两种拷贝方式:

  • 传统拷贝流程:磁盘 -> pageCache -> processCache -> socketBuffer -> nicBuffer,有四次 copy 操作和两次系统调用.
  • zero-copy流程:磁盘 -> pageCache -> nicBuffer,一次系统调用。

对比以上两种方式可以看出,传统方式有四次 copy 操作和两次系统调用, 而zero-copy只拷贝2次。

普遍的应用场景:一个 topic 被多消费者消费。使用 zero-copy(零拷贝),数据只会被复制到 pagecache中一次,节省了每次拷贝到用户空间内存中,再从用户空间进行读取的消耗,同时pagecache和zero-copy的组合使用意味着,在一个kafka集群中,大多数consumer 消费时,将看不到磁盘上的读取活动,因为数据将完全由缓存提供。 这使得消息能够以接近网络连接速度的上限进行消费

使用zero-copy方式有一个重要前提:从磁盘读出的数据块不用修改就可以直接传递,为了满足这个条件:

  • producer ,broker和 consumer都共享标准化的二进制消息格式,
  • broker维护消息日志文件,每个文件由一系列以相同格式写入到磁盘的消息集合组成,这种写入的消息格式被producer 和 consumer 共用(消息格式后面会详细介绍)。

3. 端到端消息批量压缩

在某些情况下,数据传输的瓶颈不是 CPU ,也不是磁盘,而是网络带宽。用户可以一次一个的压缩消息。但是这样会造成非常差的压缩比和消息重复类型的冗余,比如 JSON中的字段名称或 Web日志中的用户代理或公共字符串值。高性能的压缩是一次压缩多个消息,而不是压缩单个消息。

Kafka以高效的批处理格式(RecordBatch)支持一批消息可以压缩在一起发送到服务器。这批消息将以压缩格式写入,并且在日志中保持压缩,只会在consumer消费时解压缩。

Kafka 支持 GZIP,Snappy 和 LZ4 压缩协议

4. NIO多路复用技术

同步非阻塞的接收producer推送的消息:一个单独的接受线程和 N 个处理线程,每个线程处理固定数量的连接

三、消费端设计

1. 批量拉取数据: 批量拉取的好处在网络优化已经说明,不再介绍。

2. pull-based

broker起到蓄水池的作用,调节consumer、producer处理速率不一致的问题。

  • 当 consumer 速率落后于 producer 时,broker起到蓄水池的作用,consumer可以在适当的时间赶上来;
  • producer可以大批量生产要发送给 consumer 的数据;

3. offset位置(跟踪)

  • Kafka的 topic 被分割成了一组完全有序的 partition,其中每一个 partition 在任意给定的时间内只能被每个订阅了这个 topic 的 consumer 组中的一个 consumer 消费。这意味着 partition 中 每一个 consumer 的位置仅仅是一个数字,即下一条要消费的消息的offset。这使得被消费的消息的状态信息相当少,每个 partition 只需要一个数字。这个状态信息consumer提交给broker的

  • 这种方式还有一个附加的好处。consumer 可以回退到之前的 offset 来再次消费之前的数据。 例如,如果 consumer 的代码有 bug,并且在 bug 被发现前已经有一部分数据被消费了, 那么 consumer 可以在 bug 修复后通过回退到之前的 offset 来再次消费这些数据。

四、生产端设计

1. Load balancing

  • 不会经过多余节点发送数据
    生产者直接发送数据到主分区的服务器上,不需要经过任何中间路由。
    所有的 kafka 服务器节点都能响应这样的元数据请求: 哪些broker是活着的,topic的哪些分区是主分区,分配在哪个broker上,这样生产者就能适当地直接发送它的请求到服务器上。
  • 客户端控制消息发送数据到哪个分区
    随机的负载均衡或者使用一些特定语义的分区函数kafka提供特定分区的接口让用于根据指定的键值进行hash分区(当然也有选项可以重写分区函数), 例如,如果使用用户ID作为key,则用户相关的所有数据都会被分发到同一个分区上。这允许消费 者在消费数据时做一些特定的本地化处理。这样的分区风格经常被设计用于一些本地处理比较敏感的消费 者。

2. Asynchronous send

批处理是提升性能的一个主要驱动,为了允许批量处理,kafka 生产者会尝试在内存中汇总数据,并用一次请求批次提交信息。 批处理,不仅仅可以配置指定的消息数量,也可以指定等待特定的延迟时间(如64k 或10ms),这允许汇总更多的数据后再发送,在服务器端也会减少更多的IO操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一章 需求 对方的网页文件接入到我方服务器。每个文件要知道其:网站、采集时间等。 通过消息队列将多个远程服务器上的【数据文件】源源不断的接入到本地服务器,数据文件是下载下来的网页,传输过来的时候还要带上来自的网站和下载日期等信息。 目前讨论消息队列用Kafka。 第二章 基本方案 1、我现在能想到的就是: 远程服务器编写程序, 不停读取文件的内容成为一个字符串,然后再加上来自的网站、下载日期等信息,组合成一个JSON字符串,通过调用kafka的生产者API将字符串写入Kafka。 2、JSON数据格式设计: { “source”: “来源网站名” , “filename” : “html文件名”, “download-date”: “下载日期” , ”content” : “一个html文件的全部字符串 “ } 注:假设.js \.css \.png文件都不需要 3、消息主题的设计: 一个网站对应一个topic,对应到本地的一个文件夹。 4、其他: 如果只是传输文件,不考虑加上网站、下载日期等信息的话,我知道的用Flume可能更方便,但是要加上网站、下载日期的信息(类似主题订阅的功能),flume就不太方便了? 5、可能存在的顾虑:网页数据文件对数据顺序性的要求的程度。 Kafka单分区的情况小支持消息有序性, 多分区下确保消息有序的方案还需深入调研。 如果之后一个主题下对应的网页文件没有特别的传输顺序要求,这一块应该会容易处理很多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值