【Hadoop】FSDirectory詳解
簡(jiǎn)介
Namenode最重要的兩個(gè)功能之一就是維護整個(gè)文件系統的目錄樹(shù)(即命名空間namesystem) 。
HDFS文件系統的命名空間(namespace) , 也就是以“/”為根的整個(gè)目錄樹(shù), 是通過(guò)FSDirectory類(lèi)來(lái)管理的。 FSNamesystem也提供了管理目錄樹(shù)結構的方法。
FSNamesystem中的方法多是調用FSDirectory類(lèi)的實(shí)現。FSNamesystem在FSDirectory類(lèi)方法的基礎上添加了editlog日志記錄的功能。
FSDirectory的操作則全部是在內存中進(jìn)行的, 并不進(jìn)行editlog的日志記錄。
參數
參數 | 默認值 | 描述 |
---|---|---|
dfs.permissions.enabled | true | 是否開(kāi)啟權限管理 |
dfs.permissions.superusergroup | supergroup | 超級用戶(hù)組 |
dfs.namenode.acls.enabled | true | 設置為true以啟用對HDFS ACL(訪(fǎng)問(wèn)控制列表)的支持。3.3.1版本默認啟用ACL |
dfs.namenode.posix.acl.inheritance.enabled | true | 是否啟用POSIX格式的ACL權限 |
dfs.namenode.xattrs.enabled | true | 是否支持擴展namenode的屬性。 |
dfs.namenode.fs-limits.max-xattr-size | 16384 | 以字節為單位的擴展屬性的名稱(chēng)和值的最大組合大小。它應該大于0,小于或等于32768。 |
dfs.namenode.accesstime.precision | 3600000 | HDFS文件訪(fǎng)問(wèn)時(shí)間的精確值,默認為1小時(shí)。當為0時(shí),表示禁用。 |
dfs.quota.by.storage.type.enabled | true | 如果為true,則啟用基于存儲類(lèi)型的配額。 |
dfs.ls.limit | 1000 | 限制ls打印的文件數。如果小于或等于零,最多將打印 DFS_LIST_LIMIT_DEFAULT (= 1000)。 |
dfs.content-summary.limit | 5000 | 在一個(gè)鎖定周期中允許的最大內容摘要計數。0或負數意味著(zhù)沒(méi)有限制。 |
dfs.content-summary.sleep-microsec | 500 | 在內容匯總計算中,兩次請求鎖的時(shí)間。 |
dfs.namenode.fs-limits.max-component-length | 255 | 定義路徑中每個(gè)組件中UTF-8編碼的最大字節數。0的值將禁用檢查。 |
dfs.namenode.fs-limits.max-directory-items | 1024*1024 | 定義目錄可能包含的最大項目數。無(wú)法將屬性設置為小于1或大于6400000的值。 |
dfs.namenode.fs-limits.max-xattrs-per-inode | 32 | 每個(gè)索引節點(diǎn)的擴展屬性的最大數目。 |
dfs.protected.subdirectories.enable | false | 是否保護 fs.protected.directories 上設置的目錄的子目錄。 |
dfs.namenode.name.cache.threshold | 10 | 經(jīng)常訪(fǎng)問(wèn)的文件訪(fǎng)問(wèn)次數超過(guò)了這個(gè)閾值,緩存在FSDirectory nameCache中。 |
dfs.namenode.quota.init-threads | 12 | quota初始化并發(fā)線(xiàn)程的數量。 |
常量
- INodeDirectory rootDir: 整個(gè)文件系統目錄樹(shù)的根節點(diǎn), 是INodeDirectory類(lèi)型的 。
- FSNamesystem namesystem: Namenode的門(mén)面類(lèi), 這個(gè)類(lèi)主要支持對數據塊進(jìn)行操作的一些方法, 例如addBlock()。
- INodeMap inodeMap: 記錄根目錄下所有的INode,并維護INodeId ->INode的映射關(guān)系。
- ReentrantReadWriteLock dirLock: 對目錄樹(shù)以及inodeMap字段操作的鎖。
- NameCache
nameCache: 將常用的name緩存下來(lái), 以降低byte[]的使用, 并降低JVM heap的使用。 - SortedSet
protectedDirectories:使用 dfs.namenode.protected.directories 設置保護的一組目錄。 這些目錄不能被刪除,除非它們是空的。 - FSEditLog editLog: 用于寫(xiě)editlog的類(lèi)。
- HdfsFileStatus[] reservedStatuses: 待定。
- INodeAttributeProvider attributeProvider:用于實(shí)現權限管理。
操作類(lèi)型
所有客戶(hù)端的操作都是通過(guò)FSNamesystem.java 的。FSNamesystem.java 會(huì )調用具體操作的實(shí)現類(lèi)的。再實(shí)現類(lèi)里面操作時(shí)會(huì )使用到FSDirectory。
刪除
接口:
boolean delete(String src, boolean recursive, boolean logRetryCache) throws IOException {}
簡(jiǎn)介
刪除文件或者文件夾,如果刪除文件夾參數recursive必須為true。
實(shí)現邏輯
- 1、檢查是否有寫(xiě)權限。具體可查看
checkOperation(OperationCategory.WRITE)
; - 2、加全局鎖。
- 3、再次檢查是否有寫(xiě)權限。
- 4、調用FSDirDeleteOp.delete刪除目錄或者文件。
toRemovedBlocks = FSDirDeleteOp.delete(this, pc, src, recursive, logRetryCache);
- 5、釋放全局鎖。
- 6、同步editlog,并且記錄審計日志。
- 7、將需要刪除的塊
toRemovedBlocks
添加到markedDeleteQueue
隊列里面,等待異步刪除。
FSDirDeleteOp.delete 實(shí)現邏輯
- 檢查權限:調用FSDirectory的函數checkPermission檢查權限。
- 如果是非空的文件夾,檢查是否有-r參數。如果沒(méi)有-r參數則需要報錯。
- 調用deleteInternal,開(kāi)始刪除文件夾。核心刪除代碼如下:
List<INodeDirectory> snapshottableDirs = new ArrayList<>();
FSDirSnapshotOp.checkSnapshot(fsd, iip, snapshottableDirs);
ReclaimContext context = new ReclaimContext(
fsd.getBlockStoragePolicySuite(), collectedBlocks, removedINodes,
removedUCFiles);
// 更核心的刪除代碼再這個(gè)函數里面,會(huì )調用destroyAndCollectBlocks刪除block,代碼:targetNode.destroyAndCollectBlocks(reclaimContext);
if (unprotectedDelete(fsd, iip, context, mtime)) {
filesRemoved = context.quotaDelta().getNsDelta();
fsn.removeSnapshottableDirs(snapshottableDirs);
}
fsd.updateReplicationFactor(context.collectedBlocks()
.toUpdateReplicationInfo());
fsd.updateCount(iip, context.quotaDelta(), false);
- 刪除EditLog。
- 調用incrDeletedFileCount更新metrics信息。
創(chuàng )建文件
接口
HdfsFileStatus startFile(String src, PermissionStatus permissions,
String holder, String clientMachine, EnumSet<CreateFlag> flag,
boolean createParent, short replication, long blockSize,
CryptoProtocolVersion[] supportedVersions, String ecPolicyName,
String storagePolicy, boolean logRetryCache) throws IOException {
}
-
檢查當前用戶(hù)是否有寫(xiě)權限。
-
檢查是否處于安全模式,如果處于安全模式,則不能進(jìn)行當前操作。
-
檢查是否對當前文件所在的目錄是否有權限(開(kāi)啟權限管理的情況下)
-
調用FSDirWriteFileOp.startFile開(kāi)始創(chuàng )建文件或者覆蓋已有文件。
- 對于已經(jīng)存在的文件。在覆蓋的場(chǎng)景下。主要核心代碼如下,會(huì )將原來(lái)的文件刪除。并且釋放租約。
List<INode> toRemoveINodes = new ChunkedArrayList<>(); List<Long> toRemoveUCFiles = new ChunkedArrayList<>(); long ret = FSDirDeleteOp.delete(fsd, iip, toRemoveBlocks, toRemoveINodes, toRemoveUCFiles, now()); if (ret >= 0) { iip = INodesInPath.replace(iip, iip.length() - 1, null); FSDirDeleteOp.incrDeletedFileCount(ret); fsn.removeLeasesAndINodes(toRemoveUCFiles, toRemoveINodes, true); }
- 對于不需要覆蓋的場(chǎng)景下,需要重新刷新租約信息。
fsn.recoverLeaseInternal(FSNamesystem.RecoverLeaseOp.CREATE_FILE, iip, src, holder, clientMachine, false);
- 對于父文件夾存在的時(shí)候,將文件添加到父文件夾下面。
iip = addFile(fsd, parent, iip.getLastLocalName(), permissions, replication, blockSize, holder, clientMachine, shouldReplicate, ecPolicyName, storagePolicy); newNode = iip != null ? iip.getLastINode().asFile() : null;
-
添加租約信息。
fsn.leaseManager.addLease(
newNode.getFileUnderConstructionFeature().getClientName(),
newNode.getId());
- 返回文件信息。
待續。

0 評論