在 RADOS 层,Ceph 本身没有条带的概念,因为一个object 是作为一个文件整体性保存的。RBD 可以控制向一个 object 的写入方式,默认是将一个 object 写满再去写下一个object;还可以通过指定 stripe_unit 和 stripe_count,来将 object 分成若干个条带即 strip。一个 RDB image 会被分为多个 object 来保存,从而使得对一个 image 的多个读写可以分在多个 object 进行,从而可以防止某个 image 非常大或者非常忙时单个节点称为性能瓶颈。还可以将 object 进一步条带化为多个条带(stripe unit)。条带(stripe)是 librados 通过 ODS 写入数据的基本单位。这么做的好处是在保持对象数目的同时,进一步减少可以同步读写的粒度(从 object 粒度减少到 stripe 粒度),从而提高读写效率。
Ceph 的条带化行为(如果划分条带和如何写入条带)受三个参数控制:
object-size(cephfs),order(rbd,默认为22):默认对象大小为4MB。
stripe_unit:条带(stripe unit)的大小。每个 [stripe_unit] 的连续字节会被连续地保存到同一个对象中,client 写满 stripe unit 大小的数据后,接着去下一个 object 中写下一个 stripe unit 大小的数据。默认为 1,此时一个 stripe 就是一个 object。
stripe_count:在分别写入了 [stripe_unit] 个字节到 [stripe_count] 个对象后,ceph 又重新从一个新的对象开始写下一个条带,直到该对象达到了它的最大大小。这时候,ceph 转移到下 [stripe_unit] 字节。默认为 object site。
举例:32M的rbd image,object_size=4M,stripe_unit=1M,stripe_count=4
分析:
- RBD image 会被保存在总共 8 个 RADOS object (计算方式为 client data size 除以 2^[order]单位:字节)中。
- stripe_unit 为 object size 的四分之一,也就是说每个 object 包含 4 个 stripe(1M)。
- stripe_count 为 4,即每个 object set 包含四个 object。这样,client 以 4 为一个循环,向一个 object set 中的每个 object 依次写入 stripe,写到第 16 个 stripe 后,按照同样的方式写第二个 object set。
--- object set 0 ---
/---------\ /---------\ /---------\ /---------\
| obj_0 4M| | obj_1 4M| | obj_2 4M| | obj_3 4M|
|=========| |=========| |=========| |=========|
| stripe | | stripe | | stripe | | stripe |
| unit 0 | | unit 1 | | unit 2 | | unit 3 |
1M 1M 1M 1M
|---------| |---------| |---------| |---------|
| stripe | | stripe | | stripe | | stripe |
| unit 4 | | unit 5 | | unit 6 | | unit 7 |
|---------| |---------| |---------| |---------|
|---------| |---------| |---------| |---------|
| stripe | | stripe | | stripe | | stripe |
| unit 8 | | unit 9 | | unit 10 | | unit 11 |
|---------| |---------| |---------| |---------|
|---------| |---------| |---------| |---------|
| stripe | | stripe | | stripe | | stripe |
| unit 12 | | unit 13 | | unit14 | | unit 15 |
|---------| |---------| |---------| |---------|
--- object set 1 ---
/---------\ /---------\ /---------\ /---------\
| obj_4 4M| | obj_5 4M| | obj_6 4M| | obj_7 4M|
|=========| |=========| |=========| |=========|
| stripe | | stripe | | stripe | | stripe |
| unit 0 | | unit 1 | | unit 2 | | unit 3 |
1M 1M 1M 1M
|---------| |---------| |---------| |---------|
| stripe | | stripe | | stripe | | stripe |
| unit 4 | | unit 5 | | unit 6 | | unit 7 |
|---------| |---------| |---------| |---------|
|---------| |---------| |---------| |---------|
| stripe | | stripe | | stripe | | stripe |
| unit 8 | | unit 9 | | unit 10 | | unit 11 |
|---------| |---------| |---------| |---------|
|---------| |---------| |---------| |---------|
| stripe | | stripe | | stripe | | stripe |
| unit 12 | | unit 13 | | unit14 | | unit 15 |
|---------| |---------| |---------| |---------|
默认的情况下,[stripe_unit] 等于 object size;stripe_count 为1。意味着 ceph client 在将第一个 object 写满后再去写下一个 object。
cephfs
cephfs也同样支持配置file layout,可以控制file分配到指定的ceph rados objects上,这些信息是写在file/dir的xattrs上。
文件的layout xattrs为:ceph.file.layout
目录的layout xattrs为:ceph.dir.layout
目录中的文件和子目录默认继承父目录的layout配置
支持的layout配置项有:
pool: file的数据存储在哪个RADOS pool里
namespace: file的数据存储在RADOS pool里的哪个namespace里,但现在rbd/rgw/cephfs都还不支持
stripe_unit: 条带的大小,以Bytes为单位
stripe_count: 条带的个数
比如,stripe_unit=512kb,stripe_count=2,默认object size是4MB,则file写10MB的数据分配如下:
(stripe_count=2表示2个对象(每个对象大小为4M)为一个对象集,接受stripe_unit单位大小的连续字节循环写入。此时写入10M文件,则除以stripe_unit等于20个条带对象,循环写入到每个对象集中的每个对象,当一个对象集里面对象都写满后,剩下的条带对象写入到第二个对象集中,然后每个对象写入到不同的osd中去)
--- object set 0 --- --- object set 1 ---
/---------\ /---------\ /---------\ /---------\
| obj_0 4M| | obj_1 4M| | obj_M2 4M| | obj_3 4M|
|=========| |=========| |=========| |=========|
| stripe | | stripe | | stripe | | stripe |
| unit 0 | | unit 1 | | unit 0 | | unit 1 |
512KB 512KB 512KB 512KB
|---------| |---------| |---------| |---------|
| stripe | | stripe | | stripe | | stripe |
| unit 2 | | unit 3 | | unit 2 | | unit 3 |
|---------| |---------| \=========/ \=========/
| stripe | | stripe |
| unit 4 | | unit 5 | osd 16 osd 20
|---------| |---------|
| stripe | | stripe |
| unit 6 | | unit 7 |
|---------| |---------|
| stripe | | stripe |
| unit 8 | | unit 9 |
|---------| |---------|
| stripe | | stripe |
| unit 10 | | unit 11 |
|---------| |---------|
| stripe | | stripe |
| unit 12 | | unit 13 |
|---------| |---------|
| stripe | | stripe |
| unit 14 | | unit 15 |
\=========/ \=========/
osd 25 osd 3
验证file stripe
# mount -t ceph 192.168.0.31:/ /vcfs
# mkdir /vcfs/vcfs/test
# setfattr -n ceph.dir.layout -v "stripe_unit=524288 stripe_count=8 object_size=4194304 pool=cephfs_data2" /vcfs/vcfs/test
# getfattr -n ceph.dir.layout /vcfs/vcfs/test
getfattr: Removing leading '/' from absolute path names # file: vcfs/vcfs/test
ceph.dir.layout="stripe_unit=524288 stripe_count=8 object_size=4194304 pool=data"
# cephfs /vcfs/vcfs/test show_layout
WARNING: This tool is deprecated. Use the layout.* xattrs to query and modify layouts.
layout.data_pool: 1
layout.object_size: 4194304
layout.stripe_unit: 524288
layout.stripe_count: 8
写入文件,并查看文件的location
# dd if=/dev/zero of=/vcfs/vcfs/test bs=4M count=100
# cephfs /vcfs/vcfs/test show_location
WARNING: This tool is deprecated. Use the layout.* xattrs to query and modify layouts.
location.file_offset: 0 // file的偏移
location.object_offset:0 // object的偏移
location.object_no: 0 // object的number
location.object_size: 4194304 // object size为4M
location.object_name: 10000002356.00000000 // object的name
location.block_offset: 0 // block的偏移
location.block_size: 524288 // block size为512k(这里很关键)
location.osd: 0 // 存储在osd 0 上
# cephfs /vcfs/vcfs/test show_location -l 524288
WARNING: This tool is deprecated. Use the layout.* xattrs to query and modify layouts.
location.file_offset: 524288 // file的偏移
location.object_offset:0 // object的偏移
location.object_no: 1 // object的number
location.object_size: 4194304 // object size为4M
location.object_name: 10000002356.00000001 // object的name
location.block_offset: 0 // block的偏移
location.block_size: 524288 // block size为512k(这里很关键)
location.osd: 2 // 存储在osd 2 上
新建目录设置strip_unit为1M 即1048576字节
#mkdir /vcfs/vcfs/test1
# setfattr -n ceph.dir.layout -v "stripe_unit=1048576 stripe_count=8 object_size=4194304" /vcfs/vcfs/test1
# dd if=/dev/zero of=/vcfs/vcfs/test1/abc bs=4M count=10
10+0 records in
10+0 records out
41943040 bytes (42 MB) copied, 0.370634 s, 113 MB/s
# cephfs /vcfs/vcfs/test1/ show_layout
WARNING: This tool is deprecated. Use the layout.* xattrs to query and modify layouts.
layout.data_pool: 1
layout.object_size: 4194304
layout.stripe_unit: 1048576
layout.stripe_count: 8
#cephfs /vcfs/vcfs/test1/abc show_location
WARNING: This tool is deprecated. Use the layout.* xattrs to query and modify layouts.
location.file_offset: 0
location.object_offset:0
location.object_no: 0
location.object_size: 4194304
location.object_name: 10000000005.00000000
location.block_offset: 0
location.block_size: 1048576 // block size为1M
location.osd: 3
#cephfs /vcfs/vcfs/test1/abc show_location -l 1048576
WARNING: This tool is deprecated. Use the layout.* xattrs to query and modify layouts.
location.file_offset: 1048576
location.object_offset:0
location.object_no: 1
location.object_size: 4194304
location.object_name: 10000000005.00000001
location.block_offset: 0
location.block_size: 1048576 // block size为1M
location.osd: 0
rbd
在测试rbd条带的过程中遇到如下问题,以后在解决。暂时记录,初步怀疑内核不支持。
[root@radosgw1 ~]# rbd create test -p zhang --size=100M --object-size 4M --stripe-unit 1048576 --stripe-count 8 --image-format 2 --image-feature layering
[root@radosgw1 ~]# rbd info zhang/test
rbd image 'test':
size 102400 kB in 28 objects
order 22 (4096 kB objects)
block_name_prefix: rbd_data.5a27626b8b4567
format: 2
features: layering, striping
flags:
stripe unit: 1024 kB
stripe count: 8
[root@radosgw1 ~]# rbd map zhang/test
rbd: sysfs write failed
In some cases useful info is found in syslog - try "dmesg | tail" or so.
rbd: map failed: (22) Invalid argument
[root@radosgw1 ~]# dmesg |tail -n 1
[274817.782747] rbd: image test: unsupported stripe unit (got 1048576 want 4194304)
[root@radosgw1 ~]# uname -r
4.4.13-1.el7.elrepo.x86_64
未完待续。。。。