消息队列之 MetaQ 和 Kafka 哪个更香!(4)

简介: 消息队列之 MetaQ 和 Kafka 哪个更香!

MetaQ和kafka的消息读写方式

零拷贝

我们知道,我们在写数据的时候并不是直接写入到磁盘中去的,而是写入到pageCache中去的,pageCache的主要作用是减少磁盘的I/O操作。

在磁盘写入的时候会写入到pageCache中去的,然后pageCache中可以将一些小的写入合并成一个大的写入,再进行异步刷盘。当然我们也可以使用fsync进行强制刷盘,强制刷盘会影响写入性能。一般为了保证消息的可靠性,我们是会采用多副本来存储消息,而不是采用同步刷盘。

读取消息的时候如果在pageCache中有命中则直接返回,如果在pageCache中无法命中则会产生缺页中断,需要从磁盘中加载数据到缓存中,然后返回数据。并且根据局部性原理,在读数据的时候也会进行预读,把该也相邻的磁盘快读入到页缓存中去。

mmap

由于我们读取数据的时候,需要将数据从磁盘拷贝到pageCache中,但是由于pageCache属于内核空间,用户空间无法访问,所以还需要将数据从内核空间拷贝到用户空间。        

image.png

所以数据需要两次拷贝应用程序才能够访问的到,我们可以通过mmap来减少数据从内核态到用户态的拷贝。通过将程序虚拟页面映射到页缓存中,这样就不需要将数据从内核态拷贝到用户态,也可以避免产生重复数据。也不必要再通过调用read和write方法对文件进行读写,而是通过映射地址和偏移量来直接操作pageCache。      

image.png      

sendfile

下面我们来看下常规的发送文件的过程中,从磁盘读取消息到发送文件的过程是怎么样的。

image.png

DMA Copy是指不需要CPU接入,可以直接读写系统内存,类似显卡、网卡和磁盘都是用到DMA,然而像上下文切换的话就需要有CPU接入。

下面我们看看如果采用mmap发送文件之后的流程是怎么样的。

image.png

可以看到上下文切换的次数没有变化,但是数据少拷贝了一份,这个和我们上面说到的mmap所能够达到的效果是一样的。

               image.png


上图中,sendfile采用一次系统调用就完成了发送数据的需求,相比于read+write或者说mmap+writ来

说上下文切换次数变少了,但是数据还是有冗余的。在linux2.4中采用 sendfile+带[分散-收集]DMA。真正实现了无冗余的功能。

image.png

上面就是我们说的零拷贝,在Java中是通过FileChannal.transferTo()调用的,底层是通过sendfile实现。

MetaQ和kafka的读写对比

目前kafka支持sendfile的消息读写方式,MetaQ支持mmap的消息读写方式,另外MetaQ还支持sendfile的消息写方式。

image.png

默认情况下,MetaQ不论是在CommitLog或者ComsumerQueue中都是采用mmap来实现消息读写的。在发送消息的时候,通常情况下会将数据拷贝到堆内存中去,然后再塞到响应体中进行发送。当然我们也可以通过参数配置不经过堆,通过mapedBuffer直接发送到SocketBuffer。

当消费消息的时候,严格来说对于CommitLog的读取是随机的,因为CommitLog的消息是混合进行存储的,但是从整体上面来看,消息还是会从CommitLog上顺序读取的,先读取旧数据,然后再读取新数据。消息存进去之后很快就会被消费,这个时候消息还是存放在pageCache中的,所以我们是不需要读取磁盘的。

image.png

同时pageCache会定时刷盘,但是刷盘的时机是不可控制的,所以会出现swap等现象。mmap也只是做了映射,如果真正去取数据的时候不在内存中,也会产生缺页中断,需要加载数据到内存中,这个时候也会有一些延时。MetaQ采用文件预分配和文件预热来解决pageCache的不确定性。

kafka的消息写入对于单分区来说是顺序写入的,由上文可知,kafka是有.index索引文件和.log数据文件构成的。其中.index索引文件是采用mmap进行读写的,这对于本地读写索引文件则可以提高读取效率,而.log数据文件则采用sendfile的零拷贝进行实现的。对于消息的写入来说,采用mmap其实并没有什么用,因为消息都是从网络中获取的,采用sendfile来发送消息比mmap+write更能提高效率,因为在内存中少了一个SocketBuffer的拷贝。

另外通过网上研究测试表明,如果读取的数据小于4kb的时候,使用mmap的性能效率比sendfile高,当读取数据大于4kb的时候,sendfile的效率比mmap高;对于写数据,如果写入的数据包小于64kb的时候,mmap的性能效率比sendfile高,当写入数据包大于64kb的时候sendfile的效率比mmap高。

