kafka 为什么快

批量发送接收

  1. kafka,一次发送多条消息,微批处理。
  2. 生产者发送消息,需要2次rpc
    1. 发送消息
    2. broker返回ACK信号,表示已经接收消息
  3. 消费者消费消息,3次rpc
    1. 消费者请求接收消息
    2. broker返回消息
    3. 消费者返回ACK信号,表示已经消费

客户端优化

  1. 新版客户端摒弃单线程,采用双线程模式 主线程+Sender线程
  2. 主线程负责将消息置入客户端缓存(缓存会将多个消息聚合为1个批次)
  3. Sender线程将缓存中聚合好的批次消息发送到Broker

优良的日志消息格式

  1. 0.11.0版本开始日志消息格式
  2. 引用了变长字段Varints和ZigZag编码,有效降低了附加字段占用的空间,降低了网络传输、日志存盘占用开销。

数据压缩机制

支持多种消息压缩方式(gzip、snappy、lz4)。对消息进行压缩可以极大地减少网络传输 量、降低网络I/O,从而提高整体的性能。消息压缩是一种使用时间换空间的优化方式,如果对时间延有一定的要求,则不推荐对消息进行压缩。

Partition机制

对消息进行分区,提高了数据生产与消费的并行度,有效的提升了数据的吞吐量

索引 快速检索

为每个日志分段文件提供了2个索引文件(偏移量索引文件.index、时间戳索引文件.timeindex),提高了消息的查询效率

顺序写盘

  1. 操作系统可以针对线性读写做深层次的优化,比如预读(read-ahead,提前将一个比较大的磁盘块 读入内存) 和后写(write-behind,将很多小的逻辑写操作合并起来组成一个大的物理写操作)技术
  2. 文件追加的方式来写入消息,只能在日志文件的尾部追加新的消息,并且也不允许修改已写入的消息
  3. 寻址 磁盘疯狂转动

页缓存

  1. Memory Mapped Files
  2. 简称:mmap,将磁盘文件映射到内存, 用户通过修改内存就能修改磁盘文件。
  3. 它的工作原理是直接利用操作系统的Page来实现磁盘文件到物理内存的直接映射。完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。
  4. 通过mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存)。使用这种方式可以获取很大的 I/O提升,省去了用户空间到内核空间复制的开销

问题

  1. 不可靠,写到mmap中的数据并没有被真正的写到硬盘
  2. 操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘

读流程

  1. 操作系统会先查看待读取的数据所在的页 (page)是否在页缓存(pagecache)中,如果存在(命中)则直接返回数据,从而避免了对物理磁盘的 I/O 操作
  2. 如果没有命中,则操作系统会向磁盘发起读取请求并将读取的数据页存入页缓存,之后再将数据返回给进程。

写流程

  1. 操作系统也会检测数据对应的页是否在页缓存中,如果不存在,则会先在页缓存中添加相应的页最后将数据写入对应的页。
  2. 被修改过后的页也就变成了脏页,操作系统会在合适的时间把脏页中的数据写入磁盘,以保持数据的一致性。

kafka应用

  1. Kafka提供了一个参数 producer.type 来控制是不是主动flush
  2. 如果Kafka写入到mmap之后就立即flush然后再返回Producer叫同步(sync)
  3. 写入mmap之后立即返回Producer不调用flush叫异步(async)

  1. 大量使用了页缓存,这是 Kafka 实现高吞吐的重要因素之一。
  2. 减少对磁盘 I/O 的操作(具体来说,就是把磁盘中的数据缓存到内存中,把对磁盘的访问变为对内 存的访问)
  3. 维护页缓存和文件之间的一致性交由操作系统来负责,比进程内维护更加安全有效

零拷贝

传统

先读取、再发送,实际经过1~4四次copy

实际IO读写,需要进行IO中断,需要CPU响应中断(内核态到用户态转换),尽管引入DMA(DirectMemory Access,直接存储器访问)来接管CPU的中断请求,但四次copy是存在“不必要的拷贝”的

实际上并不需要第二个和第三个数据副本。数据可以直接从读缓冲区传输到套接字缓冲区。

零拷贝

两个过程

数据落盘通常都是非实时的,Kafka的数据并不是实时的写入硬盘,它充分利用了操作系统分页存储来利用内存提高I/O效率

  1. 网络数据持久化到磁盘 (Producer 到 Broker)
  2. 磁盘文件通过网络发送(Broker 到 Consumer)
  1. 磁盘数据通过DMA(Direct Memory Access,直接存储器访问)拷贝到内核态 Buffer
  2. 直接通过 DMA 拷贝到 NIC Buffer(socket buffer),无需 CPU 拷贝
  3. 除了减少数据拷贝外,整个读文件 ==> 网络发送由一个 sendfile 调用完成,整个过程只有两次上 下文切换,因此大大提高了性能

4. Java NIO

对sendfile的支持就是FileChannel.transferTo()/transferFrom()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值