FileSystemRMStateStore、LeveldbRMStateStore、ZKRMStateStore 詳細對比分析
一、概述對比
| 特性 | FileSystemRMStateStore | LeveldbRMStateStore | ZKRMStateStore |
| 存儲后端 | Hadoop FileSystem (HDFS/S3/本地) | LevelDB 嵌入式數據庫 | ZooKeeper 分布式協(xié)調服務(wù) |
| 代碼行數 | ~1018 行 | ~797 行 | ~1493 行 |
| 版本 | 1.3 | 1.1 | 1.5 |
| 依賴(lài) | Hadoop FileSystem API | leveldbjni (JNI) | Apache Curator + Zookeeper |
| 架構類(lèi)型 | 主從式 (共享存儲) | 單機嵌入式 | 分布式共識 |
| 一致性模型 | 最終一致性 (依賴(lài)FS) | 強一致性 | 強一致性 (ZAB協(xié)議) |
二、存儲架構對比
2.1 FileSystemRMStateStore - 目錄/文件結構
hdfs://namenode:8020/rmstate/FSRMStateRoot/
├── RMVersionNode # 版本信息
├── EpochNode # Epoch計數器
├── RMDTSecretManagerRoot/ # 委托令牌
│ ├── DelegationKey_<id>
│ ├── RMDelegationToken_<seq>
│ └── RMDTSequenceNumber_<seq>
├── AMRMTokenSecretManagerRoot/ # AMRM令牌
│ └── AMRMTokenSecretManagerNode
├── RMAppRoot/ # 應用狀態(tài)
│ └── <ApplicationId>/
│ ├── <ApplicationId>
│ └── attempt_<id>
├── ReservationSystemRoot/ # 資源預留
│ └── <PlanName>/
└── ProxyCARoot/ # CA證書(shū)
├── caCert
└── caPrivateKey
特點(diǎn):
- 樹(shù)形目錄結構
- 每個(gè)狀態(tài)項對應一個(gè)文件
- 使用文件重命名保證原子性
2.2 LeveldbRMStateStore - Key-Value 結構
數據庫: yarn-rm-state (LevelDB)
Key | Value
--------------------------------------|------------------------------
RMVersionNode | VersionProto
EpochNode | EpochProto
RMDTSecretManagerRoot/DelegationKey_<id> | DelegationKey
RMDTSecretManagerRoot/RMDelegationToken_<seq> | TokenData
RMDTSecretManagerRoot/RMDTSequentialNumber | Int
RMAppRoot/application_<id> | ApplicationStateDataProto
AMRMTokenSecretManagerRoot | AMRMTokenStateProto
ProxyCARoot/caCert | X509Certificate (DER)
ProxyCARoot/caPrivateKey | PrivateKey (DER)
ReservationSystemRoot/<plan>/<res_id> | ReservationProto
特點(diǎn):
- 扁平化 Key-Value 存儲
- Key 使用路徑風(fēng)格 (
/)
- 內置 B+Tree 索引
2.3 ZKRMStateStore - Znode 層次結構
/yarn rm/ZKRMStateRoot/
├── VERSION_INFO # 版本
├── EPOCH_NODE # Epoch
├── RM_ZK_FENCING_LOCK # 鎖節點(diǎn) (HA)
├── RMAppRoot/
│ ├── HIERARCHIES/ # 分層索引 (1-4)
│ │ ├── 1/application_1
│ │ │ └── application_1234_0001_01 # 嘗試狀態(tài)
│ │ ├── 2/application_12
│ │ │ └── application_34_0001_01
│ │ └── ...
│ └── application_<id>
│ └── attempt_<id>
├── RMDTSecretManagerRoot/
│ ├── RMDTSequentialNumber # 序列號
│ ├── RMDTMasterKeysRoot/
│ │ └── Key_<id>
│ └── RMDelegationTokensRoot/
│ ├── 1/Token_1
│ │ └── Token_1234
│ └── ...
├── AMRMTokenSecretManagerRoot/
│ ├── currentMasterKey
│ └── nextMasterKey
├── ReservationSystemRoot/
│ └── <PlanName>/
│ └── <ReservationId>
└── ProxyCARoot/
├── caCert
└── caPrivateKey
特點(diǎn):
- 分層目錄設計 (優(yōu)化 ZK 節點(diǎn)數量)
- 支持節點(diǎn)分割 (split index 1-4)
- 內置 ACL 權限控制
- 臨時(shí)節點(diǎn)用于 HA 鎖
三、核心功能實(shí)現對比
3.1 應用狀態(tài)管理
存儲操作
| 實(shí)現 | 存儲方式 | 原子性保證 |
| FileSystemRMStateStore | 臨時(shí)文件 + rename (2-3次IO) | 依賴(lài)文件系統 rename |
| LeveldbRMStateStore | 直接 db.put() (1次IO) | LevelDB 事務(wù) |
| ZKRMStateStore | safeCreate() + 事務(wù) (多次IO) | ZK 事務(wù) (Multi) |
// FileSystemRMStateStore - 臨時(shí)文件策略
protected void writeFile(Path outputPath, byte[] data, boolean makeUnreadableByAdmin) {
Path tempPath = new Path(outputPath.getParent(), outputPath.getName() + ".tmp");
fsOut = fs.create(tempPath, true);
fsOut.write(data);
fsOut.close();
fs.rename(tempPath, outputPath); // 原子重命名
}
// LeveldbRMStateStore - 直接寫(xiě)入
protected void storeApplicationStateInternal(ApplicationId appId, ApplicationStateData appStateData) {
db.put(bytes(key), appStateData.getProto().toByteArray());
}
// ZKRMStateStore - 安全創(chuàng )建
public synchronized void storeApplicationStateInternal(ApplicationId appId,
ApplicationStateData appStateDataPB) throws Exception {
String nodeCreatePath = getLeafAppIdNodePath(appId.toString(), true);
zkManager.safeCreate(nodeCreatePath, appStateData, zkAcl,
CreateMode.PERSISTENT, zkAcl, fencingNodePath);
}
3.2 委托令牌管理
| 實(shí)現 | 令牌存儲 | 序列號存儲 | 原子性 |
| FileSystemRMStateStore | 單獨文件 | 單獨文件 | ? 不保證 |
| LeveldbRMStateStore | WriteBatch | WriteBatch | ? 保證 |
| ZKRMStateStore | 事務(wù) | 事務(wù) | ? 保證 |
// FileSystemRMStateStore - 分開(kāi)存儲,存在不一致風(fēng)險
private void storeOrUpdateRMDelegationTokenState(...) {
writeFileWithRetries(nodeCreatePath, identifierData.toByteArray(), true);
// 序列號單獨存儲...
if (dtSequenceNumberPath == null) {
createFileWithRetries(latestSequenceNumberPath);
} else {
renameFileWithRetries(dtSequenceNumberPath, latestSequenceNumberPath);
}
}
// LeveldbRMStateStore - 原子批量操作
private void storeOrUpdateRMDT(...) {
try (WriteBatch batch = db.createWriteBatch()) {
batch.put(bytes(tokenKey), tokenData.toByteArray());
if (!isUpdate) {
batch.put(bytes(RM_DT_SEQUENCE_NUMBER_KEY), bs.toByteArray());
}
db.write(batch); // 原子提交
}
}
// ZKRMStateStore - ZK 事務(wù)
protected synchronized void storeRMDelegationTokenState(...) {
SafeTransaction trx = zkManager.createTransaction(zkAcl, fencingNodePath);
trx.create(nodeCreatePath, identifierData.toByteArray(), zkAcl, CreateMode.PERSISTENT);
trx.setData(dtSequenceNumberPath, seqOs.toByteArray(), -1);
trx.commit(); // 原子提交
}
3.3 刪除操作
| 實(shí)現 | 應用刪除 | 嘗試刪除 | 批量刪除 |
| FileSystemRMStateStore | 遞歸刪除目錄 | 單獨刪除 | ? 無(wú) |
| LeveldbRMStateStore | WriteBatch 刪除 | WriteBatch 刪除 | ? 支持 |
| ZKRMStateStore | safeDelete + 層級清理 | safeDelete | ? 支持 |
四、高可用特性對比
4.1 HA 支持
| 特性 | FileSystemRMStateStore | LeveldbRMStateStore | ZKRMStateStore |
| HA 支持 | ? 支持 (共享存儲) | ? 不支持 | ? 支持 |
| Fencing 機制 | ? 無(wú) | ? 無(wú) | ? 有 |
| Epoch 管理 | ? 有 | ? 有 | ? 有 |
| 腦裂防護 | 依賴(lài)共享存儲 | 不支持 | ZK 鎖 |
4.2 ZKRMStateStore 專(zhuān)用 HA 特性
// Fencing 鎖節點(diǎn)
private static final String FENCING_LOCK = "RM_ZK_FENCING_LOCK";
private String fencingNodePath;
// 驗證活躍狀態(tài)線(xiàn)程
private class VerifyActiveStatusThread extends Thread {
@Override
public void work() {
while (!isFencedState()) {
// 周期性創(chuàng )建/刪除 fence 節點(diǎn)
zkManager.createTransaction(zkAcl, fencingNodePath).commit();
Thread.sleep(zkSessionTimeout);
}
}
}
// 安全事務(wù) - 帶 fencing
public void safeCreate(String path, ...) {
SafeTransaction trx = zkManager.createTransaction(zkAcl, fencingNodePath);
trx.create(path, data, acl, mode);
trx.commit();
}
4.3 ZKRMStateStore 分層優(yōu)化
// 應用ID分層存儲 - 避免單節點(diǎn)children過(guò)多
// 配置: yarn.resourcemanager.zk-appid-node-split-index
// splitIndex=2 時(shí): application_12 / application_34_0001
private Map<Integer, String> rmAppRootHierarchies;
for (int splitIndex = 1; splitIndex <= 4; splitIndex++) {
rmAppRootHierarchies.put(splitIndex,
getNodePath(hierarchiesPath, Integer.toString(splitIndex)));
}
五、可靠性機制對比
5.1 原子性保證
| 實(shí)現 | 機制 | 依賴(lài) |
| FileSystemRMStateStore | .tmp/.new 文件 + rename | 文件系統原子性 |
| LeveldbRMStateStore | WriteBatch | LevelDB WAL |
| ZKRMStateStore | SafeTransaction (Multi) | ZAB 協(xié)議 |
5.2 故障恢復
| 實(shí)現 | 恢復機制 | 不完整記錄處理 |
| FileSystemRMStateStore | 手動(dòng)清理 .tmp 文件 | checkAndRemovePartialRecord() |
| LeveldbRMStateStore | 自動(dòng)恢復 | LevelDB 自動(dòng)應用 WAL |
| ZKRMStateStore | 自動(dòng)恢復 | ZK 自動(dòng)處理 |
5.3 重試機制
| 實(shí)現 | 重試方式 | 配置參數 |
| FileSystemRMStateStore | FSAction.runWithRetries() | fsNumRetries=15, fsRetryInterval=1000ms |
| LeveldbRMStateStore | LevelDB 內置 | 無(wú)需配置 |
| ZKRMStateStore | Curator 內置重試 | zkSessionTimeout, retryPolicy |
六、性能對比
6.1 IO 操作次數
| 操作 | FileSystemRMStateStore | LeveldbRMStateStore | ZKRMStateStore |
| 存儲應用狀態(tài) | 2-3 次 (tmp+rename) | 1 次 (put) | 1-2 次 |
| 更新應用狀態(tài) | 3 次 (new+delete+rename) | 1 次 (put) | 1 次 |
| 刪除應用 | N+1 次 | 1 次 (batch) | 多次 (遞歸) |
| 存儲令牌+序列號 | 2-4 次 | 1 次 (batch) | 1 次 (事務(wù)) |
6.2 數據組織
| 特性 | FileSystemRMStateStore | LeveldbRMStateStore | ZKRMStateStore |
| 數據索引 | 無(wú) (文件名) | B+Tree | Znode 路徑 |
| 范圍查詢(xún) | 低效 | 高效 | 中等 |
| 壓縮 | 無(wú) | Snappy | 無(wú) |
| 緩存 | HDFS DataNode | BlockCache | ZK Client Cache |
| 節點(diǎn)限制 | 無(wú) | 磁盤(pán)容量 | ZK 單節點(diǎn) 1MB |
七、安全性對比
7.1 權限控制
| 實(shí)現 | 權限機制 | 加密支持 |
| FileSystemRMStateStore | HDFS ACLs, XAttr | HDFS 加密區域 |
| LeveldbRMStateStore | 文件系統權限 | 無(wú) |
| ZKRMStateStore | ZK ACLs (Digest/SASL) | SSL/TLS |
八、配置對比
FileSystemRMStateStore
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.FileSystemRMStateStore</value>
</property>
<property>
<name>yarn.resourcemanager.fs.state-store.uri</name>
<value>hdfs://namenode:8020/rmstate</value>
</property>
<property>
<name>yarn.resourcemanager.fs.state-store.num-retries</name>
<value>15</value>
</property>
<property>
<name>yarn.resourcemanager.fs.state-store.retry-interval-ms</name>
<value>1000</value>
</property>
LeveldbRMStateStore
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.LeveldbRMStateStore</value>
</property>
<property>
<name>yarn.resourcemanager.leveldb.state-store.path</name>
<value>/var/log/yarn/rmstate</value>
</property>
<property>
<name>yarn.resourcemanager.leveldb.compaction-interval-secs</name>
<value>3600</value>
</property>
ZKRMStateStore
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
<property>
<name>yarn.resourcemanager.zk.state-store.parent-path</name>
<value>/yarn rm</value>
</property>
<property>
<name>yarn.resourcemanager.zk.timeout-ms</name>
<value>10000</value>
</property>
<property>
<name>yarn.resourcemanager.zk.num-retries</name>
<value>3</value>
</property>
<property>
<name>yarn.resourcemanager.zk.znode-size-limit-bytes</name>
<value>10485760</value>
</property>
九、優(yōu)缺點(diǎn)總結
FileSystemRMStateStore
| 優(yōu)點(diǎn) | 缺點(diǎn) |
| ? 共享存儲支持,適合 HA | ? IO 開(kāi)銷(xiāo)大 |
| ? 生態(tài)系統集成 | ? 原子性依賴(lài)外部文件系統 |
| ? 跨平臺 (HDFS/S3/本地) | ? 令牌和序列號分開(kāi)存儲 |
| ? 簡(jiǎn)單直觀(guān) | ? 性能一般 |
LeveldbRMStateStore
| 優(yōu)點(diǎn) | 缺點(diǎn) |
| ? 高性能 (嵌入式) | ? 單機限制 |
| ? WriteBatch 原子性 | ? 無(wú)法跨機器共享 |
| ? 內置索引和壓縮 | ? 不適合 HA |
| ? 故障自動(dòng)恢復 | ? 容量受單機磁盤(pán)限制 |
ZKRMStateStore
| 優(yōu)點(diǎn) | 缺點(diǎn) |
| ? 分布式一致性 | ? 依賴(lài) ZK 集群 |
| ? HA 成熟方案 | ? ZK 節點(diǎn)大小限制 (1MB) |
| ? Fencing 機制 | ? 性能受網(wǎng)絡(luò )延遲影響 |
| ? ACL 權限控制 | ? 需要額外維護 ZK |
十、選擇決策樹(shù)
場(chǎng)景選擇決策樹(shù)
│
▼
┌───────────────────────────┐
│ 是否有 HA 需求? │
└───────────────────────────┘
/ \
是 否
/ \
┌─────────────────┐ ┌─────────────────┐
│ 是否有共享存儲? │ │ 性能要求如何? │
└─────────────────┘ └─────────────────┘
/ \ / \
是 否 高 低
/ \ / \
┌──────────────────┐ ┌──────────┐┌──────────┐ ┌──────────────┐
│ FileSystemRMState│ │ ZKRM ││ Leveldb │ │ MemoryRM │
│ Store (HDFS) │ │StateStore││StateStore│ │ StateStore │
└──────────────────┘ └──────────┘└──────────┘ └──────────────┘
推薦場(chǎng)景
| 場(chǎng)景 | 推薦方案 | 原因 |
| 生產(chǎn) HA 集群 | ZKRMStateStore | 成熟 HA 方案,fencing 支持 |
| HDFS 已有 | FileSystemRMStateStore | 共享存儲利用 |
| 開(kāi)發(fā)測試 | LeveldbRMStateStore | 簡(jiǎn)單高性能 |
| 小規模/邊緣 | LeveldbRMStateStore | 無(wú)外部依賴(lài) |
| 超大規模集群 | ZKRMStateStore | 分層優(yōu)化 |
十一、版本演進(jìn)對比
| 版本 | FileSystemRMStateStore | LeveldbRMStateStore | ZKRMStateStore |
| 1.0 | 初始版本 | 初始版本 | 初始版本 |
| 1.1 | - | 預留系統 | - |
| 1.2 | AMRMToken 分離 | - | AMRMToken 分離 |
| 1.3 | 預留系統 | - | 預留系統 |
| 1.4 | - | - | 應用節點(diǎn)分層 |
| 1.5 | - | - | 令牌節點(diǎn)分層 |
十二、總結
一句話(huà)選擇
- 生產(chǎn) HA: 首選 ZKRMStateStore(成熟穩定,fencing 支持)
- 共享存儲環(huán)境: 使用 FileSystemRMStateStore(利用現有 HDFS)
- 開(kāi)發(fā)測試/輕量級: 選擇 LeveldbRMStateStore(高性能,低依賴(lài))
核心差異
| 維度 | FileSystemRMStateStore | LeveldbRMStateStore | ZKRMStateStore |
| 架構 | 主從 (共享存儲) | 單機嵌入 | 分布式共識 |
| 一致性 | 最終一致 | 強一致 | 強一致 |
| HA | 依賴(lài)存儲 | 不支持 | 原生支持 |
| 性能 | 中 | 高 | 中 |
| 復雜度 | 低 | 低 | 高 |
| 運維 | 簡(jiǎn)單 | 簡(jiǎn)單 | 需維護 ZK |
三種實(shí)現各有適用場(chǎng)景,選擇時(shí)需綜合考慮:
- 是否需要 HA
- 基礎設施條件 (是否有共享存儲/ZK 集群)
- 性能要求
- 運維復雜度容忍度