初探lustre中数据分片

2022-08-17 12:47:39 浏览数 (1)

lustre的环境

  • 版本: lustre 2.14.0
代码语言:javascript复制
[client ~]$ lfs --version
lfs 2.14.0
  • 组件:1个mds,mgs和mds共享一个磁盘,后端采用ldiskfs.2个ost
代码语言:javascript复制
[client ~]$ lctl dl |grep -v "cli"
  0 UP mgc MGC10.211.55.12@tcp 668ebd57-05d7-4faf-b5af-66e997972911 4
  3 UP mdc bigfs-MDT0000-mdc-ffff929ffb511000 2762b3a8-0210-4c9f-b5ab-25b059d23afd 4
  4 UP osc bigfs-OST0000-osc-ffff929ffb511000 2762b3a8-0210-4c9f-b5ab-25b059d23afd 4
  5 UP osc bigfs-OST0001-osc-ffff929ffb511000 2762b3a8-0210-4c9f-b5ab-25b059d23afd 4
lustre中文件数据分片模式
  • 默认模式 :默认lustre集群中文件的stripe_count=1,stripe_size=1M,也就是说所有文件的数据只会落到一个ost上,数据的是被分片为多个stripe_size大小的块,存储在一个ost上,不会分不到多个ost上。默认模式,会减少文件执行stat/unlink的开销,stripe_count>1会导致更多的lock和网络的开销。其次是默认的模式即使出现某个ost换掉,也仅仅影响某个ost的上的数据,对于其他的ost上,数据并未做分片,也没影响。
代码语言:javascript复制
// lustre默认的stripe_count和stripe_size
[client ~]$ lfs getstripe /mnt/lustre
/mnt/lustre
stripe_count:  1 stripe_size:   1048576 pattern:       0 stripe_offset: -1

// 这里准备15M的数据写入到集群,查看数据分布模式
[client ~]$ ls -l -1h
total 16M
-rw-r--r--. 1 root root 15M Jan 16 21:54 1.data

// 数据写入到集群
[client ~]$ cp 1.data  /mnt/lustre

// 从客户端视角查看刚刚写入的数据
[client ~]$ ls -l -1h /mnt/lustre
total 12M
-rw-r--r--. 1 root root 15M Jan 16 21:56 1.data

// 1.data的的确是写入到了一个ost,这个obdidx =1 是代表了ost index=1的那个ost上
[client ~]$ lfs getstripe  /mnt/lustre/1.data 
/mnt/lustre/1.data
lmm_stripe_count:  1
lmm_stripe_size:   1048576
lmm_pattern:       raid0
lmm_layout_gen:    0
lmm_stripe_offset: 1
        obdidx           objid           objid           group
             1              34           0x22                0
  • stripe模式 : 当设置文件或者目录的stripe_count>1时候,文件会被stripe到多个ost.在lustre中最佳的stripe_count应该是ost的个数。在stripe模式中,当单个ost容量不足以支撑某个文件时候,设置stripe_count>1可以让这个文件分散的存储在多个ost上。如果做了stripe_count>1的设置,某个ost换掉,那么这个文件的数据就会出现确实,存在这样的一个风险。
代码语言:javascript复制
// 数据准备
[client ~]$ cp ../go.tar.gz  ./2.data
[client ~]$ ls -l -1h
-rw-r--r--. 1 root root 3.6M Jan 16 22:00 2.data

// 准备做stripe分片的目录
[client ~]$ mkdir /mnt/lustre/stripe_dir

// 获取默认的stripe属性,模式是不分片的,继承根的挂载目录属性
[client ~]$ lfs getstripe  /mnt/lustre/stripe_dir/
/mnt/lustre/stripe_dir/
stripe_count:  1 stripe_size:   1048576 pattern:       0 stripe_offset: -1

// 设置这个目录超过stripe_size的数据大小的分片个数
[client ~]$ lfs setstripe  /mnt/lustre/stripe_dir -c 3

// 获取stripe_dir目录的的stripe的属性,目前是设置为3个分片
[root@CentOS-Lustre-Client ~/temp_data]$ lfs getstripe  /mnt/lustre/stripe_dir/
/mnt/lustre/stripe_dir/
stripe_count:  3 stripe_size:   1048576 pattern:       raid0 stripe_offset: -1


// 写入2.data到stripe_dir目录
[client ~]$ cp 2.data  /mnt/lustre/stripe_dir/

// 获取2.data的stripe的信息,目前整个环境
[client ~]$ lfs getstripe  /mnt/lustre/stripe_dir/2.data 
/mnt/lustre/stripe_dir/2.data
lmm_stripe_count:  2
lmm_stripe_size:   1048576
lmm_pattern:       raid0
lmm_layout_gen:    0
lmm_stripe_offset: 1
        obdidx           objid           objid           group
             1              35           0x23                0
             0               3            0x3                0
