Wal log的接口规范设计文档(HDFS-1580:Add interface for generic Write Ahead Logging mechanism)

本文详细介绍了HDFS中Write-Ahead Log(WAL)接口的设计方案,包括JournalFactory接口定义、EditLog流操作、自定义WAL配置等核心内容,并探讨了FSImage改进措施及Backup Namenode功能。
转帖请注明本空间地址: http://blog.youkuaiyun.com/chenpingbupt  
原文请参:
https://issues.apache.org/jira/browse/HDFS-1580

1、接口定义
abstract class JournalFactory {
     JournalFactory(Configuration conf);
     void close();
     boolean available();
     void format();
     // get past logfiles
     List<URI> getLogs(long sinceTransactionId);
     // Streams
     EditLogInputStream getInputStream(URI);
     EditLogOutputStream getOutputStream(URI);
}
class EditLogOutputStream {
     ...
     void beginRoll(long txid) throws IOException;
     void endRoll() throws IOException;
     abstract void write(long txid, byte op, Writable ... writables)     throws IOException;
}
class EditLogInputStream {
     ...
     void getLayoutVersion() throws IOException;
}
JournalFactory负责管理StrorageDevice(SD),SD可以存储多个Wal。例如:目录edits_dir可以存储edits,edits.new,在hdfs-1073之后,还可以存储edits.{txid-txid}。
FileJournalFactory管理文件SD,容许client访问Storage中的logs
URI可以定位logs,client可以使用URI来打开。
FSEditLog包含一个EditLogOutputStream列表,这个列表都是从JournalFactory中构建出来的
1、1     format()
FSEditLog.format()负责将所有URI指定的dir进行初始化,但是它是通过调用所有URI的factory的format来进行初始化的,以便底层的Storage可以创建流进行logging日志。如果是FileJournalFactory,其format是一个stun,具体参加IMAGE-AND_EDITS问题部分。
1、2     Versioning
Editlog的格式也在不断的变化,所以在EditLogInputStream中加入了一个getLayoutVersion()来获取这个信息。
1、3     Error handling
当底层的Storage出错时,该Stream会被删除,一般过程是,EditLogOutputStream在写入时,抛出异常,Editlog接受异常并将stream从activeStreams中删除。FSEditLog会在roll的时候尝试读取该删除的流
1、4     Rolling
EditLogOutputStream.roll()会保证所有所有的txid在roll之前都已经提交了
2     Configuring custom WAL
目前NN通过dfs.namenode.edits.dir来指定一个URI列表作为Editlog的目录,而使用dfs.namenode.edits.plugin.<PLUGIN>来指定一个JournalFactory的实现去初始化这个URI指定的目录。
<property>
     <name>dfs.namenode.edits.dir</name>
     <value>mywal://foobar/etc/etc</value>
     <description>Location of editlog.</description>
</property>
<property>
     <name>dfs.namenode.edits.plugin.mywal</name>
     <value>com.mycompany.hdfs.MyWalJournalFactory</value>
     <description>Journal Factory implementation.</description>
</property>
Factory的构造函数中需要conf和URI列表两个
3     FileJournalManager
FileJournalManager作为一个特殊用例对待,当URI的sechma是file://开始的时候
4     Transferring logs to checkpointer
现在的Checkpointer需要通过http下载image和edits,在这个设计之后,只需下载image即可。当需要load edits的时候,JournalFactory.getLogs将会返回一个URI列表,然后通过使用JournalFactory.getInputStream()来打开,如果是FileJournalFactory,getInputStream会来检查该URI是本地还是remote的,如果是remote的会先通过http下载到本地
5     Modifications to FSImage
5、1     format
FSImage增加一个format方法,用来format一下NNStorage和Editlog
5、2     loadFSImage()
目前loadFSImage会遍历所有的SD获取他们的Checkpoint time。在这个设计之后,loadFSImage只会到IMAGE类型的SD并且调用FSEditLog.getLogs(),并将返回的URI加载到Namesystem。
5、3     recoverInterruptedCheckpoint
这个先留着,本意是通过家产edits.new的存在性来判断Checkpointing过程是否在完成之前被中止了。HDFS-1073将会包这个给干掉,它通过将文件上传到一个零时文件,然后原子性的重命名。
6     The IMAGE_AND_EDITS problem
FileJournalFactory.format()仅仅是一个stub,因为现在的FSImage有一种IAMGE_AND_EDITS的SD,如果FSImage格式化所有的IMAGE类型的SD,FSEdit格式化所有的EDITS类型的SD,那么两者都会format上述的IMAGE_AND_EDITS的SD。所以这个事情留给FSImage去做。
7     Backup namenode functionallity
当前BN在FSImage and FSNamesystem,都有一些特殊的对待,这个设计中也先不管了。
BN的stream初始化和清理都在logJSpoolStart和releaseBackupStream中完成。
FSEditLog遍历所有的EDITS目录来做roll,有了close和获取新stream的方法之后,BackupStreams显然没有必要也去遍历。

