Curve 块存储 IO 链路零拷贝
背景
Curve块存储IO链路零拷贝的实现
CurveBS实现零拷贝,使用RDMA技术从网卡将数据直接放入用户态内存,再使用brpc的IOBuf技术保证了在数据转移过程中的零拷贝,最后使用基于SPDK的PolarFS的DMA write接口,将用户态内存中的数据直接使用DMA技术落盘。这一过程,需要依赖对IOBuf中内存分配的精确控制,因为DMA接口对写buffer的内存对齐和len是有要求的。我们使用的nvme基于PRP,要使用的DMA writev接口,对iovec的内存必须满足:
iovec[0]的offset 4字节对齐,iovec[0]的末尾与page对齐; 后续的iovec项,要求整个page; 最后的iovec项,要求以page起点开始,并且以整4字节长度对齐结束;
Curve块存储的ChunkServer端IO路径
1、Leader的日志落盘路径
起点是brpc层接收到client的写请求之后,到达chunk service层,写请求的数据可以分为两部分,分别是ChunkRequest和cntl_->request_attachment(); 在ChunkOpRequest将ChunkRequest和attachment部分,打包成raft log,提交raft node,其中核心的Encode部分代码如下:
Encode的逻辑:首先添加一个4个字节的metasize字段,然后序列化ChunkRequest,之后将attachment拼接到最后;
raft log在raft log manager中最终交给CurveSegment调用
落盘逻辑:首先调用posix_memalign分配4k 对齐的内存空间,之后将entry→id.term、 meta_field、data.length、real_length、data_check_sum等元数据打包在write_buf的头部,然后将先前的raft log拷贝到write_buf,最后调用_lfs->write落盘;
raft log meta
metasize +序列化后的ChunkRequest
attachment即数据部分
3、Follower的日志落盘路径
Follower端收到的attachment即上一节中Encode部分的日志
raft service将attachment取出后,调用logmanage中的CurveSegment::append(const braft::LogEntry* entry)执行日志落盘,这部分逻辑与leader日志落盘基本一致。
Follower端的数据落盘路径,首先会从raft service收到的raft log中Decode出ChunkRequest和data,这个data就是Leader收到的attachment相同的数据,这部分逻辑基本上是从IObuf中切割出ChunkRequest的过程;
之后,将调用datastrore层的WriteChunk,这部分与Leader一致;
实现零拷贝
第一项是raft log meta + 部分padding;如图第一部分padding长度为2K-50B 第二项是部分padding + (meta+chunkrequest) + attachment的iovec[0],一共是一个完整的4k block, 这部分的padding长度是2K-100B
Follower的日志落盘:与leader日志落盘基本是上一样的,唯一的区别是上述(2)中的meta+chunkrequest和 attachment的iovec[0]从follower收到rpc时就是一整块内存,在第(3)步重组iovec时,稍微有所区别。
Leader的数据落盘:leader需要落盘的数据,就是rpc中收到的attachment,前面我们说到,在rpc接收时,我们已经做到了attachment的满足DMA write的内存对齐条件。
Follower的数据落盘:follower端收到的attachment包含meta+chunkrequest和 leader的attachment数据,这里的区别就是一个从attachment切割下meta+chunkrequest的过程,我们只要保证meta+chunkrequest的长度能被4整除,那么剩余的需要落盘的数据部分,自然能保证4字节对齐的约束,因此也没有问题。
总结
本文介绍了CurveBS在基于RDMA技术的brpc进行网络传输,以及基于SPDK技术的PolarFS文件的系统作为底层存储引擎访问nvme磁盘的场景下,通过对CurveBS的IO链路进行分析,规划好IO链路上的数据搬移,尽可能减少数据的拷贝,使得CPU只参与控制逻辑,从而减少了CPU的占用,实现了零拷贝。
关于 Curve
Curve 是一款高性能、易运维、云原生的开源分布式存储系统。可应用于主流的云原生基础设施平台:对接 OpenStack 平台为云主机提供高性能块存储服务;对接 Kubernetes 为其提供 RWO、RWX 等类型的持久化存储卷;对接 PolarFS 作为云原生数据库的高性能存储底座,完美支持云原生数据库的存算分离架构。Curve 亦可作为云存储中间件使用 S3 兼容的对象存储作为数据存储引擎,为公有云用户提供高性价比的共享文件存储。
- GitHub:https://github.com/opencurve/curve- 官网:https://opencurve.io/- 用户论坛:https://ask.opencurve.io/- 微信群:搜索群助手微信号 OpenCurve_bot