当前位置:网站首页>【ceph】CEPHFS 内部实现(一):概念篇--未消化
【ceph】CEPHFS 内部实现(一):概念篇--未消化
2022-06-26 14:56:00 【bandaoyu】
基础
CephFS致力于提供POSIX兼容的文件系统接口,为了实现这一目标,CephFS选择了以目录树的形式在内存管理和使用元数据信息。和S3的“伪目录”做对比,这种目录树的方式能更高效、直接地实现POSIX语义。
CephFS作为分布式文件系统,面临所有分布式系统都要着力解决的两个问题:海量数据,单点。面对海量元数据,单机内存容量显然无法满足要求,对此CephFS提供了多个Active MDS机制,将目录树划分成不同区域,分别在不同MDS上管理,MDS在检测到对端MDS故障后,能对故障MDS进行接管,解决单点问题,实现高可用。
由于目录树的结构特点,导致对目录树的并发操作需要一种互斥机制来保证一致性。举例来说,同时在同一个目录下新建文件,对于这个目录来说必须是顺序进行的,而在不同目录下创建文件时,对目标目录的修改是可以并行的,但同时也要确保目标目录以上直至根节点,在这个期间不会被其他线程修改,比如对一个目录节点进行修改时,这个目录及其全部父节点所在路径无法做快照,这是显而易见的。为此MDS中实现了自己的一套锁机制。
为了提高可靠性,MDS中每次针对目录树的修改都是先写日志,再修改内存目录树结构,最后将修改后的结果落盘。如果中途有MDS故障,再次启动或者被其他MDS接管时,重放日志即可恢复到故障前的目录树状态。
实现
目录树结构
目录树中三个关键数据结构是inode,dentry和dir,三者通过互相连接,共同组成了一个树形目录结构。

Inode中存储的是具体文件/目录的元信息,例如mode,size等。inode号用来在metapool或datapool中查找对应的对象,在metapool中,每个对象是一个dir(分片),在datapool中,每个对象(头对象)是一个文件。
Dentry中存储的是文件/目录的名字,被用来连接inode和dir。
Dir通过一个items map记录自己管理的目录项(dentry),且拥有一个和自身连接的inode,通过inode可以继续向上回溯目录树。items map通过omap方式存储在metapool中。
目录树细节
inode
inode除记录元信息外,作为目录节点时还通过dirfrags管理本节点的分片(fragement),通过分片可以将一个大目录(应用层面)或者热点目录(应用层面)拆分成多个较小目录(实现层面),从而管理更大容量的目录或者在多个mds间实现负载平衡。
dentry
dentry在内存中有三种存在方式:primary,remote,null。
- primary dn表示一个正常的目录项:已连接到一个inode。
- remote dn对应文件系统中的硬链接(hard link),文件系统中不允许dir有hard link,所以只有普通文件在mds内存中可能有对应的remote dn出现。一个inode只能有一个parent,但能有多个remote parent,parent指向的是primary dentry,remote parent指向的是remote dentry。
- null dn是一个中间状态,表示dn还未和inode关联。和前两种dentry不一样,null dn不会存储在meta pool中。
dir
每个dir节点都是以<inodenum>.<fragment>的命名方式存在于meta pool中,通过CDir::fetch()读取metapool中的数据,填充自己的CDir::items,从而在内存初中创建相应的dentry和inode结构。
auth
单个Active MDS时,三种元数据结构都只有一份内存副本,位于Active MDS中,且都标记为auth,但当存在多个Active MDS时,每种元数据结构(inode、dentry、dir)都可能出现!auth的情况,!auth情况的出现是由于目录分裂(split)、备份(replicate)、迁移(export)引起。对于来自client的修改类请求,只有auth能处理,!auth节点只能处理非修改类请求。
master / slave request
master和slave用于标识一个mds间请求中的请求方和接收方。发起方为mater(mdr->is_master()),接受方为slave(mdr->is_slave())
锁
实现数据一致性最简单的办法是每次操作对整个目录树加锁,这种方式实现简单,但在性能上显然无法接受。为了实现对目录树中数据结构更高效的互斥操作,mds中设计了12个锁,每个锁管理一部分元数据信息,每个锁有自己的状态,分属于不同类型的状态机,状态机定义了每个锁存在的状态,以及每个状态下client能获得的锁权限和能进行的操作。
锁的类型及所属状态机如下:
struct LockType {
int type;
const sm_t *sm;
explicit LockType(int t) : type(t) {
switch (type) {
case CEPH_LOCK_DN: // 管理dentry
case CEPH_LOCK_IAUTH: // 管理mod,uid,gid等信息
case CEPH_LOCK_ILINK: // 管理link属性
case CEPH_LOCK_IXATTR: // 管理扩展属性
case CEPH_LOCK_ISNAP: // 管理快照信息
case CEPH_LOCK_IFLOCK: // 文件锁相关
case CEPH_LOCK_IPOLICY: // 管理layout、quota等信息
sm = &sm_simplelock;
break;
case CEPH_LOCK_IDFT: // 管理分片信息
case CEPH_LOCK_INEST: // 管理目录递归统计信息,如文件个数等
sm = &sm_scatterlock;
break;
case CEPH_LOCK_IFILE: //对于目录则是管理本层目录的统计信息,对于普通文件则是管理文件大小等
sm = &sm_filelock;
break;
case CEPH_LOCK_DVERSION:
case CEPH_LOCK_IVERSION:
sm = &sm_locallock;
break;
default:
sm = 0;
}
}
};
其中CEPH_LOCK_DVERSION和CEPH_LOCK_DN是dentry使用的两个锁,其余都是inode使用的锁。dir中没有锁。
对锁共有4种操作:加读锁(rdlock),加写锁(wrlock),加远程写锁(remote_wrlock),加互斥锁(xlock)。每个锁会用到哪些操作根据所属状态机类型区分,总的来说,rdlock用于共享读,xlock用于独占资源,wrlock是针对目录进行的优化锁操作,remote_wrlock则是在处理rename操作中可能会用到的一种加锁方式(因为处理rename请求的MDS是dest-dn为auth的节点,可能会和src-inode的auth不不是同一个MDS上,这时需要在dest-dn的auth节点上对src-inode进行remote_wrlock)。
MDS每次操作目录树时都会先确定好需要锁定的资源(即锁类型)和要进行的操作,然后通过Locker::acquire_locks()集中进行加锁,如果中途碰到某个锁无法加成功,则这个mdr被挂起,直到对应资源可用后再被重新执行。
sm_locallock
locallock sm(sate machine) 有两个分别用于dn version和inode version管理的锁。这两个锁都是为了在本地mds中维护version的一致性。而其他三种状态机则是为了在全部Active mds中维护资源的一致性。
来自客户端的修改请求处理前都会对相应资源进行xlock,在没有明确要求对version进行加锁时,Locker会根据mdr是否为master为相应的version locker默认进行wrlock或xlock。比如创建新文件时会对新文件的dentry进行xlock,这个过程中mds会自动对dentry 的version lock加锁。
对version lock进行xlock和wrlock区别在于xlock在同一个MDS上是互斥的,wrlock是可以重复加的。
locallock sm 是四种状态机中最简单的一种,它只有一个状态,是否可加锁是通过计数方式进行判断,不能加锁时并不会对锁进行状态调整。sm_simplelock
simplelock sm中的锁只能进行rdlock和xlock两种操作,这和通常的共享/互斥概念是一致的。两种操作都会根据sm判断是否可成功加锁,不满足加锁条件时会根据状态机进行调整。