# influxd print-config WARN[0000]log.go:228 gosnowflake.(*defaultLogger).Warn DBUS_SESSION_BUS_ADDRESS envvar looks to be not set, this can lead to runaway dbus-daemon processes. To avoid this, set envvar DBUS_SESSION_BUS_ADDRESS=$XDG_RUNTIME_DIR/bus (if it exists) or DBUS_SESSION_BUS_ADDRESS=/dev/null. Command "print-config" is deprecated, use the influx-cli command server-config to display the configuration values from the running server assets-path: "" bolt-path: /root/.influxdbv2/influxd.bolt e2e-testing: false engine-path: /root/.influxdbv2/engine feature-flags: {} flux-log-enabled: false hardening-enabled: false http-bind-address: :8086 http-idle-timeout: 3m0s http-read-header-timeout: 10s http-read-timeout: 0s http-write-timeout: 0s influxql-max-select-buckets: 0 influxql-max-select-point: 0 influxql-max-select-series: 0 instance-id: "" key-name: "" log-level: info metrics-disabled: false nats-max-payload-bytes: 0 nats-port: 0 no-tasks: false overwrite-pid-file: false pid-file: "" pprof-disabled: false query-concurrency: 1024 query-initial-memory-bytes: 0 query-max-memory-bytes: 0 query-memory-bytes: 0 query-queue-size: 1024 reporting-disabled: false secret-store: bolt session-length: 60 session-renew-disabled: false sqlite-path: "" storage-cache-max-memory-size: 1073741824 storage-cache-snapshot-memory-size: 26214400 storage-cache-snapshot-write-cold-duration: 10m0s storage-compact-full-write-cold-duration: 4h0m0s storage-compact-throughput-burst: 50331648 storage-max-concurrent-compactions: 0 storage-max-index-log-file-size: 1048576 storage-no-validate-field-size: false storage-retention-check-interval: 30m0s storage-series-file-max-concurrent-snapshot-compactions: 0 storage-series-id-set-cache-size: 0 storage-shard-precreator-advance-period: 30m0s storage-shard-precreator-check-interval: 10m0s storage-tsm-use-madv-willneed: false storage-validate-keys: false storage-wal-flush-on-shutdown: false storage-wal-fsync-delay: 0s storage-wal-max-concurrent-writes: 0 storage-wal-max-write-delay: 10m0s storage-write-timeout: 10s store: disk strong-passwords: false template-file-urls-disabled: false testing-always-allow-setup: false tls-cert: "" tls-key: "" tls-min-version: "1.2" tls-strict-ciphers: false tracing-type: "" ui-disabled: false vault-addr: "" vault-cacert: "" vault-capath: "" vault-client-cert: "" vault-client-key: "" vault-client-timeout: 0s vault-max-retries: 0 vault-skip-verify: false vault-tls-server-name: "" vault-token: "" 根据配置定位influxdb暂用CPU负载高的原因,并提供解决方案
最新发布
11-08
<think>我们之前讨论的是InfluxDB的配置文件以及其CPU负载高的问题。根据引用[5],配置InfluxDB以应对高写入负载需要优化硬件和配置。现在用户的问题是根据InfluxDB配置信息定位CPU负载高的原因及解决方案。 首先,我们需要分析可能导致CPU负载高的原因: 1. **硬件配置不足**:根据引用[1]和[5],InfluxDB应在SSD上运行,并且需要足够的内存和多核CPU。如果硬件配置低于工作负载需求,可能导致CPU高负载。 2. **写入负载过高**:高写入负载(特别是超过硬件处理能力)会导致CPU过载。引用[5]提到要优化写入,包括使用批量写入、避免高基数标签等。 3. **查询负载过高**:复杂的查询或高频率的查询也会占用大量CPU资源。 4. **配置不当**:例如,walwrite-ahead log)配置、shard-group-duration设置不合理,或者没有限制每个数据库的最大序列数(max-series-per-database)导致高基数问题。 接下来,结合用户提供的配置信息(来自`/root/.influxdbv2/configs`),但注意该文件是客户端配置文件,不是服务端配置。服务端配置文件通常是`influxdb.conf`(对于InfluxDB 1.x)或通过环境变量和启动参数配置(InfluxDB 2.x)。因此,我们需要用户提供服务端配置信息。 但是,用户并没有提供具体的服务端配置,所以我们只能根据常见原因和优化建议进行回答。 ### 定位CPU负载高的步骤 1. **检查硬件配置**: - 确认InfluxDB运行在SSD上(引用[1]强调必须在SSD上运行)。 - 检查内存和CPU是否满足工作负载需求。参考引用[1]中的表格,评估当前负载属于低、中、高哪个级别,并对比硬件配置。 2. **监控负载来源**: - 使用InfluxDB自带的监控功能或系统工具(如`top`,`htop`)查看是写入还是查询导致CPU高。 - 通过InfluxDB的日志或内置监控查看慢查询和高写入负载。 3. **分析数据模型**: - 高基数(high cardinality)是常见问题,即tag的取值组合过多,导致索引庞大。检查每个measurement的series数量(可通过`SHOW SERIES CARDINALITY`命令,在InfluxDB 1.x中;对于2.x,使用API或界面查看)。 - 避免使用高基数的tag(如用户ID、唯一标识等作为tag)。 4. **检查配置参数**: - **wal配置**:调整WAL的flush间隔和文件大小,以平衡写入性能和内存/磁盘使用。 - **shard-group-duration**:根据数据保留策略设置合适的分片组时长。太短会导致大量小分片,增加开销;太长则不利于数据过期和查询效率。 - **max-series-per-database**:设置该参数限制每个数据库的最大series数,防止高基数问题失控(在InfluxDB 1.8+和2.x中支持)。 - **并发控制**:调整`flux-concurrency`(对于2.x)和查询相关的并发参数。 5. **优化写入和查询**: - **写入**:使用批量写入,增大批处理大小,减少请求次数。 - **查询**:优化查询语句,避免全量扫描;使用连续查询(CQ)或任务(Task)预聚合数据;建立合适的索引(但注意InfluxDB的索引是自动基于tag的,所以主要是合理设计tag)。 ### 解决方案 1. **升级硬件**:确保使用SSD,增加CPU核心数和内存(引用[1])。 2. **配置优化**: - 设置`max-series-per-database`和`max-values-per-tag`以防止高基数问题。 - 调整WAL配置,例如增加`wal-fsync-delay`(在1.x中)以减少同步次数(但可能增加数据丢失风险)。 - 根据数据保留时间调整`shard-group-duration`,一般设置为保留期的1/4到1/2(例如保留7天,则分片组时长1天或2天)。 3. **数据模型优化**: - 审查tag的设计,避免使用高基数字段作为tag。考虑将高基数字段作为field(但注意field没有索引)。 - 如果基数已经很高,考虑删除不必要的series或数据。 4. **负载管理**: - 对于写入:使用批量写入,调整客户端写入频率和批量大小。 - 对于查询:限制查询范围,避免大时间范围扫描;优化查询语句(如使用条件过滤);在非高峰时段运行资源密集型查询。 5. **监控与调优**: - 使用Grafana监控InfluxDB的关键指标(如写入速率、查询执行时间、内存使用等,引用[4])。 - 根据监控结果持续调整配置。 注意:由于用户没有提供具体的服务端配置和当前负载指标,以上是通用建议。建议用户先收集以下信息: - 当前硬件配置(CPU、内存、磁盘类型) - InfluxDB版本 - 服务端配置文件内容(如`/etc/influxdb/influxdb.conf`或通过`influxd print-config`命令获取) - 监控数据(如每秒写入点数、series数量等) §§相关问题§§ 1. 如何监控InfluxDB的CPU使用情况? 2. 如何识别InfluxDB中的高基数问题? 3. InfluxDB写入性能优化的具体配置参数有哪些? 4. 如何调整InfluxDB的shard-group-duration配置? 5. 在InfluxDB中,如何处理高基数series? </think>### 根据 InfluxDB 配置定位 CPU 负载高的原因及解决方案 #### 一、核心原因分析(基于配置与引用) 1. **硬件配置不足** - 检测指标: - 每秒写入字段数 > 25万 或系列数 > 100万(根据引用[1]的负载分级) - SSD 未配置(引用[1]强调必须使用 SSD) - 表现: CPU 因磁盘 I/O 等待飙升(HDD 无法处理高吞吐写入)[^1][^5] 2. **高基数(High Cardinality)问题** - 检测命令: ```sql SHOW SERIES CARDINALITY -- 若返回值 > 1000万需紧急优化(引用[1]阈值) ``` - 根源: Tag 值组合爆炸(如将用户ID设为 Tag),导致内存索引膨胀[^5] 3. **写入负载配置不当** - 关键缺陷: - `wal-fsync-delay` 未优化(默认 0s) - 未启用批量写入(batch-size < 5000 点/次) - 后果: 频繁的磁盘同步操作占用 CPU(引用[5]) 4. **查询负载压力** - 风险场景: - 未配置 `max-concurrent-queries`(默认无限) - Grafana 面板执行复杂聚合查询(引用[4]) #### 二、解决方案(分优先级实施) **1. 紧急优化(24小时内)** ```bash # 修改配置文件 /etc/influxdb/influxdb.conf [data] max-series-per-database = 1000000 # 限制高基数(引用[1]) wal-fsync-delay = "100ms" # 减少磁盘同步(引用[5]) [coordinator] max-concurrent-queries = 20 # 防查询过载 ``` **2. 硬件与架构调整(3天内)** - **存储层**: 迁移数据到 SSD(必需操作,引用[1]) - **写入层**: ```python # 客户端批量写入示例(减少请求次数) from influxdb_client import InfluxDBClient with InfluxDBClient(url="http://localhost:8086", token="YOUR_TOKEN") as client: with client.write_api(batch_size=10_000) as writer: # 增大批次 writer.write("bucket", "org", data_points) ``` **3. 深度调优(1周内)** | 参数 | 建议值 | 作用 | |-----------------------|-----------------|-------------------------------| | `shard-group-duration` | 24h → 7d | 减少分片碎片化(引用[5]) | | `cache-max-memory-size`| 内存的 50% | 提升索引缓存命中率 | | `flux-concurrency` | CPU 核心数 × 2 | 优化查询并行度 | #### 三、验证方法与监控 1. **实时诊断工具** ```bash influxd inspect report-linux # 生成资源占用报告 ``` - 关注输出中的 `Series Cardinality` 和 `Write Throughput` 2. **关键监控指标(Grafana 配置)** | 指标 | 安全阈值 | 告警条件 | |-----------------------------|-----------------|-----------------------| | `sys_cpu_usage` | < 70% | 持续 > 80% 持续 5min | | `write_wal_fsync_duration` | < 100ms | P99 > 200ms | | `query_active` | < `max-concurrent-queries` | 达到上限值 | > 通过上述优化,典型案例中 CPU 负载可降低 40-60%(引用[5]实践数据)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值