临汾做网站公司哪家好,桂林旅游必去十大景点,wordpress会员可见插件,青海网站维护HDFS的standby节点启动过慢原因分析以及应对策略 1. NN启动大致流程2. Editlog日志清理策略2.1 为什么需要合并editlog#xff1f;2.2 什么时候删除editlog#xff1f; 3. NN启动的日志加载策略4. Standby启动慢应对策略5. 疑问和思考5.1 如何人工阅读editlog和fsimage文件的… HDFS的standby节点启动过慢原因分析以及应对策略 1. NN启动大致流程2. Editlog日志清理策略2.1 为什么需要合并editlog2.2 什么时候删除editlog 3. NN启动的日志加载策略4. Standby启动慢应对策略5. 疑问和思考5.1 如何人工阅读editlog和fsimage文件的内容5.2 checkpoint的触发策略是什么5.3 如果删除editlog失效导致保存过多的editlog如果nn重启启动过程是否会很长5.4 如果standby长期宕机active重启后有没有快速恢复的办法5.5 如何人工触发checkpoint 6. 参考文档 在hdfs的nn重启过程时以standby的方式进行启动其中当前节点的fsimage和active节点的editlog数量对启动时间起到关键性的影响。本问题探讨hdfs的active节点正常当standby节点重启时重启过慢的原因分析以及应对的策略。 为了分析出standby节点启动慢的原因有必要分析和了解nn启动过程中在做什么事情才能进一步分析慢在哪里以及怎么优化。
1. NN启动大致流程
这里不探讨nn启动过程中复杂的代码逻辑实现梳理整体上nn启动时nn在能处理client的请求之前必须完成以下几步
从fsimage文件中读取系统metadata读取edit logs并把记录在其中的操作合并到系统metadata中去生成一个新的checkpoint新的fsimage必须和旧fsimage加上edit log上操作保持一致保持safe mode直到Datanodes上报足够数量的block信息节点状态升级为standby集群状态恢复可以给客户端提供服务
图形如下 #mermaid-svg-Q6n0HX0ZAzhJIGro {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Q6n0HX0ZAzhJIGro .error-icon{fill:#552222;}#mermaid-svg-Q6n0HX0ZAzhJIGro .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Q6n0HX0ZAzhJIGro .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-Q6n0HX0ZAzhJIGro .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Q6n0HX0ZAzhJIGro .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Q6n0HX0ZAzhJIGro .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Q6n0HX0ZAzhJIGro .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Q6n0HX0ZAzhJIGro .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Q6n0HX0ZAzhJIGro .marker.cross{stroke:#333333;}#mermaid-svg-Q6n0HX0ZAzhJIGro svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Q6n0HX0ZAzhJIGro .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Q6n0HX0ZAzhJIGro .cluster-label text{fill:#333;}#mermaid-svg-Q6n0HX0ZAzhJIGro .cluster-label span{color:#333;}#mermaid-svg-Q6n0HX0ZAzhJIGro .label text,#mermaid-svg-Q6n0HX0ZAzhJIGro span{fill:#333;color:#333;}#mermaid-svg-Q6n0HX0ZAzhJIGro .node rect,#mermaid-svg-Q6n0HX0ZAzhJIGro .node circle,#mermaid-svg-Q6n0HX0ZAzhJIGro .node ellipse,#mermaid-svg-Q6n0HX0ZAzhJIGro .node polygon,#mermaid-svg-Q6n0HX0ZAzhJIGro .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Q6n0HX0ZAzhJIGro .node .label{text-align:center;}#mermaid-svg-Q6n0HX0ZAzhJIGro .node.clickable{cursor:pointer;}#mermaid-svg-Q6n0HX0ZAzhJIGro .arrowheadPath{fill:#333333;}#mermaid-svg-Q6n0HX0ZAzhJIGro .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Q6n0HX0ZAzhJIGro .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Q6n0HX0ZAzhJIGro .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-Q6n0HX0ZAzhJIGro .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-Q6n0HX0ZAzhJIGro .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Q6n0HX0ZAzhJIGro .cluster text{fill:#333;}#mermaid-svg-Q6n0HX0ZAzhJIGro .cluster span{color:#333;}#mermaid-svg-Q6n0HX0ZAzhJIGro div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Q6n0HX0ZAzhJIGro :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 启动服务 加载fsimage 拉取editlog进行数据合并 进行checkpoint 通知active拉取fsimage safe mode 上报block 启动完成 说明
启动时会调用jn的rpc接口拉取editlog进行合并值得注意的是editlog信息并不会写入到本地的editlog文件中而是加载到当前节点的内存中进行数据合并因此standby节点的editlog会被active节点少standby完成checkpoint后生成fsimage文件后通知acrive节点active节点通过jn的GET接口拉取fsimage完成checkpoint同步editlog合并、checkpoint生成fsimage依赖机器的内存、磁盘io性能并且如果需要合并的editlog文件很多就会导致启动过程很慢
根据生产经验在大多数情况下造成nn启动慢的原因是在拉取editlog进行数据合并环节耗时过多针对该问题进行重点分析。
2. Editlog日志清理策略
在HA架构下fsimage checkpoint后的editlog组成了完整的数据但是不代表hdfs的nn节点只保存checkpoint后的editlog。事实上nn拥有自己的保存策略。在讨论这个问题前我觉得有必要回顾一下为什么需要合并editlog以及合并editlog的策略是什么。
2.1 为什么需要合并editlog
在client写数据是在一致性流程中我们在HDFS高可用架构涉及常用功能整理进行了梳理editlog会通过append的方式记录数据写入的相关操作在获得极致的写入性能同时却牺牲了数据的组织性因此难以通过查询editlog的方式组织数据结构。这就会导致一个问题editlog持续写入如果不进行数据合并就会导致editlog越来越多最后难以管理特别是重启后需要重新回放所有的editlog这是难以接受的。所以通过合并editlog的方式过程叫checkpoint生产fsimage。为了减少active的压力合并editlog的工作是交给standby负责的。
大体上的checkpoint流程如下
2.2 什么时候删除editlog
之前我一直以为nn是在standby完成checkpointactive将fsimage同步完成后会自行删除editlog减少active的过期的editlog。直到我重新做了认真整理了checkpoint环节并阅读了部分代码后发现checkpoint和删除editlog策略是两件不相干的事儿。
editlog日志的删除内部维护了特定的日志删除策略。主要的代码如下
/**void purgeOldStorage(NameNodeFile nnf) throws IOException {FSImageTransactionalStorageInspector inspector new FSImageTransactionalStorageInspector(EnumSet.of(nnf));storage.inspectStorageDirs(inspector);long minImageTxId getImageTxIdToRetain(inspector);purgeCheckpointsOlderThan(inspector, minImageTxId);if (nnf NameNodeFile.IMAGE_ROLLBACK) {// do not purge edits for IMAGE_ROLLBACK.return;}// If fsimage_N is the image we want to keep, then we need to keep// all txns N. We can remove anything N1, since fsimage_N// reflects the state up to and including N. However, we also// provide a cushion of older txns that we keep, which is// handy for HA, where a remote node may not have as many// new images.//// First, determine the target number of extra transactions to retain based// on the configured amount.long minimumRequiredTxId minImageTxId 1;//最小的日志事务id为 最小需要保留的事务txid减去需要额外保留的事务id其中minimumRequiredTxId为检查点镜像文件的最后一条事务id本质上就是保留numExtraEditsToRetain条事务。long purgeLogsFrom Math.max(0, minimumRequiredTxId - numExtraEditsToRetain);//edit log的文件输入流ArrayListEditLogInputStream editLogs new ArrayListEditLogInputStream();//填充purgeableLogs.selectInputStreams(editLogs, purgeLogsFrom, false, false);//排序优先比较第一条事务txid然后比较最后一条事务txidCollections.sort(editLogs, new ComparatorEditLogInputStream() {Overridepublic int compare(EditLogInputStream a, EditLogInputStream b) {return ComparisonChain.start().compare(a.getFirstTxId(), b.getFirstTxId()).compare(a.getLastTxId(), b.getLastTxId()).result();}});// Remove from consideration any edit logs that are in fact required.//如果edit log文件的第一个事务txid比最小需要保留的事务txid大那么该edit log需要保留从待editLogs list中移除。while (editLogs.size() 0 editLogs.get(editLogs.size() - 1).getFirstTxId() minimumRequiredTxId) {editLogs.remove(editLogs.size() - 1);}// Next, adjust the number of transactions to retain if doing so would mean// keeping too many segments around.//如果editLogs list的条数比需要保留的最大edits文件数多那么能保留的最小事务id purgeLogsFrom 需要扩大将purgeLogsFrom 置为该日志的文件事务txid//如果了解前因后果的话需要清除的日志由两个参数控制需要保留的事务数量及需要保留的日志文件数两个是且的关系只有两个条件都满足的日志才会保留有一个不满足就会删除这里其实就是当日志文件数大于需要保留的日志文件数时多余的日志文件数需要清除。while (editLogs.size() maxExtraEditsSegmentsToRetain) {purgeLogsFrom editLogs.get(0).getLastTxId() 1;editLogs.remove(0);}// Finally, ensure that were not trying to purge any transactions that we// actually need.//最后确认下本次清除的事务id必须比最低要求低不然抛出异常。if (purgeLogsFrom minimumRequiredTxId) {throw new AssertionError(Should not purge more edits than required to restore: purgeLogsFrom should be minimumRequiredTxId);}//调用方法清除这个前文已经将了purgeableLogs.purgeLogsOlderThan(purgeLogsFrom);}更多细节不在展开总结下来nn删除editlog主要由2个策略决定
保留 numExtraEditsToRetain 条事务保留 maxExtraEditsSegmentsToRetain 个edit log日志文件
两个策略独立运行只要有一个条件不满足日志就会被删除。
查看源码得知
numExtraEditsToRetain对应的参数为 dfs.namenode.num.extra.edits.retained默认值1000000maxExtraEditsSegmentsToRetain对应的参数为 dfs.namenode.max.extra.edits.segments.retained默认值10000
所以整体总结过来的策略是editlog的删除策略是
最多保留dfs.namenode.max.extra.edits.segments.retained默认值10000 n n跟fsimage的文件个数有关个editlog如果nn的事务增长较快由于只保留dfs.namenode.num.extra.edits.retained默认值1000000条事务因此editlog数量可能会少于dfs.namenode.max.extra.edits.segments.retained默认值10000个。
另外可以从fsimage的名称可以获取最小的事务id比如fsimage_000000000096796869对应的最小事务id是000000000096796869往前保留1000000个事务即从95796870开始事务ID比这个小的editlog文件都会被删除包含95796870的editlog会被保留即便该editlog文件的事务ID可能会比95796870小这也是为什么可能保留的editlog可能超过fs.namenode.max.extra.edits.segments.retained默认值10000的原因 在查看hadoop的官方hdfs-default.xml文档获得相关配置的解释。
名称默认值description翻译dfs.namenode.num.extra.edits.retained1000000The number of extra transactions which should be retained beyond what is minimally necessary for a NN restart. It does not translate directly to file’s age, or the number of files kept, but to the number of transactions (here “edits” means transactions). One edit file may contain several transactions (edits). During checkpoint, NameNode will identify the total number of edits to retain as extra by checking the latest checkpoint transaction value, subtracted by the value of this property. Then, it scans edits files to identify the older ones that don’t include the computed range of retained transactions that are to be kept around, and purges them subsequently. The retainment can be useful for audit purposes or for an HA setup where a remote Standby Node may have been offline for some time and need to have a longer backlog of retained edits in order to start again. Typically each edit is on the order of a few hundred bytes, so the default of 1 million edits should be on the order of hundreds of MBs or low GBs. NOTE: Fewer extra edits may be retained than value specified for this setting if doing so would mean that more segments would be retained than the number configured by dfs.namenode.max.extra.edits.segments.retained.应该保留的额外事务的数量超出了 NN 重新启动所需的最低限度。它不会直接转换为文件的年龄或保存的文件数量而是转换为事务的数量这里“编辑”是指事务。一个编辑文件可能包含多个事务编辑。在检查点期间NameNode 将通过检查最新的检查点事务值减去此属性的值来确定要保留的编辑总数。然后它扫描编辑文件以识别不包括计算范围的保留交易的旧文件并随后清除它们。保留对于审计目的或 HA 设置很有用其中远程备用节点可能已离线一段时间并且需要保留更长的保留编辑积压才能重新开始。通常每次编辑大约为几百字节因此默认的 100 万次编辑应该是数百 MB 或低 GB 的数量级。注意如果这样做意味着保留的段数多于 dfs.namenode.max.extra.edits.segments.retained 配置的数量则保留的额外编辑可能少于为此设置指定的值。dfs.namenode.num.checkpoints.retained2最多保存2个fsimage文件
3. NN启动的日志加载策略
nn启动时会加载本地的fsimage然后通过jn下载editlog进行数据回放但是如果nn的editlog清理策略不生效保留了很长时间以前的editlogstandby重启后到底是把active节点的所有editlog都下载下来回放还是会根据本地的fsimage下载相应的editlogfsimage最小事务之后的editlog进行回放也就是说active如果保留了过多的editlog是否会对standby的启动流程是否有影响
为了解答这个疑问我自己搭建了一个hdfs集群并进行模拟和验证观察相关的日志情况如下
nn2节点standby重启相关日志如下nn2加载了fsimage_0000000000000002066并记录当前的txid0000000000000002066并开始从txid2067进行下载因此直接忽略txid2066的editlog文件。 可以得出结论
standby重启后会根据fsimage计算最小的txid并从最小txid开始下载editlog因此active节点如果保存了过多的editlog并不会干扰standby的启动过程。如果standby本地的fsimage版本过老就会需要从nn1下载大量的editlog进行数据合并需要消耗很长时间正常情况下active最多保存dfs.namenode.max.extra.edits.segments.retained默认值10000 n n跟fsimage的文件个数有关个editlog如果standby宕机时间过久本地的fsimage active保留的editlog有可能无法完成数据回放会出现数据丢失。
4. Standby启动慢应对策略
如果standby启动过慢原因是由于fsimage版本过老应对的策略应该是从active节点同步最新的fsimage从而减少下载editlog日志。
如下2种方式均可
将active节点的fsimage拷贝给standby节点在启动standby节点执行命令同步元数据后在启动standby节点
hdfs namenode -bootstrapStandby如果standby节点宕机时间过长active节点由于没有standby节点进行checkpoint可能fsimage的版本很低可以在启动standby节点前手动执行savepoint在同步fsimage。但是需要注意手动执行checkpoint需要先进入安全模式此时客户端是不能读写的对业务有影响需要业务低峰期执行。
# 进入安全模式
hdfs dfsadmin -safemode enter# 执行checkpoint
hdfs dfsadmin -saveNamespace
hdfs dfsadmin -saveNamespace# 离开安全模式
hdfs dfsadmin -safemode leave# standby同步元数据
hdfs namenode -bootstrapStandby5. 疑问和思考
5.1 如何人工阅读editlog和fsimage文件的内容
可以通过hdfs提供的工具进行读取
# 读取editlog和fsimage文件并转化成xml文件
hdfs oev -i edits_0000000000000157832-0000000000000158267 -o test_edits.xml
hdfs oev -i fsimage_0000000000000002066 -o test_edits.xml
# -i 为输入edits文件地址
# -o 为输出的xml地址cat test_edits.xml5.2 checkpoint的触发策略是什么
触发进行checkpoint的时机由这么几个配置项决定
dfs.namenode.checkpoing.check.period检测是否满足上面两个条件的时间间隔默认值为60秒。即1分钟检查一次。
dfs.namenode.checkpoint.period执行checkpoint的最小时间间隔默认为3600秒即1小时。
dfs.namenode.checkpoint.txns触发checkpoint的事务数默认值为1000000。
上述两个条件只要符合其一则执行checkpoint。 也就是说3600s内一定会触发一次checkpoint如果集群的写频繁满足1000000条事务还没到3600s就会触发checkpoint
5.3 如果删除editlog失效导致保存过多的editlog如果nn重启启动过程是否会很长
不一定。
启动过程时依赖本地的fsimage通过fsimage计算最小txid并基于最小txid加载回放editlog通常回放editlog的多少对启动过程的时长有很大的影响。
因此
如果standby进行checkpoint的流程正常fsimage的版本比较高nn启动过程也是比较快的。如果standby进行checkpoint的流程不正常fsimage的版本比较低nn启动过程就会比较慢。
5.4 如果standby长期宕机active重启后有没有快速恢复的办法
暂无。
原因是standby长期宕机没有节点进行checkpointactive节点的fsimage很老需要回放大量的editlog如果fsimage版本过低editlog被清理策略清理有可能会导致数据丢失需要时间很长因此很难快速恢复。
5.5 如何人工触发checkpoint
# 进入安全模式
hdfs dfsadmin -safemode enter# 执行checkpoint
hdfs dfsadmin -saveNamespace
hdfs dfsadmin -saveNamespace# 离开安全模式
hdfs dfsadmin -safemode leave# standby同步元数据
hdfs namenode -bootstrapStandby6. 参考文档
hadoop edits日志不删除现象排查HDFS——fsimage