sm_scatterlock
scatterlock sm有两个锁:IDFT用于目录分片管理,INEST用于目录递归统计信息管理,两者都可以进行rdlock,wrlock,但INEST lock多了在!auth上进行remote_wrlock的操作。相比simple lock sm,scatter sm多了MIX状态,提供多个副本同时写入的功能。举例来说,假设两个Active MDS,某个inode关联的目录分裂成两个分片分别位于两个MDS上,在两个分分片下各自创建新文件,这时如果INEST锁在MIX状态,则rstat信息会在两个MDS上各自更新(各自+1),当有读请求需要读取inode的rstat信息时,由于需要对INEST进行rdlock,这时会先把两个MDS上分散的数据整合到inode的auth节点上,然后加锁才会成功,最后客户端读到正确数据。
scatter sm在auth和!auth上加锁 sm_filelock
filelock sm只有一个类型的锁:IFILE。
对于目录IFILE管理本层目录的统计信息(INEST管理的是递归信息),可以进行rdlock,wrlock,remote_wrlock。三种加锁行为和scatterlock sm一样。
对于文件,IFILE管理每个client对文件的读写及范围。可以进行rdlock,xlock,这两种加锁行为和simplelock sm一样。
lease
在client端元数据依然有dir,inode,dn三种形式,但比mds中要简单得多,dn不再有三种形态,而是只有两种:有inode关联,没有inode关联。dentry lease被用来表示dn在client端的有效性。
dentry lease存在的必要性可能有这样两个原因:
- 有inode关联的dn可以通过inode的cap来判断dn有效性,但没有inode关联的dn就无法借助inode的cap来判断了
- 在read dir的时候,可以不用获取dir下各个节点的inode
loner
从CInode::calc_ideal_loner()可以看出loner是指在所有client中,当只有一个client在请求写权限时,这个client就被当做loner。
根据src/mds/locks.c中状态机的定义,只有simplelock sm和filelock sm有loner的概念,作为loner的client对元数据具有全部权限(读/互斥),非loner的client则没有任何权限,因此也就无法操作元数据,这本质上是加锁过程产生的一个结果。加锁简单来说是为了保证数据一致性,具体来说是mds根据状态机收回其他client的cap,如果client端有脏数据,则先更新数据,再将cap授予给请求操作的client这样一个过程。拿simplelock sm举例,当一个client需要对一个文件修改owner时,请求发到mds后,mds对inode的AUTH lock进行xlock,当xlock成功时,表明之前(如果有的话)授予给其他client的对于AUTH的cap已经被收回,这时mds可以对inode进行修改,修改完后要进行drop locks,如果自从xlock后,再没有其他client请求这个inode的cap,那么这时发起请求的这个client就是loner,AUTH lock进入到LOCK_EXCL状态,根据状态机定义这个client现在对AUTH具有全部权限,这也和loner的字面意思也相符。如果在xlock成功后,请求处理完成前,又有其他client请求inode的写cap(CEPH_CAP_GEXCL),那么当第一个请求处理完,drop locks时发现其他节点也在请求写,这时不满足loner条件,锁的状态不再进入到LOCK_EXCL,二是根据状态机定义和各个client对cap的请求,重新计算状态,根据得到的状态将cap发送给第一个请求中的client,至此,修改文件owner的那个请求完成。
cap
client端针对每个inode都有独立的cap,表示是否可以相应元数据进行读写。从状态机定义可以看出,scatter sm只有sync状态下允许client读,其他状态下client没有任何权限,这和scatter sm下的两个锁作用也相符合:IDFT管理目录分片和INEST管理目录递归统计,这两种信息对于client来说只能读取,client不应该去尝试修改,因为这两种信息是在mds中进行维护的。对于simplelock sm,client对每种资源(对应一种锁类型)有读和互斥两个权限,符合常理。对于filelock sm,SHARED和EXCL用来维护对stats(对目录)和size(对普通文件)这些资源的互斥,CEPH_CAP_FILE_RD和CEPH_CAP_FILE_WR用来管理普通文件的读取和写入,CEPH_CAP_FILE_CACHE和CEPH_CAP_FILE_BUFFER用来管理普通文件的缓冲读写能力(对应本地文件系统中的Cache和Buffer功能)。
client range
根据filelock sm可以看出对普通文件是支持多个client下同时读写的,比如LOCK_MIX状态下,每个client都能拥有CEPH_CAP_GRD|CEPH_CAP_GWR权限。相应的在MDS端,client range结构用来记录每个client当前的读写范围,当有其他client改变了文件的size后,相应client range要更新。
inline data
当一个文件过小时(不超过client_max_inline_size)把数以inode的attr(blustore中最终就是rocksdb的key-val)形式存在。
pin和freeze
pin表示元数据正在被引用,这时无法对目录进行迁移、分裂操作,需要进行迁移或者分裂时需要先freeze目标子树,freeze后相关的元数据节点无法被pin,也就无法被修改。
作者:宋新颖
链接:https://www.jianshu.com/p/ebb3f44b67b4
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
边栏推荐
- Bank of Beijing x Huawei: network intelligent operation and maintenance tamps the base of digital transformation service
- 1. accounting basis -- several major elements of accounting (general accounting theory, accounting subjects and accounts)
- vsomeip3 双机通信文件配置
- 一键安装gcc脚本
- Database - integrity constraints
- Informatics Olympiad 1405: sum and product of prime numbers (thinking problem)
- 1.会计基础--会计的几大要素(会计总论、会计科目和账户)
- Keil4打开单片机工程一片空白,cpu100%程序卡死的问题解决
- 杜老师说网站更新图解
- Talk about the recent situation of several students from Tsinghua University
猜你喜欢

