IO Pipeline 不算什么新鲜事儿,通过 io.Reader io.Writer 等接口,把多个流处理连接一起,只需返回 Reader, 直到调用 Read 函数时才读数据,高效节约内存。类比 Spark 流处理,transformation 时只是传递 RDD, 只有 Action 时才会触发数据计算。,,举一个从 http 读取 json 数据的例子:,我们不需要 ioutil.ReadAll 全部 body 再调用 Unmarshal, decoder 内置 buffer 流式解析即可。但是这个例子不完美,有很多问题,上面是改进后的版本,看着舒服多了,这还只是一个 reader 的实现。在 minio 中,经常有 N 多个 io.Reader 或者 io.Writer 组合在一起,实现 io pipeline, 稍复杂一些,略去错误处理,只看 getObjectHandler 主干代码,getObjectNInfo 调用后端具体实现,返回 GetObjectReader gr, 从 gr 中读取数据写回 http Writer …,gr 实现有很多种,minio 支持 NAS,FS, EC 多种模式,可以从文件系统中读数据,可以从 remote http 中读取,1. FS 本地文件系统下载数据,GetObjectNInfo 定义在 fs-v1.go, 原理比较简单, 根据 header 获取要读取文件的 offset, length 组装后返回 objReaderFn,NewGetObjectReader 代码会处理压缩或者加密的场景,内部还会构建 reader. fsOpenFile 打开文件后,还要封装一层 io.LimitReader 获取指定长度的数据,switch 分支会处理 isCompressed, isEncrypted, default 三种场景,区别是需要重新计算文件的 offset, length 然后再封装对应的 io.Reader …,2. EC 多机纠删码下载数据,与 fs 本地文件系统的区别在于,需要从多个 onlineDisks 中读取数据,并且可能是 remote 网络请求,这里用到了 xioutil.WaitPipe 底层是对 io.Pipe 的封装,getObjectWithFileInfo 把数据写入 pw 管道,上层调用 Read 从 pr 管道中读取数据,newBitrotReader 封装多个 reader, NewErasure 从 reader 中读数据,调用 Decode 解码读取的数据,如果出现错误,那么需要调用 healObject 尝试修复,理论上 K+M 中至多可以损坏 M 份数据,,如上图所示,8 台机器,每台 16 块硬盘,每块硬盘 8T, 总大小 1PB. 如果 strip 条带 K+M=16, 其中 M=4 的情况下,可用空间为 768T,利用率 75%,至多可以损坏 32 块硬盘,或者 2 台机器宕机,上面分析读取,对于上传对象逻辑也同理。Minio 代码整体 20w 行, 涉及到了大部分对象存储的知识,适合入门,值得一读,
© 版权声明
文章版权归作者所有,未经允许请勿转载。