首页  

Kafka 和 RocketMQ 底层存储简单比较     所属分类 kafka 浏览量 1132
顺序读写 
页缓存 数据写入页缓存 脏页 
操作系统在合适的时候将脏页写入磁盘中 
小的写入操作合并成大的写入,再刷盘

读取 页缓存命中则直接返回 
页缓存 miss 则产生缺页中断,从磁盘加载数据至页缓存中,然后返回数据

预读  局部性原理 把相邻的磁盘块读入页缓存中

顺序写盘的速度比随机写内存要快

数据丢失 断电 未刷盘的脏页数据丢失
可以调用 fsync 强制刷盘  ,但性能损耗大

一般建议通过多副本机制来保证消息的可靠,而不是同步刷盘。

采用文件追加的方式来写入消息

mmap-文件内存映射 ,避免拷贝  
避免内核空间页缓存到用户空间的拷贝


文件映射
将程序虚拟页面直接映射到页缓存上,不需要从内核态往用户态拷贝数据
不用调用read或write方法对文件进行读写,可通过映射地址加偏移量的方式直接操作

sendfile-零拷贝

一般发送文件的流程
磁盘  页缓存(内核空间) 缓冲区(用户空间) socketbuffer(内核空间)  网卡

DMA  Direct Memory Access ,独立直接读写系统内存,不需要 CPU 介入,显卡、网卡之类都会用DMA


Linux2.1 sendfile
页缓存(内核空间) socketbuffer(内核空间) 网卡

Linux2.4  sendfile 
sendfile  +  分散-收集(Scatter-gather)DMA
 
Java里的 sendfile 
FileChannal.transferTo()  


RocketMQ CommitLog 所有的消息顺序追加写入 CommitLog ,并建立消息对应的 CosumerQueue , 消费者通过 CosumerQueue 得到消息的真实物理地址再去 CommitLog 获取消息。 可将 CosumerQueue 理解为消息的索引 CommitLog 和 CosumerQueue 都使用 mmap 发消息的时候默认将数据拷贝到堆内存中,然后再发送 this.fileChannel = new RandomAccessFile(this.file,"rw").getChannel(); this.mappedByteBuffer = this.fileChannel.map(MapMode.READ_WRITE,0,fileSize); 顺序写盘,整体来看是顺序读盘,使用 mmap,不是真正的零拷贝 文件预先分配和文件预热即每页写入一个0字节,然后再调用mlock 和 madvise(MADV_WILLNEED) CommitLog 大小默认1G 后台线程 AllocateMappedFileService mlock 将进程使用的部分或者全部的地址空间锁定在物理内存中,防止其被交换到swap空间 madvise 给操作系统建议,说明文件在不久的将来要访问,可以提前读几页
Kafka 一个分区一个文件夹 日志文件没有用 mmap,索引文件用了 mmap 发消息 用 零拷贝 FileChannel.transferTo sendfile vs mmap+write sendfile少了一次页缓存到 SocketBuffer 的拷贝 vm.swappiness 建议 设置为1
RocketMQ VS Kafka 都是顺序写入,不过 RocketMQ 把消息都存一个文件中,而 Kafka 是一个分区一个文件 每个分区一个文件在迁移或者数据复制更加灵活 但是分区多了 会变成 随机读写 发送消息 RocketMQ mmap + write ,通过预热来减少大文件 mmap 因为缺页中断产生的性能问题 Kafka sendfile,发送效率更高,少了一次页缓存到 SocketBuffer 的拷贝
RocketMQ Kafka 简单比较 rocketmq知识点 kafka核心知识点

上一篇     下一篇
Redis内部存储结构

kafka-topics.sh 无法获取topic列表及topic信息

kafka之broker-list bootstrap-server 和 zookeeper

kafka发送端核心参数说明

kafka消息发送机制

Kafka中的分区分配