我们都知道,kafka是依赖于文件系统来保存和缓冲消息的。在其他消息队列RabbitMQ中,使用的是内存作为默认的存储介质,而磁盘作为备选介质,以此来实现高吞吐和低延迟的效果;redis则是完全依赖于内存实现的。那为什么kafka采用这种持久化的形式还能提供如此有竞争力的性能呢?

一、kafka对写操作的优化

首先kafka在同一个topic partition中的数据是有序的 ,kafka设计的时候,就只支持在文件末尾进行追加,而不支持修改操作,属于典型的顺序写入操作,操作系统对顺序读写坐了深层次的优化----预读和后写(将一个大的磁盘块读入内存,将很多小逻辑的写操作在内存中完成后,一次性将这一块数据写入磁盘中)。有相关研究表明,对磁盘的顺序写入速度远远大于对磁盘的随机写入,甚至还快过了对内存的随机写入。

二、kafka对读操作的优化

kafka在读取的时候使用了零拷贝技术,降低对文件的拷贝次数,一定程度上提升了速度。

三、kafka大量使用了页缓存

前面对读写操作的优化,使得kafka能承载吞吐量也不容小视,但这并不是kafka在全局性能上具备竞争力的全部因素。接下来将介绍的是页缓存,kafka是如何借助操作系统的帮助提升性能的。

页缓存是操作系统对数据文件的读写提供的一种缓冲技术,目的是为了减少I/O操作的次数。
当进程读取某个文件的时候,操作系统会先查看待读取的数据所在的页是否在页缓存中,如果在则直接返回给进程,如果不在则从磁盘读取后先写入页缓存,然后再将数据返回给进程。
当进程写入某个文件的时候,操作系统也会查看需要操作的页是否在页缓存中,如果存在则进行写入,如果不在则从磁盘中读取后再进行相关写入操作,被修改后的页,操作系统会在合适的时间内刷入磁盘来保证数据的一致性。

kafka大量使用页缓存,这也是kafka实现高性能的原因之一。 对于一个进程来说,他会在进程内部缓存所需要的数据,然而这些数据很有可能也缓存在操作系统的页缓存中,也就是这一部分数据被缓存了两次。就算kafka服务重启,页缓存内的数据也还是存在,但进程内的数据则需要重新加载。这也在一定程度上能简化代码,而且维护页缓存和文件的一致性问题交给操作系统完成会比进程内维护要更加的安全、高效。

虽然kafka的消息加载到页缓存中后,由操作系统择机刷入磁盘,但是kafka也还是提供了同步刷盘和间断性强制刷盘的功能,这些功能可以通过控制参数来实现。同步刷盘确实可以实现数据的可靠性,但是并不建议这样做,提高消息的可靠性应该由副本机制来实现,而不是由严重损耗性能的同步刷盘来实现。

Logo

Kafka开源项目指南提供详尽教程,助开发者掌握其架构、配置和使用,实现高效数据流管理和实时处理。它高性能、可扩展,适合日志收集和实时数据处理,通过持久化保障数据安全,是企业大数据生态系统的核心。

更多推荐