本文是滴滴云开源框架教程系列文章的一篇。
1.背景说明
继上次的 Ceph介绍及原理架构 和 分布式存储Ceph之PG状态详解,这次继续分享干货。
用户需要从cephfs存储系统中检索一个大文件指定关键字的一行信息, 并且对延迟和性能要求比较高。
2. 原始方案
2.1 流程图
2.2 说明
- 假如用户拉取的文件大小是16M, 文件按照4M切分,散落到四个数据片上
- 用户首先请求cephfs拉取文件信息
- cephfs会根据crush算法找计算文件散落到那几个数据片上
- cephfs会拉取文件所属的数据片然后聚合起来
- cephfs文件拉取后返回给用户
- 用户拉取完整个文件,开始做过滤关键字操作
2.3 实战
//检索2.7G文件为例
$ ll -lh nginx/logs/access.log.2018102911
-rw-rw-r-- 1 root root 2.7G Oct 29 12:07 nginx/logs/access.log.2018102911
//grep 模拟花费12s
$ time grep "xxxyyyzzzqqq" nginx/logs/access.log.2018102911
real 0m12.355s
user 0m0.302s
sys 0m0.823s
2.4 优缺点
优点
- 简单方便
- 开发成本低
缺点
- 用户端检索延迟大,影响用户体验
- 客户端集群网卡带宽波动较大,带宽有限,每次都需要把大日志文件拉取到客户端
- 对ceph集群负载也有波动影响
2.5 总结
用户拉取文件,必须先通过cephfs拉取文件到本地,然后根据关键字检索这行数据。如果用户检索量比较大的时候,并且文件大小都不统一,拉取文件越大网络延迟越高,并且在大文件中过滤关键字效率非常低,严重影响用户的体验。
3. 优化方案
3.1 流程图
3.2 说明
- 用户发起请求输入文件名和key关键字到达索引层
- 索引层根据key找到对应的offset信息,然后传给dss-readline
- dss-readline根据cephfs cursh算法找到对应的object信息和offset信息
- 根据dss-readline用户输入的offset找到对应的object块信息
- dss-readline直接获取需要块的offset 该行的信息
3.3 实战
//查找2.8G文件offset对应的信息
$ ll nginx/logs/access.log.2018110216 -lh
-rw-rw-r-- 1 root root 2.8G Nov 2 17:08 nginx/logs/access.log.2018110216
//sed的方式模拟,花费12s
$ time sed -n "1024p" nginx/logs/access.log.2018110216
real 0m12.042s
user 0m1.191s
sys 0m0.929s
//dss_readfile 自研工具, 输入参数:poolname, filename, offset 可以看出来花费91ms
//usage: dss_readfile <poolname> <filename> <offset>
time ./dss_readfile data nginx/logs/access.log.2018110216 1024
real 0m0.091s
user 0m0.042s
sys 0m0.011s
3.4 优缺点
缺点
- 需要额外开发成本
优点
- 提升用户体验,从以前检索单个2.8G文件耗时10s左右, 优化后控制在100ms左右
- 客户端网络网卡带宽可用率得到提升
- 减少对ceph集群的冲击影响
3.5 总结
思路:
由于文件信息是放到服务端,进行切片存储到数据节点。
我们能不能只拉取我需要的块信息,不用全量拉取到本地,答案是肯定的。
- 根据文件信息查找所有的object、offset信息
- 根据offset找到需要检索的object信息
- 找到对应的object,读取该object对应的offset位置的信息(一行数据可能会拆分多个object)
优点: