1.cephfs集群搭建,源码在客户端挂载后,安装在这个挂载目录里,源码新建目录,安装存储数据,源码能限制目录的安装bytebuf源码大小吗(配额)?
2.Cephfs å¿«ç
§ä»ç»ä¸ä½¿ç¨
3.Ceph为什么越来越火?国内使用ceph较为成功的存储厂商有哪些?
4.cephfs:用户态客户端预读
5.GlusterFSåCephåªä¸ªå¥½ï¼
cephfs集群搭建,在客户端挂载后,源码在这个挂载目录里,安装新建目录,源码存储数据,安装能限制目录的源码大小吗(配额)?
cephfs使用ceph-fuse的方式挂载可以设置配额,内核方式挂载暂时还不能设置配额,安装
用户态ceph-fuse挂载设置配额的源码方式为:
setfattr -n ceph.quota.max_bytes -v /dir/dir/
Cephfs å¿«ç §ä»ç»ä¸ä½¿ç¨
äºåå®å ¨ç®¡çæå¡ä¸å®¶æ°éäºæ ç¥ç¥¥ç¿»è¯CEPFSæ¯æå¿«ç §åè½ï¼é常éè¿ä½¿ç¨mkdirå½ä»¤åå»ºå¿«ç §ç®å½ã注æè¿æ¯ä¸ä¸ªéèçç¹æ®ç®å½ï¼å¨ç®å½å表ä¸ä¸å¯è§ã
é常æ åµä¸ï¼å¿«ç §æ£å¦èµ·åï¼å®ä»¬ä¿åæ°æ®ååè¿ç¨ä¸çç¶æãéè¦æ³¨æçä¸ç¹äºï¼CEPFSå¿«ç §çä¸äºåè½ä¸æ¨å¯è½ææçææä¸åï¼
é»è®¤æ åµä¸ï¼æ°æ件系ç»ä¸ä¼å¯ç¨CEPFSå¿«ç §åè½ãè¦å¨ç°ææ件系ç»ä¸å¯ç¨å®ï¼è¯·ä½¿ç¨ä¸é¢çå½ä»¤ã
å¯ç¨å¿«ç §åï¼CephFSä¸çææç®å½é½å°æä¸ä¸ªç¹æ®ç .snap å¿«ç §ç®å½ãï¼å¦ææ¿æï¼å¯ä»¥ä½¿ç¨å®¢æ·ç«¯snapdir设置é ç½®å ¶ä»å称ï¼
è¦å建CephFSå¿«ç §ï¼è¯·å¨ .snap ä¸å建åç®å½ãç¨ä½ éæ©çåååå»ºå¿«ç §ãä¾å¦ï¼è¦å¨ç®å½â/1/2/3/âä¸åå»ºå¿«ç §ï¼è¯·ä½¿ç¨ mkdir /1/2/3/.snap/my-snapshot-name å½ä»¤ã
客æ·ç«¯ä¼å°è¯·æ±åéå°MDSæå¡å¨ï¼ç¶åå¨æå¡å¨çServer::handle_client_mksnapï¼ï¼ä¸å¤çãå®ä¼ä» SnapServerä¸åé ä¸ä¸ª snapidï¼å©ç¨æ°ç SnapRealmå建并é¾æ¥ä¸ä¸ªæ°çinodeï¼ç¶åå°å ¶æäº¤å° MDlogï¼æ交åä¼è§¦å MDCache::do_realm_invalidate_and_update_notify()ï¼æ¤å½æ°å°æ¤ SnapRealm广æç»ææå¯¹å¿«ç §ç®å½ä¸ä»»ä¸æ件æ管è¾æç客æ·ç«¯ã客æ·ç«¯æ¶å°éç¥åï¼å°åæ¥æ´æ°æ¬å° SanpRealmå±çº§ç»æï¼å¹¶ä¸ºæ°çSnapRealmç»æçææ°ç SnapContextï¼ç¨äºå°å¿«ç §æ°æ®åå ¥ OSD 端ãåæ¶ï¼å¿«ç §çå æ°æ®ä¼ä½ä¸ºç®å½ä¿¡æ¯çä¸é¨åæ´æ°å°OSD端ï¼å³sr_tï¼ãæ´ä¸ªè¿ç¨æ¯å®å ¨å¼æ¥å¤ççã
å¦æå é¤å¿«ç §ï¼å°æ§è¡ç±»ä¼¼çè¿ç¨ãå¦æå°inodeä»å ¶ç¶SnapRealmä¸å é¤ï¼éå½å代ç å°ä¸ºéå½åçinodeå建ä¸ä¸ªæ°çSnapRealmï¼å¦æSnapRealmä¸åå¨ï¼ï¼å°å¨åå§ç¶SnapRealmä¸ææçå¿«ç §IDä¿åå°æ°SnapRealmçç¶å¿«ç §ï¼past_parent_snapsï¼ä¸ï¼ç¶åéµå¾ªä¸åå»ºå¿«ç §ç±»ä¼¼çè¿ç¨ã
RADOS SnapContextç±ä¸ä¸ªå¿«ç §åºåIDï¼snapidï¼åä¸ä¸ªå å«ææå¿«ç §ID对象ç»æã为äºçæ该å表ï¼æ们å°ä¸SnapRealmå ³èçSnapIDä¸ç¶å¿«ç §ä¸çææææSnapIDç»åèµ·æ¥ãè¿æ¶çSnapIDç±SnapClientç¼åçææå¿«ç §è¿æ»¤æã
æ件æ°æ®åå¨å¨RADOSâself-managedâå¿«ç §ä¸ãå¨å°æ件æ°æ®åå ¥OSDæ¶ï¼å®¢æ·ç«¯ä¼å°å¿å°ä½¿ç¨æ£ç¡®çSnapContextã
å¿«ç §çdentriesï¼åå ¶inodeï¼ä½ä¸ºå¿«ç §æ¶æå¨ç®å½çä¸é¨åå¨çº¿åå¨ãæædentriesé½å æ¬ç¬¬ä¸ä¸ªåæåä¸ä¸ªææçsnapidãï¼éå¿«ç §çdentrieså°æå设置为CEPH_NOSNAPï¼ã
æ大é代ç å¯ä»¥ææå°å¤çååãå½å®¢æ·ç«¯æ¶å°MClientSnapæ¶æ¯æ¶ï¼å®ä¼æ´æ°æ¬å°SnapRealm表示åå ¶å°ç¹å®Inodeçé¾æ¥ï¼å¹¶ä¸ºInodeçæCapSnapãCapSnapä½ä¸ºåè½ååçä¸é¨åè¢«æ¸ é¤ï¼å¦æåå¨èæ°æ®ï¼CapSnapå°ç¨äºé»æ¢æ°çæ°æ®åå ¥ï¼ç´å°å¿«ç §å®å ¨æ¸ é¤å°OSDã å¨MDSä¸ï¼æ们çæ代表ç齿çå¿«ç §ï¼ä½ä¸ºå²æ´ç齿ç常è§è¿ç¨çä¸é¨åãå ·ææ°åºCapSnapæ°æ®çåç被åºå®å¹¶è®°å½å¨æ¥å¿ä¸ã
éè¿å¨å¿«ç §çæ ¹ç®å½â.snapâä¸è°ç¨ârmdirâæ¥å é¤å¿«ç §ãï¼å°è¯å é¤æ ¹å¿«ç §å°å¤±è´¥çç®å½ï¼å¿ é¡»å å é¤å¿«ç §ãï¼ä¸æ¦å é¤ï¼å®ä»¬å°è¢«è¾å ¥å°å·²å é¤å¿«ç §çOSDMapå表ä¸ï¼æ件æ°æ®å°ç±OSDå é¤ãå½ç®å½å¯¹è±¡è¢«è¯»å ¥å¹¶å次ååæ¶ï¼å æ°æ®ä¼è¢«æ¸ é¤ã
å ·æå¤ä¸ªç¡¬é¾æ¥çInode被移å¨å°ä¸ä¸ªèæå ¨å±SnapRealmãèæSnapRealmè¦çæ件系ç»ä¸çææå¿«ç §ãinodeçæ°æ®å°ä¸ºä»»ä½æ°å¿«ç §ä¿çãè¿äºä¿ççæ°æ®å°è¦çinodeçä»»ä½é¾æ¥ä¸çå¿«ç §ã
éè¦æ³¨æçæ¯ï¼CephFSçå¿«ç §åå¤ä¸ªæ件系ç»ç交äºæ¯åå¨é®é¢çââæ¯ä¸ª MDSé群ç¬ç«åé snappidï¼å¦æå¤ä¸ªæ件系ç»å ±äº«ä¸ä¸ªæ± ï¼å¿«ç §ä¼å²çªãå¦ææ¤æ¶æ客æ·å é¤ä¸ä¸ªå¿«ç §ï¼å°ä¼å¯¼è´å ¶ä»äººä¸¢å¤±æ°æ®ï¼å¹¶ä¸è¿ç§æ åµä¸ä¼æåå¼å¸¸ï¼è¿ä¹æ¯ CephFSçå¿«ç §ä¸æ¨è使ç¨çåå ä¹ä¸ã
åå»ºå¿«ç §ï¼
ä»å¿«ç §ä¸æ¢å¤æ件ï¼
èªå¨å¿«ç §
使ç¨cephfs-snapèªå¨å建åå é¤æ§å¿«ç §ã
ä¸è½½æä»¶å° /usr/bin
é åcron ä¸èµ·ä½¿ç¨ã{ hourly,daily,weekly,monthly}
使ç¨ç¤ºä¾ï¼
å建ç cron æä»¶å¿ é¡»è®¾ç½®ä¸ºå¯æ§è¡
è¦éªè¯é ç½®ç cron ä»»å¡æ¯å¦ä¼æ£ç¡®æ§è¡ï¼è¯·æå¨è¿è¡ä¸è¿°æ¥éª¤ä¸å建ç cron.* èæ¬
ç°å¨æ£æ¥ .snap ç®å½ä¸æ¯å¦åå»ºäº cephfs å¿«ç §
å¦æ cron 没ææé¢æ触åå¿«ç §ï¼è¯·éªè¯â/usr/bin/cephfs-snapâåâ/etc/cron.*/cephfs-snapâæ件æ¯å¦å¯æ§è¡
åèæç« ï¼
Ceph为什么越来越火?国内使用ceph较为成功的存储厂商有哪些?
Ceph是当前非常流行的开源分布式存储系统,具有高扩展性、安装高性能、源码高可靠性等优点,同时提供块存储服务(rbd)、内核源码跟踪调试对象存储服务(rgw)以及文件系统存储服务(cephfs)。目前也是OpenStack的主流后端存储,随着OpenStack在云计算领域的广泛使用,ceph也变得更加炙手可热。国内目前使用ceph搭建分布式存储系统较为成功的企业有x-sky,深圳元核云,上海UCloud等三家企业。
cephfs:用户态客户端预读
用户态客户端读取文件数据通常通过Client::_read_async函数实现,这是read操作的核心函数。根据名称,“异步读”意味着存在与之对应的“同步读”,即Client::_read_sync。理解了Client::_read_async,Client::_read_sync也就容易掌握了。这两者之间的主要区别在于,Client::_read_async负责读取缓存并具有预读功能,而Client::_read_sync则是CH资源源码直接从osd读取数据。
Client::_read_async可以简单分为read和readahead两部分。read对应于读流,而readahead对应于预读流。以下是这两个流的简单图示。可以看出,readahead stream不会阻塞等待。
结合代码来解释Client::_read_async。首先,解释一下预读。假设我们读取一个M的文件,每次读取k,如果没有预读且最初没有缓存文件内容,总共需要读取次,每次都需要与osd交互。如果有预读,同样需要读取次,文库付费源码下载但每次发送k的读请求给osd后,预读机制会再发送一个k的读请求,后面的k的读请求不阻塞等待。这相当于将用户的一次读请求在后端分成两个请求,共读取k,其中后一个k的请求是异步的。因此,下一次读请求来时,增加了命中缓存的几率,即使没有命中缓存,这也相当于提前将这个k的请求发送给osd,争取了一点时间效率。
预读Readahead在ceph中可以作为一个单独的模块,其代码位置在src/common/Readahead.h和src/common/Readahead.cc。这个模块的功能很简单,即通过简单的PHP来客系统源码机制或算法来计算每次预读的偏移(offset)和长度(length)。
在Readahead类中,有两个参数m_readahead_min_bytes和m_readahead_max_bytes,表示预读请求的最小和最大预读长度。这两个值是通过配置参数赋值的,在src/common/options.cc中有三个关于预读的配置参数。m_readahead_min_bytes和m_readahead_max_bytes的赋值位置在Client::_create_fh处。
从上面的代码中可以看出,m_readahead_min_bytes的值为 * = KB,m_readahead_max_bytes的值为in->layout.get_period() * (uint_t)conf->client_readahead_max_periods。get_period()函数来自结构体file_layout_t。目前ceph中使用的是简单条带策略,stripe_unit = object_size = 4M,stripe_count = 1,因此m_readahead_max_bytes的值为4M * 4 = M。综上所述,预读的范围是KB ~ M(在不考虑预读对齐的情况下)。
Readahead类实例是作为struct Fh的成员来使用的,struct Fh可以看作是文件的描述结构,Fh即File handle的简写。
读取文件时,需要先打开文件,在打开文件时,会建立Fh,并将其加入fd_map中。然后在关闭文件时,销毁Fh,并将其从fd_map中移除。代码如下:先是Client::open,然后再Client::_open中调用Client::_create_fh创建Fh。可以看出,如果一个文件已经打开,修改的预读范围对正在读取的文件是没有影响的。
在Client::_read_async中,在进行预读之前,需要计算预读的偏移值和长度。readahead_extent.first是偏移值,readahead_extent.second是长度,通过Readahead::update函数得到。
Readahead::update代码如下。在研究Readahead::_observe_read代码之前,先研究Readahead中7个比较重要的参数。Readahead::_observe_read代码如下。从代码中可以看出,_observe_read函数的作用是判断这一次的读请求是否是顺序的,如果不是顺序读,将其中的5个成员置0(置0的作用在后面可以看到,最后算出的预读偏移和长度都为0)。
Readahead::_compute_readahead是预读最重要的函数,代码如下。单纯看代码,会有点看不懂预读对齐,参考下面的图,更容易理解。上面的原理图只画了一种情况,即offset和offset+len分别落在不同的对象区间。如果readahead_end靠近align_prev时,如果需要对齐到4n,那么对齐的代价就是减少的对齐长度不能大于对齐前的预读长度的一半;如果readahead_end更靠近align_next时,如果需要对齐到4(n+1),那么对齐的代价就是增加的对齐长度不能大于对齐前的预读长度的一半。
还有第二种情况,即offset和offset+len分别落在相同的对象区间。这个时候就不能往align_prev对齐,如果需要补全到align_next,同样的道理,补全的对齐长度不能大于对齐前的预读长度的一半。所以通过预读对齐,预读的大小范围在K到M。
预读的原理图如下。预读的时候会判断是否是顺序读,这里就涉及到读的方式,一般都是顺序读,除非特意指定为随机读,当然这种情况暂且不论。在正常的顺序读中,也会出现非顺序读的情况。以ceph-fuse为例,比如读取M的test文件,一个io是K,总共会发个读请求。简单示意图如下。由于存储后端osd回复读请求的时间不一致,所以预读不一定按照①②③④顺序执行请求,假设①请求处理完后,③请求②请求比先读到后端数据,即顺序为①③②④。那么在处理③时,预读Readahead实例中记录的m_last_pos = K,而此时的读流的offset = K,m_last_pos != offset,这就没有按照顺序去读,就不会去预读。
GlusterFSåCephåªä¸ªå¥½ï¼
GlusterFSåCephé½æ¯Red Hatæä¸çæççå¼æºåå¨äº§åï¼Cephä¸GlusterFSå¨åçä¸æçæ¬è´¨ä¸çä¸åãç°å¨ç½ä¸æå¾å¤GlusterFSåCephç对æ¯æç« ï¼å¯ä»¥åèãæ»çæ¥è¯´ï¼å¦æåªä½¿ç¨æ件åè®®ï¼æè§GlusterFS好ä¸äºï¼å¦æè¦ä½¿ç¨å¯¹è±¡ãåãæ件ç»ä¸åå¨ï¼é£Cephæ¯ä¸äºéæ©ãè¦ä½¿ç¨å¥½è¿ä¸¤ä¸ªå¼æºè½¯ä»¶ï¼é½éè¦æä¸å®çITå®ååæå ¥ï¼å¦æå®é ä¸ç产使ç¨ï¼å»ºè®®éæ©åä¸åç产åï¼GlusterFSåä¸äº§ååå¾æ¯è¾å¥½çå ¬å¸æ大éãå¯ç¿ï¼Cephåä¸äº§ååå¾æ¯è¾å¥½çå ¬å¸æXSKYãå æ ¸äºãæ岩ã