同步操作将从 shishan100/儒猿分布式小文件系统 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
儒猿自研分布式小文件存储系统。
定位: 小文件存储 ——> 几KB~几百MB之间的文件存储。
EditLog
的存储采用ProtoBuf序列化 + 自定义头
存储。
比如一个文件有2条EditLog
EditLog
经过ProtoBuf序列化
之后,得到的byte数组长度为18EditLog
经过ProtoBuf序列化
之后,得到的byte数组长度为25那EditLog
文件的内容如下:
第一条EditLog 第二条EditLog
+--------+-------------------------+--------+-----------------------------+
| Length | Actual Content (18byte) | Length | Actual Content (25byte) |
| 0x0012 | EditLog Serialization | 0x0019 | EditLog Serialization |
+--------+-------------------------+--------+-----------------------------+
内存目录树 + txId
持久化在同一个FsImage
文件中,将时间戳拼接在文件名称:
fsimage-1624846255954
fsimage-1624846265954
fsimage-1624846275954
在保存完成FsImage
文件之后,BackupNode
和NameNode
都会做如下操作:
FsImage
文件,将文件按时间戳降序排序。FsImage
文件,直到找到一个格式合法的FsImage
文件。
FsImage
文件不合法,保存到一半的时候BackupNode
宕机了,或者BackupNode
传给NameNode
的时候传了一半内容,BackupNode
宕机了,导致整个文件不完整FsImage
文件,只保留第2个FSImage
文件NameNode
基于第2步得到的FsImage
文件,读取其中的TxId
,删除比TxId
小的EditLog
文件其中FsImage
文件格式如下:
+----------------+----------+--------+-------------------+
| 4 byte | 8 byte | Content |
| Content Length | maxTxId | FSDirectory Serialization |
+----------------+----------+----------------------------+
其中校验FSImage文件的合法性,只需要读取前4个字节,得到文件长度,然后校验文件的长度是否相等即可。
每个DataNode从配置的根目录下面创建一个storage文件夹,里面创建000-255个文件夹,每个文件夹内再创建000-256个文件夹,总共65535个文件夹
当需要储存一个文件的时候,根据文件全路径转换后得到一个字符串,字符串经过hash取模65535,定位到目标文件夹,文件保存在目标文件夹。
举个例子:
假设需要储存文件
/user1/aaa/bbb/c.jpg
, 转换后得到字符串为:user1-aaa-bbb-c.jpg
, 经过hash取模65535,结果为/210/102/
, 则文件保存在:{baseDir}/storage/210/102/user1-aaa-bbb-c.jpg
。
经过这样转换后所有的文件都会存放在65536个文件夹中,存储文件层级永远是3层。(无论你的文件全路径是/a.jpg
还是/a/a/a/a/a/a/a/a.jpg
)
DataNode是一个基于key-value的对象存储库,对于/aaa/bbb/c.jpg
的字符串,DataNode理解是一个key,而不是一个文件目录,可以达到快速访问文件的目的。
配合NameNode提供文件目录树,对外表现是一个文件目录树,但是文件存储本质上是一个key-value对象存储。
目前实现了几种方式有几种转换方式:
/user1/aaa/bbb/c.jpg
转换成user1-aaa-bbb-c.jpg
在65536个文件夹中,除了存储每个文件本身之外,还新建了一个文件storage.info文件。
在DataNode
启动的时候,扫描65536个文件夹的storage.info内容,得到每个文件夹内的文件存储信息,然后往NameNode上报。
BackupNode除了承担拉取EditLog文件,定时进行Checkpoint生成FsImage文件功能之外,还承担着容灾的职责。
当NameNode出现故障的时候,BackupNode需要主动升级为NameNode,并通知客户端和DataNode进行切换。所以各个节点需要做以下事情:
宕机的NameNode作为BackupNode重启后,同样执行上面的过程。
NameNode中的元数据保存在内存目录树中,一旦文件数量过多. (1亿条大概评估需要内存2.5GB),则一台NameNode机器的内存放不下, 所以要设计多NameNode进行元数据分片机制。
多NameNode节点数据分片规则可以有几种选择:
目前实现为第二种,一致性hash算法可以采用16383个虚拟节点的方式,平均打散分配到每个节点。
新节点上线后,发送选票给旧节点,旧节点发现已经有Controller,返回强制性选票给新节点,新节点遇到强制性选票则无条件确定就集群的Controller节点
假设一开始3个节点,需要新增两个节点,按顺序启动,此时Controller可能会收到2个重平衡请求,需要入队串行化处理。
假设现在有3个NameNode节点:namenode01、namenode02、namenode03,其中namenode02挂着一个backupnode01.
集群中发起的连接状态正常是:
namenode02 -> namenode01
namenode03 -> namenode02
namenode03 -> namenode01
假设此时namenode01宕机了,backupnode01作为备份节点升级为namenode节点。此时集群中的节点需要变成以下状态:
namenode02 -> namenode01 namenode02 -> backupnode01
namenode03 -> namenode02 --> namenode03 -> namenode02
namenode03 -> namenode01 namenode03 -> backupnode01
应该如何做呢?这里分为几个步骤:
此时节点之间的连接状态是这样的
namenode02 -> namenode01
namenode03 -> namenode02
namenode03 -> namenode01
backupnode01 -> namenode02
backupnode01 -> namenode03
接着namenode02和namenode03收到请求之后,发现这个节点id比我小,还往我这里发起连接,所以他们这个时候就知道了namenode01节点已经被备份节点顶替了。
此时namenode02和namenode03首先会作为服务端关闭这些连接:
backupnode01 -> namenode02
backupnode01 -> namenode03
然后namenode02、namenode03会主动发起往backupnode01的链接。这个时候backupnode01发现连接变成了这样:
backupnode01 -> namenode02
backupnode01 -> namenode03
namenode02 -> backupnode01
namenode03 -> backupnode01
backupnode01就会关闭作为客户端主动往namenode02和namenode03发起的连接,最终整个集群的链接状态保持成这样:
namenode02 -> backupnode01
namenode03 -> namenode02
namenode03 -> backupnode01
cd ruyuan-dfs-common && mvn protobuf:compile
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。