lustre中stripe属性确定文件位置
文件数据在ost上位置分析
  • 当执行lfs getstripe {mount目录}/{xx文件}获取了文件的stripe属性,其中的obdidx objid objid group包含了文件stripe的基本信息。obdidx是后端ost的index(当前集群有2个ost,index分别是0和1),objid代表后端ost文件系统中O/{group的值}目录。后面两列的objid分别代表了O/{group的值}/d{第一个objid}的目录和O/{group的值}/d{第一个objid}/{第二个objid}的子目录。比如下面列子中2.data文件,lmm_stripe_count是2(stripe_count=2),分别是在ost index=0和ost index=1的后端的ost上,文件的第一个分片是在ost index=0在ost index=0后端挂载对应的文件是O/0/d5/5;而ost index=1后端挂载对应的文件是O/0/d26/38,这个目录在后端的ost index=1中是不存在的,在O/0下面只有,O/0/d{0~31}32个目录,d26中不存在文件2.data的分片38.而在d6下面存在38这个文件分片,因此在lustre 2.14中当objid超过32时候,分片的目录对应的是O/0/d{objid2}/objid.
  • lfs getstripe命令输出文件的布局信息,obdidx objid objid group,从右往左的第二个objid如果超过后端ost的目录中O/0/d{0~31}这个的目录范围(比如d34),那么文件真是分片的的所在后端的ost目录则需要根据第二个objid重新计算,从试验的情况确认了计算规则(O/{group}/d{第二个objid2}/{第二个objid});如果没有超过(通常是ost index=0)的情况,ost后端的文件分片则位于O/{group}/d{第一个objid}/{第二个objid}
代码语言:javascript复制
/************************客户端写入数据*****************/

// 准备数据
[client ~]$ ls -l -1h
-rw-r--r--. 1 root root 3.6M Jan 16 22:00 2.data

// 重新创建目录的stripe
[client ~]$ mkdir /mnt/lustre/stripe_dir

// 设置目录的stripe
[client ~]$ lfs setstripe -c 2  /mnt/lustre/stripe_dir/ 

// 写入数据
[client ~]$ cp 2.data  /mnt/lustre/stripe_dir/

// 查看对应的对象分片的信息
[client ~]$ lfs getstripe  /mnt/lustre/stripe_dir/2.data 
/mnt/lustre/stripe_dir/2.data
lmm_stripe_count:  2
lmm_stripe_size:   1048576
lmm_pattern:       raid0
lmm_layout_gen:    0
lmm_stripe_offset: 0
        obdidx           objid           objid           group
             0               5            0x5                0
             1              38           0x26                0
代码语言:javascript复制
/***************ost index=0 显示后端的2.data的数据分片***********/

[ost /mnt/ost0/O/0/d5]$ ls -l -1h
total 2.0M
-rw-rw-rw- 1 root root 2.0M Jan 16  2022 5

/***************ost index=1 显示后端的2.data的数据分片***********/

[ost /mnt/ost2/O/0/d6]$ ls -l -1h
total 1.6M
-rw-rw-rw- 1 root root 1.6M Jan 16  2022 38
客户端视角查看lustre文件的inode
  • 客户端的视角查看的文件inode是从fid计算出来的,fid的是有seq、objid、version进行计算的。具体是是通过fid_flatten函数实现。
代码语言:javascript复制
// lustre中的fid的定义
struct lu_fid {
  // seq序号
	__u64 f_seq;
  // object id
	__u32 f_oid;
  // 版本号
	__u32 f_ver;
} __attribute__((packed));

// 从fid中获取客户端查看的inode
static inline __u64 fid_flatten(const struct lu_fid *fid)
{
	__u64 ino;
	__u64 seq;

	if (fid_is_igif(fid)) {
		ino = lu_igif_ino(fid);
		return ino;
	}

	seq = fid_seq(fid);

	ino = (seq << 24)   ((seq >> 24) & 0xffffff0000ULL)   fid_oid(fid);

	return ino ?: fid_oid(fid);
}

为了方便起见,自己写了lfs_tool工具来获取文件的fid和文件的stripe信息,整合后以json的形式dump出来,列出文件的stripe信息,包括文件的数据的所在ost的位置

代码语言:javascript复制
// 查看2.data客户端视角中的文件inode信息
[client ~]$ ls -li /mnt/lustre/stripe_dir/2.data 
144115205272502281 -rw-r--r--. 1 root root 3687735 Jan 16 23:14 /mnt/lustre/stripe_dir/2.data

// lfs_tool解析文件的fid,获取文件的综合信息,列举出来文件的所在ost的位置
[client ~]$ ./lfs_tool  -f /mnt/lustre/stripe_dir/2.data          
summary:
{
  "fid_seq": 8589935617,
  "fid_objid": 9,
  "fid_version": 0,
  "inode": 144115205272502281,
  "stripe_count": 2,
  "stripe_size": 1048576,
  "pattern": "raid0",
  "file": "/mnt/lustre/stripe_dir/2.data",
  "ost_list": [
   {
    "index": "0",
    "data_location": "O/0/d5/5"
   },
   {
    "index": "1",
    "data_location": "O/0/d6/38"
   }
  ]
 }

0 人点赞