kafka服务器性能要求,Kafka性能测试及分析

Kafka 简介

Kafka 是一种基于 Zookeeper 协调的分布式消息系统,使用 Scala 编写。其主要设计目标如下:

以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 TB 级以上数据也能保证常数时间复杂度的访问性能。

高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒 100K 条以上消息的传输。

支持 Kafka Server 间的消息分区,及分布式消费,同时保证每个 Partition 内的消息顺序传输。

同时支持离线数据处理和实时数据处理。

Scale out:支持在线水平扩展。

基础概念

Broker

Kafka 集群中每一台服务器被称为一个 Broker。

Topic

一类消息,每条消息发布到Kafka都会隶属于一个 Topic。

Partition

物理上把 Topic 分成一个或多个 Partition,每个 Partition 在物理上对应一个文件夹,文件夹名为 Topic 名称 + Partition Index(例如:test_topic-0),该文件夹下存储这个 Partition 的所有消息和索引文件,每个 Partition 里面存储的消息是有序的。

Segment

一个 Partition 物理上由多个 Segment 组成,每个 Partition 里面的消息会被分配到多个大小相等的 Segment 数据文件中,但由于消息的大小不等,所以每个 Segment 里面的消息总数不一定相等。

Producer

消息生产者,负责发布消息到 Kafka。

Consumer

消息消费者,向 Kafka 读取并消费消息。

Consumer Group

每个 Consumer 属于一个特定的 Consumer Group,每条消息只能被 Consumer Group 中的 Consumer 一个消费,但是可以被多个 Consumer Group 消费。

Kafka的性能究竟有多好

Kafka给人们影响最深刻的应该就是快了,出奇的快,据 LinkedIn 统计,最新的数据是每天利用 Kafka 处理的消息超过1万亿条,在峰值时每秒钟会发布超过百万条消息,就算是在内存和 CPU 都不高的情况下,Kafka 的速度最高可以达到每秒十万条数据,并且还能持久化存储。

首先我们来验证一下这个数据是否属实,有没有水分,测试工具使用官方提供的 kafka-producer-perf-test.sh,测试单台服务器在发送5千万条大小为1KB的消息时性能如何。

服务器

CPU:2.3 GHz Intel Core i5

内存:8 GB 2133 MHz LPDDR3

硬盘:128GB PCIe SSD

JDK:1.8

Kafka主要配置

Broker:1台

num.network.threads(用于接收并处理网络请求的线程数):3

num.io.threads(用于接收并处理磁盘IO的线程数 ):8

num.partitions(每个 Topic 下面的 Partition 数量,直接影响 Kafka 集群的吞吐性能,理论上 Partition 越多吞吐量越大,但相应的延迟和内存开销越大,并且高可用性降低):3

其他配置均使用默认值

性能测试命令

kafka-producer-perf-test --producer-props bootstrap.servers=localhost:9092 --topic Test --throughput 1000000 --record-size 1024 --num-records 50000000

--producer-props bootstrap.servers:Kafka 的服务器地址及端口

--topic:发送的消息所属类别

--throughput:最大信息吞吐量,单位为 messages/sec,数值越小消息延迟越小

--record-size:每条消息的大小,单位为 bytes

--num-records:要发送的消息条数

测试结果

50000000 records sent, 143633.997593 records/sec (140.27 MB/sec), 213.37 ms avg latency, 574.00 ms max latency, 209 ms 50th, 269 ms 95th, 317 ms 99th, 449 ms 99.9th.

64a4ed516f52

性能测试

在后台跑着许多程序的情况下,Kafka 依然跑出了平均每秒发送14万+条的吞吐量,可见 Kafka 的性能确实非常优秀。

Kafka的性能为什么这么好

1.顺序读写

Kafka的消息是不断追加到文件中的,这个特性使它可以充分利用磁盘的顺序读写能力。顺序读写降低了硬盘磁头的寻道时间,只需要很少的扇区旋转时间,所以速度远快于随机读写。Kafka官方给出的测试数据(Raid-5, 7200rpm),顺序I/O: 600MB/s,随机I/O: 100KB/s。

2.批量发送

即使顺序读写,过于频繁的大量小I/O操作一样会造成磁盘的瓶颈,所以 Kafka 在此处的处理是先将消息缓存在内存中,然后一次请求批量发送出去,比如可以指定缓存的消息到某个量的时候发送,或者缓存了固定的时间后发送这种策略大大减少了服务器端的I/O次数。

3.文件分段

前文介绍了 Kafka 的队列 Topic 被分为了多个区 Partition,每个 Partition 又分为了多个 Segment,所以一个队列中的消息实际上是保存在N多个片段文件中,通过分段的方式,每次文件操作都是对一个小文件的操作,非常轻便,同时也增加了并行处理能力。

4.零拷贝(Zero-Copy)

首先介绍一下传统的网络I/O操作流程,从一个文件中读出数据并将数据传输到网络上的另一程序,其操作包含两个核心调用:

File.read(fileDesc, buf, len);

Socket.send(socket, buf, len);

看上去好像挺简单的,但实际上从系统层面它做了以下4步操作:

64a4ed516f52

传统数据拷贝

其中:

1.read() 调用引发了一次从用户模式到内核模式的上下文切换。在内部,发出 sys_read()(或等效内容)以从文件中读取数据。直接内存存取(direct memory access,DMA)引擎执行了第一次拷贝,它从磁盘中读取文件内容,然后将它们存储到一个内核地址空间缓存区中。