由于kafka主要是用于日志传输,处理海量数据,对于数据的正确度要求不是很高,并且在发送消息的时候一般会进行消息的汇聚,然后批量发送消息,所以整体上来说kafka的读写数据量会比较大,这个时候使用sendfile能够获取更高的性能,而MetaQ主要是用来针对阿里的复杂应用场景,对于数据的可靠性、数据的实时性要求会比较高,由于对数据的实时性要求较高,一般不会进行汇聚批量发送消息,所以读写数据量不会很大,这个时候使用mmap可以获得更好的性能,当如果发现写入的数据量比较大时,也可以切换为sendfile进行写入。

目录
相关文章
|
2月前
|
消息中间件 传感器 缓存
为什么Kafka能秒杀众多消息队列?揭秘它背后的五大性能神器,让你秒懂Kafka的极速之道!
【8月更文挑战第24天】Apache Kafka作为分布式流处理平台的领先者,凭借其出色的性能和扩展能力广受好评。本文通过案例分析,深入探讨Kafka实现高性能的关键因素:分区与并行处理显著提升吞吐量;批量发送结合压缩算法减少网络I/O次数及数据量;顺序写盘与页缓存机制提高写入效率;Zero-Copy技术降低CPU消耗;集群扩展与负载均衡确保系统稳定性和可靠性。这些机制共同作用,使Kafka能够在处理大规模数据流时表现出色。
41 3
|
2月前
|
消息中间件 存储 Kafka
ZooKeeper助力Kafka:掌握这四大作用,让你的消息队列系统稳如老狗!
【8月更文挑战第24天】Kafka是一款高性能的分布式消息队列系统,其稳定运行很大程度上依赖于ZooKeeper提供的分布式协调服务。ZooKeeper在Kafka中承担了四大关键职责:集群管理(Broker的注册与选举)、主题与分区管理、领导者选举机制以及消费者组管理。通过具体的代码示例展示了这些功能的具体实现方式。
58 2
|
2月前
|
消息中间件 存储 Kafka
现代消息队列与云存储问题之Kafka在海量队列场景下存在性能的问题如何解决
现代消息队列与云存储问题之Kafka在海量队列场景下存在性能的问题如何解决
|
4月前
|
消息中间件 存储 Java
深度探索:使用Apache Kafka构建高效Java消息队列处理系统
【6月更文挑战第30天】Apache Kafka是分布式消息系统,用于高吞吐量的发布订阅。在Java中,开发者使用Kafka的客户端库创建生产者和消费者。生产者发送序列化消息到主题,消费者通过订阅和跟踪偏移量消费消息。Kafka以持久化、容灾和顺序写入优化I/O。Java示例代码展示了如何创建并发送/接收消息。通过分区、消费者组和压缩等策略,Kafka在高并发场景下可被优化。
107 1
|
4月前
|
消息中间件 Java Kafka
使用Spring Boot和Kafka实现高效消息队列
使用Spring Boot和Kafka实现高效消息队列
|
3月前
|
消息中间件 C语言 RocketMQ
消息队列 MQ操作报错合集之出现"Connection reset by peer"的错误,该如何处理
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
3月前
|
消息中间件 Java C语言
消息队列 MQ使用问题之在使用C++客户端和GBase的ESQL进行编译时出现core dump,该怎么办
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
21天前
|
消息中间件
手撸MQ消息队列——循环数组
队列是一种常用的数据结构,类似于栈,但采用先进先出(FIFO)的原则。生活中常见的排队场景就是队列的应用实例。在数据结构中,队列通常用数组实现,包括入队(队尾插入元素)和出队(队头移除元素)两种基本操作。本文介绍了如何用数组实现队列,包括定义数组长度、维护队头和队尾下标(front 和 tail),并通过取模运算解决下标越界问题。此外,还讨论了队列的空与满状态判断,以及并发和等待机制的实现。通过示例代码展示了队列的基本操作及优化方法,确保多线程环境下的正确性和高效性。
24 0
手撸MQ消息队列——循环数组
|
2月前
|
消息中间件 存储 缓存
一个用过消息队列的人,竟不知为何要用 MQ?
一个用过消息队列的人,竟不知为何要用 MQ?
91 1
|
3月前
|
消息中间件 开发工具 RocketMQ
消息队列 MQ使用问题之一直连接master失败,是什么原因
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。

热门文章

最新文章

下一篇
无影云桌面