Restcloud ETL extraction de données de table de base de données dynamique

RestCloud ETL抽取動態庫錶數據實踐

【TcaplusDB知识库】TcaplusDB单据受理-建表审批介绍

Bank of Beijing x Huawei: network intelligent operation and maintenance tamps the base of digital transformation service

Detailed explanation of C language programming problem: can any three sides form a triangle, output the area of the triangle and judge its type

RestCloud ETL解决shell脚本参数化

feil_uVission4左侧工目录消失

【TcaplusDB知识库】TcaplusDB运维单据介绍

Solution to the upper limit of TeamViewer display devices

Document 1
随机推荐
Program analysis and Optimization - 8 register allocation
Unity C # e-learning (10) -- unitywebrequest (2)
kubernetes的Controller之deployment
Sorted out a batch of script standard function modules (version 2021)
Unity C # e-learning (10) -- unitywebrequest (1)
使用卷积对数据进行平滑处理
5张图诠释了容器网络
Unity C # e-learning (IX) -- wwwfrom
shell脚本多进程并发写法实例(高阶修炼)
Notes on writing questions in C language -- table tennis competition
Kubernetes的pod调度
设计人员拿到的工程坐标系等高线CAD图如何加载进图新地球
手机股票注册开户安全吗,有没有什么风险?
Restcloud ETL extraction de données de table de base de données dynamique
网上找客户经理办理股票开户安全吗??
Optimizing for vectorization
Unity uses skybox panoramic shader to make panorama preview. There is a gap. Solution
杜老师说网站更新图解
R language uses GLM function to build Poisson logarithm linear regression model, processes three-dimensional contingency table data to build saturation model, uses step function to realize stepwise re
Is it safe to open an account by digging money? Is there any risk?