2.所需的数据被从读取缓冲区拷贝到用户缓冲区,read() 调用返回。该调用的返回引发了内核模式到用户模式的上下文切换(又一次上下文切换)。现在数据被储存在用户地址空间缓冲区。

3.send() 套接字调用引发了从用户模式到内核模式的上下文切换。数据被第三次拷贝,并被再次放置在内核地址空间缓冲区。但是这一次放置的缓冲区不同,该缓冲区与目标套接字相关联。

4.send() 系统调用返回,结果导致了第四次的上下文切换。DMA 引擎将数据从内核缓冲区传到协议引擎,第四次拷贝独立地、异步地发生 。

整个过程共经历四次上下文切换,四次拷贝,其中2、3两步没有必要,应用程序只是起到缓存数据并将其传回到套接字的作用而以,别无他用。而零拷贝正是通过消除这些冗余的数据拷贝而提高性能的,零拷贝的一个核心调用变化就是将之前的 file.read() 和 socket.send() 方法替换成 transferTo() 方法:

transferTo(position, count, writableChannel);

transferTo() 方法将数据从文件通道传输到了给定的可写字节通道。在内部,它依赖底层操作系统对零拷贝的支持,在 UNIX 和各种 Linux 系统中,此调用被传递到 sendfile() 系统调用中,而此时系统操作变成了以下3步:

64a4ed516f52

零拷贝

通过 transferTo() 方法,我们将上下文切换的次数从四次减少到了两次,将数据复制的次数从四次减少到了三次(其中只有一次涉及到了 CPU),不过这好像并未达到零拷贝的要求,在 Linux 内核 2.4 及后期版本中,套接字缓冲区描述符做了相应调整,使得 DMA 引擎可以直接把数据从内核缓冲区传输到协议引擎,从而消除了剩下的最后一次 CPU 拷贝,达到真正意义上的零拷贝。

5.使用OS层面的PageCache

Kafka 重度依赖底层操作系统提供的 PageCache 功能。当上层有写操作时,操作系统只是将数据写入 PageCache,同时标记 Page 属性为 Dirty。当读操作发生时,先从 PageCache 中查找,如果发生缺页才进行磁盘调度,最终返回需要的数据。实际上 PageCache 是把尽可能多的空闲内存都当做了磁盘缓存来使用。同时如果有其他进程申请内存,回收 PageCache 的代价又很小,所以现代的OS都支持 PageCache。

使用 PageCache 功能同时可以避免在 JVM 内部缓存数据,JVM 为我们提供了强大的 GC 能力,同时也引入了一些问题不适用于 Kafka 的设计。

如果在 Heap 内管理缓存,JVM 的 GC 线程会频繁扫描 Heap 空间,带来不必要的开销。如果 Heap 过大,执行一次 Full GC 对系统的可用性来说将是极大的挑战。

所有在 JVM 内的对象都不免带有一个 Object Overhead (千万不可小视),内存的有效空间利用率会因此降低。

所有的 In-Process Cache 在OS中都有一份同样的 PageCache。所以通过将缓存只放在 PageCache,可以至少让可用缓存空间翻倍。

如果 Kafka 重启,所有的 In-Process Cache 都会失效,而OS管理的 PageCache 依然可以继续使用。

总结

通过以上测试和分析我们得出,Kafka 的确是个性能十分出色的消息队列,但是评估一个消息队列是否适用并不能仅仅看性能,还需考量其可靠性、是否支持扩展以及是否支持事物等,再根据实际的业务场景做出相应取舍,下面附上各大MQ的功能对比。

MQ

RabbitMQ

ActiveMQ

ZeroMQ

Redis

Kafka

语言

Erlang

Java

C/C++

C

scala

支持协议

AMQP STOMP (STOMP 1.0, STOMP 1.1 and STOMP 1.2)MQTTHTTP(有三种方式)

AMQPMQTTOpenWireSTOMP

zmq_ipc(本地进程间通信)基于Socket的通信协议:TCP、INROC 、IPC 、PGM

自定义redis协议

自定义

持久化策略

本地磁盘文件

AMQ(磁盘文件)、KahaDB(本地数据库)、JDBC、LevelDB(本地数据库)

不支持持久化

支持磁盘持久化

磁盘持久化

消息确认机制

有消息确认机制

AUTO_ACKNOWLEDGE = 1 自动确认CLIENT_ACKNOWLEDGE = 2 客户端手动确认 DUPS_OK_ACKNOWLEDGE = 3 自动批量确认SESSION_TRANSACTED = 0 事务提交并确认自定义的ACK_MODE:INDIVIDUAL_ACKNOWLEDGE = 4 单条消息确认

无,更像NIO模式下的非阻塞事件模式

有消息确认机制

批处理

支持批量发送消息

支持批量发送消息

支持

支持

支持

消息处理模式(push-pull)

push

同时支持Push-pull

请求响应模式(同步)发布订阅模式(异步)单向管道模型

非严格意义push-pull

Pull

消息顺序性

单个消费者有序

单个消费者有序

有序

Topic单个partition内有序

支持事务

支持

支持

支持

集群策略

主从模式支持自动选主

1、消费者集群2、Broker集群(共享队列)3、主从模式(共享DB、KahaDB复制、共享文件系统)

主从

zookeeper分布式多节点

容灾

主从、镜像队列

共享存储ZooKeeper协调

主从或codis

分区副本

负载均衡

Rabbitmq-cluster或LVS或HAproxy

Broker-Cluster(共享队列)

LVS或codis

通过zookeeper调度topic分区

管理界面

rabbitmqadmin

ActiveMQ Web Console

Redis-cli或redisLive

kafka-run-class.sh

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值