FoundationDB 存储基准测试上 RAM Disk:mako_storage_bench.sh 在 okteto 开发 Pod 上的 tmpfs 实践指南
发布时间:2026/9/21 7:43:14 锦皓数字建站

分布式数据库KV存储数据库后端【免费下载链接】foundationdbFoundationDB - the open source, distributed, transactional key-value store项目地址https://gitcode.com/gh_mirrors/fo/foundationdb点击查看免费下载mako_storage_bench.sh是 FoundationDB 仓库中用于捕获存储服务器 CPU 回归的单机吞吐基准脚本其设计前提是存储进程的 CPU 成为瓶颈。本文以 contrib/mako_storage_bench-ramdisk-okteto.md 为主体完整讲解如何在 okteto 开发 Pod 上把集群数据目录放到 tmpfs内存盘使基准真正跑成 CPU-bound并深入 contrib/mako_storage_bench.sh 及 fdbserver/flow 源码解释脚本自动注入的 tmpfs knob、redwood 与 rocksdb 引擎的差异、okteto 拓扑坑与容量规划。读完本文你将能够独立完成从给 Pod 挂载 /mnt/ram到跑出可信的 TPS 对比数据的全部步骤。为什么 mako 存储基准需要一块 RAM Diskmako_storage_bench.sh的设计目标是让存储服务器 CPU成为瓶颈从而检测存储引擎乃至存储服务器热路径flow、fdbrpc、网络、序列化等上的 CPU 回归。这在数据目录位于快速本地存储时成立但在 okteto 开发 Pod 上并不成立Pod 的文件系统是容器 overlay底层是网络挂载的 EBS因此基准被 EBS 的 fsync/IO 延迟所束缚而不是存储 CPU。症状非常典型文档记录的实测吞吐量停留在很低的平台在全新 m7a Pod 上约1.5k TPS存储进程 CPU 远低于 85%commit 延迟达到数十毫秒。解决办法是把集群数据放到tmpfs内存支持的目录上使 commit 不再承担磁盘延迟存储进程重新变为 CPU-bound。脚本已经内置了自动检测逻辑当/mnt/ram存在且可写时它会自动使用它并自动附加下述 tmpfs knob因此一旦开发 Pod 拥有了/mnt/ram直接运行contrib/mako_storage_bench.sh build_output4就能以 CPU-bound 方式跑起来。剩下的实际工作只是给 Pod 提供这块内存目录——而这在 okteto 上需要一些技巧。补充说明build_output4只是示例构建目录作者本机~/src/fdb4构建树即开发 Pod 上的/root/build_output4请替换为你自己的构建根目录。注意mako 默认不参与构建需要以-D BUILD_MAKOON配置构建否则build_output4/bin/mako不存在脚本会在入口处直接报错退出contrib/mako_storage_bench.sh 会对三个二进制逐一检查可执行性。TL;DR# 一次性 Pod 配置详见下文给开发 Pod 一个 /mnt/ram tmpfs 内存余量。 # 然后直接运行——脚本自动检测 /mnt/ram 并附加 tmpfs knob contrib/mako_storage_bench.sh build_output4脚本自动做了什么以及如何覆盖WORKDIR数据目录与输出目录集群数据目录和 mako 输出都位于WORKDIR之下。脚本的判定逻辑在 contrib/mako_storage_bench.shif [[ -z ${WORKDIR:-} -w /mnt/ram ]]; then WORKDIR/mnt/ram/mako_storage_bench fi readonly WORKDIR${WORKDIR:-${PWD}/mako_storage_bench}即当/mnt/ram是可写目录时默认使用/mnt/ram/mako_storage_bench否则回退到$PWD/mako_storage_bench。可以通过导出WORKDIR覆盖例如指向非 tmpfs 路径强制使用 EBS 数据目录用于对照实验。tmpfs knob--knob_disable_posix_kernel_aio1这是脚本在 tmpfs 上能跑起来的关键。fdbserver 默认以O_DIRECT 内核 AIO 打开数据文件而tmpfs 拒绝O_DIRECT因此如果没有回退机制集群根本启动不起来。脚本在检测到WORKDIR位于 tmpfs 上时自动附加该 knobcontrib/mako_storage_bench.shif [[ $(stat -f -c %T $(dirname ${WORKDIR}) 2/dev/null) tmpfs \ ${KNOBS} ! *disable_posix_kernel_aio* ]]; then KNOBS${KNOBS:${KNOBS} }--knob_disable_posix_kernel_aio1 fi对应源码在 fdbrpc/Net2FileSystem.cpp当文件以OPEN_UNBUFFERED打开、未禁用 AIO、且FLOW_KNOBS-DISABLE_POSIX_KERNEL_AIO为假时走AsyncFileKAIO内核 AIO要求O_DIRECT否则回退到Net2AsyncFileEIO 缓冲路径tmpfs 可接受。该 knob 的默认值在 flow/Knobs.cpp 中为0即默认启用内核 AIO。因此你可以用KNOBS...传额外的 knobs如果你没有自己包含 tmpfs knob脚本会替你追加反过来若你想强制 EBS 数据目录非 tmpfs脚本不会注入该 knob保持默认的内核 AIO/O_DIRECT 行为。有界时长SECONDS_RUN / WARMUP_SECONDS脚本的默认值是WARMUP_SECONDS300、SECONDS_RUN600见 contrib/mako_storage_bench.sh均可通过环境变量覆盖缩短测量窗口例如SECONDS_RUN120 WARMUP_SECONDS60是控制 tmpfs 占用、加快迭代的有效手段详见下文容量规划。存储引擎redwood默认vs rocksdb on tmpfsredwood开箱即用默认引擎是redwood映射为ssd-redwood-1。redwood 走 flow 的文件 IO 路径脚本自动附加的 tmpfs knob 已足够无需任何KNOBS。引擎到存储类型的映射在 contrib/mako_storage_bench.sh引擎名configure new存储类型备注redwoodssd-redwood-1默认引擎rocksdbssd-rocksdb-v1需要 RocksDB-enabled 构建sharded-rocksdbssd-sharded-rocksdb需要 RocksDB-enabled 构建须显式指定allredwood rocksdb便捷别名不含 sharded-rocksdb集群由 tests/loopback_cluster/run_custom_cluster.sh 以1 stateless / 1 log / 1 storage复制因子 1的方式拉起脚本通过--storage_type把引擎传入configure newcontrib/mako_storage_bench.sh。rocksdb还需要两个额外 knobsrocksdb引擎... build_output4 rocksdb需要两个额外的 knobs。RocksDB 自行管理文件 IO不经过 flow在ssd-rocksdb-v1上默认以O_DIRECT打开数据库ROCKSDB_USE_DIRECT_READS与ROCKSDB_USE_DIRECT_IO_FLUSH_COMPACTION在 fdbserver/core/ServerKnobs.cpp 中默认值均为true并在 fdbserver/kvstore/KeyValueStoreRocksDB.cpp 中直接映射到 RocksDB 的Options::use_direct_reads与use_direct_io_for_flush_and_compaction。tmpfs 拒绝O_DIRECT因此存储服务器会在rocksdb::DB::Open处失败fdbserver/kvstore/KeyValueStoreRocksDB.cpp 记录RocksDBError: Invalid argument: Direct I/O is not supported by the specified DB.并崩溃循环——而且由于这发生在任何数据目录创建之前基准会卡在configure new处脚本的BUILD_TIMEOUT只保护 mako 构建阶段不覆盖集群启动因此不会自我中止见 contrib/mako_storage_bench.sh 的注释。自动的 tmpfs knob 对 RocksDB 无效必须单独禁用 RocksDB 的直接 IO。这两个是运行时 knobs无需重新编译。脚本仍会自动附加 flow 的 knob所以你只需提供两个rocksdb_*knobsKNOBS--knob_rocksdb_use_direct_readsfalse --knob_rocksdb_use_direct_io_flush_compactionfalse \ contrib/mako_storage_bench.sh build_output4 rocksdb这两个rocksdb_*knobs 对 redwood 无害因此同样的KNOBS也可用于... build_output4 redwood rocksdb的一次性双引擎跑法。文档记录了一次 24Gi tmpfsm7a Pod上完整 300s/600s 跑的观测加上 knobs 后 rocksdb 与 redwood 一样跑成存储 CPU-bound约4.6k vs 4.8k TPS且峰值占用更小约3.3 GB vs redwood 的 5.5 GB——即 rocksdb 并没有撑爆内存盘。不过它的单次 GET 延迟更高、冲突率也更高这是正常现象。你无法直接在 Pod 内mount一个 tmpfs开发容器没有CAP_SYS_ADMIN所以mount -t tmpfs ...会以permission denied失败。/dev/shm存在但被限制为 64 MB你在系统里看到的那些大 tmpfs 挂载如/var/okteto/secret等都是只读的。因此这块内存目录只能来自Pod 规格spec中的 memory-backedemptyDir。okteto 拓扑坑要 patch BASE deployment而不是 cloneokteto up并不是直接运行你的 deployment。对于name: dev的 okteto manifest会存在两个 deploymentdev—— base deployment缩容到0/0。这是 okteto 克隆的来源source of truth。dev-okteto—— okteto 生成并**主动调谐reconcile**的活动克隆真正运行你的 Pod。关键行为okteto 会剥掉它不拥有的 volumes对dev-okteto执行kubectl patch deployment dev-okteto ...添加 volume 会静默消失但 okteto 克隆时会保留 base deployment 的 volumes这正是efs-ccache、fdb cluster 文件等能到达开发 Pod 的方式。所以 volume 必须加到basedevdeployment 上okteto up随后会把它带进 Pod。下文示例使用 deployment 名gglass-dev请替换为你 okteto manifest 的name:。设置步骤1. 提高开发容器内存上限okteto.ymlmemory-backedemptyDir的内容会计入容器的 memory cgroup即占用dev容器的内存limit而不是节点的空闲 RAM。因此 tmpfs 内容加上所有 fdbserver/mako 的 RSS 必须落在 limit 之内。在okteto.yml中提高它resources: requests: cpu: 4000m memory: 24Gi # was 16Gi limits: cpu: 8000m memory: 48Gi # was 32Gi -- room for a 24Gi tmpfs fdbserver/mako RSS这部分确实会跨okteto up持久保存在okteto.yml中。2. 给 base deployment 添加 tmpfs volumeokteto.yml这种 manifest 格式无法声明emptyDir因此以 strategic-merge patch 的方式应用到basedeployment。保存为fdb-ramdisk.yamlspec: template: spec: volumes: - name: ramdisk emptyDir: medium: Memory sizeLimit: 24Gi containers: - name: dev volumeMounts: - name: ramdisk mountPath: /mnt/ram应用到 base它处于 0 副本不影响正在运行的东西kubectl patch deployment gglass-dev --patch-file fdb-ramdisk.yaml注意该 patch 修改的是活着的 base deployment。任何供应gglass-dev的机制你的 dev-pod 基础设施/manifest在重新应用时都会覆盖它。若要永久化请把同样的volumes/volumeMounts块加到那个源 manifest 中。3. 重建 Podokteto upokteto 会把已 patch 的base 克隆成dev-okteto因此新 Pod 会拥有/mnt/ram和 48Gi 上限。4. 验证kubectl exec pod -c dev -- df -hT /mnt/ram # 期望tmpfs, 24G kubectl exec pod -c dev -- sh -c touch /mnt/ram/.w rm /mnt/ram/.w echo ok第二条命令验证/mnt/ram可写。tmpfs 容量规划磁盘占用随总插入量 TPS × 墙钟时间增长默认g18ui工作负载每次事务插入一个新 key。内存盘提高了 TPS因此同样的墙钟时间会比 EBS 写出更多数据。作为参考EBS 上 ~1.5k TPS 跑 600 s 大约写了 ~4 GBredwood 文件是主体考虑 COW/extent 开销后约~2 KB/次插入。两个事实让容量规划变得简单tmpfs 的sizeLimit是硬上限超出写入会得到 ENOSPC并且其用量计入容器内存上限超过即 OOMKill内存只在实际写入字节时消耗而不是预先保留。建议默认的完整 300s/600s 跑在24Gi tmpfs上对 redwood 绰绰有余峰值约 5.5 GB。若引擎更快或跑得更久想控制占用可以用SECONDS_RUN120 WARMUP_SECONDS60缩短一旦 CPU-bound2 分钟的测量窗口足够。sizeLimit: 24Gilimits.memory: 48Gi可从容覆盖上述场景。对于极高 TPS 或长时间运行两者一起上调例如 40Gi tmpfs / 64Gi limit并确认节点确实有这么多 RAM。禁用 / 回退从 base 移除 volume 并重新克隆kubectl patch deployment gglass-dev --typejson \ -p [{op:remove,path:/spec/template/spec/volumes/-}] okteto up或重新应用你的 basegglass-devmanifest。如需恢复原来的内存上限还原okteto.yml中的 memory limits。脚本现在在/mnt/ram存在时自动优先使用它所以普通运行就会用内存盘。要不删除 volume 而强制使用 EBS 数据目录可对该次运行导出WORKDIR$PWD/mako_storage_bench任何非 tmpfs 路径均可。其他坑你会丢失build_output4。它位于易失的容器 overlay 上而内存上限的修改和 volume patch 都会触发 Pod 滚动更新rollout。之后用run-ccmk4或你自己的构建包装脚本重建——ccache 在持久 EFS volume 上因此热重建只需几分钟而不是冷构建。mako链接libfdb_c.so且以SKIP_BUILD_RPATH构建。mako_storage_bench.sh已经设置LD_LIBRARY_PATHbuild/lib以及LD_BIND_NOW1使 mako 加载匹配的客户端见 contrib/mako_storage_bench.sh。这与内存盘无关但正是 mako 能从构建树直接运行的原因。mako 退出时会在_dl_fini中 abortlibfdb_c 作为共享库的 teardown 问题但发生在写出全部输出之后。脚本以已完成的报告文本中检索Overall TPS见 contrib/mako_storage_bench.sh判断成功并禁用了 core dumpulimit -c 0所以这是无害的——看到 abort 信息不必惊慌。附一次跑完后的产物每次引擎跑完成后输出位于${WORKDIR}/${label}/下mako-run.txt—— mako run 阶段的 tee 报告含Overall TPS等汇总mako.json—— 逐秒采样与最终统计--json_reportmako-sketch.json—— 原始延迟 sketch--stats_export_pathcluster-start.log、mako-build.txt—— 集群启动日志与 mako 构建阶段输出。A/B 对比时请务必在同一台机器/实例上背靠背运行基线构建与实验构建结果仅在相同硬件与条件下可比并重点观察 TPS 差值——任何在存储服务器热路径上新增的 CPU 开销都会与单核存储进程争抢 CPU通常表现为吞吐下降而非明显延迟。赞分享分布式数据库KV存储数据库后端【免费下载链接】foundationdbFoundationDB - the open source, distributed, transactional key-value store项目地址https://gitcode.com/gh_mirrors/fo/foundationdb点击查看免费下载相关推荐探索未来开发Okteto——在Kubernetes上的应用开发利器探索未来开发Okteto——在Kubernetes上的应用开发利器 项目简介 在云原生时代Kubernetes的出现让应用程序部署达到了前所未有的高度但与云原生开发工具Delta Lake 基准测试框架实战指南在 AWS EMR 与 GCP Dataproc 上运行 TPC-DS 基准测试Delta Lake 基准测试框架实战指南在 AWS EMR 与 GCP Dataproc 上运行 TPC DS 基准测试 本指南基于 Delta Lake湖仓一体数据工程数据湖30分钟上手Kubernetes架构可视化从Pod到存储的完整实践指南30分钟上手Kubernetes架构可视化从Pod到存储的完整实践指南 diagrams是一个功能强大的架构可视化工具它允许你使用代码来创建清晰、专业的云系数据可视化开发工具文档上一篇彻底清理Owncast API文档优化实战指南下一篇MTKClient项目中Preloader区域访问问题的分析与解决创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。