
JuiceFS 元数据引擎 TiKV 最佳实践垃圾回收、集群部署与硬件调优指南【免费下载链接】juicefsJuiceFS is a distributed POSIX file system built on top of Redis and S3.项目地址: https://gitcode.com/GitHub_Trending/ju/juicefsTiKV 是 JuiceFS 官方支持的高可用分布式元数据引擎之一基于 Raft 协议提供多副本数据一致性与横向扩容能力。本文以 docs/zh_cn/administration/metadata/tikv_best_practices.md 为核心结合 pkg/meta/tkv_tikv.go 等仓库源码系统讲解 TiKV 作为 JuiceFS 元数据引擎时的垃圾回收机制、集群部署硬件要求、运行参数调优思路以及典型故障处理帮助你构建一个稳定、可维护的大规模文件系统元数据层。TiKV 作为元数据引擎的核心特性JuiceFS 将元数据与对象存储分离元数据引擎负责维护文件系统的目录树、文件属性、切片slice引用等信息。TiKV 是其中面向大规模、高可用场景的分布式 KV 存储方案在 pkg/meta/tkv_tikv.go 中通过Register(tikv, newKVMeta)注册为可用的元数据驱动。TiKV 的核心设计带来两个直接收益多副本数据一致性TiKV 通过 Raft 协议保证多副本之间的数据一致性以及高可用。建议生产环境至少部署三个副本以保证数据安全和服务稳定。横向扩容能力TiKV 有很好的横向扩容能力适用于大规模且对性能有一定要求的文件系统场景。从源码结构看JuiceFS 对 TiKV 客户端还做了若干面向元数据场景的定制例如在 pkg/meta/tkv_tikv.go 的事务提交路径中启用了SetEnable1PC(true)与SetEnableAsyncCommit(true)以降低跨 Region 事务与提交延迟对元数据操作的影响元数据变更日志XLOG默认被划分为 64 个分片可通过环境变量JFS_TKV_CHANGELOG_SHARDS调整见 pkg/meta/tkv_tikv.go用于支撑目录统计、增量扫描等后台任务。垃圾回收GCMVCC 与 safe-pointTiKV 原生支持 MVCC多版本并发控制机制当新写入的数据覆盖旧数据时旧数据不会被立即替换而是与新数据同时保留并以时间戳区分版本。垃圾回收GC的任务便是清理不再需要的旧版本数据。TiKV 根据集群变量safe-point一个时间戳决定是否清理某个时间点之前的旧版本数据。JuiceFS 在 v1.0.4 之前不会设置safe-point此时 TiKV 元数据引擎需要依赖 TiDB 才能正常进行垃圾回收v1.0.4 之后JuiceFS 客户端会周期性地设置safe-point默认清除三小时之前的旧版本数据。JuiceFS 的 GC 配置gc-interval这个「三小时」的默认值可以在挂载时通过 meta url 的gc-interval参数修改。源码 pkg/meta/tkv_tikv.go 给出了具体解析逻辑interval : time.Hour * 3 if dur, err : time.ParseDuration(query.Get(gc-interval)); err nil { if dur ! 0 dur time.Hour { logger.Warnf(TiKV gc-interval (%s) is too short, and is reset to 1h, dur) dur time.Hour } interval dur } logger.Infof(TiKV gc interval is set to %s, interval)值得注意的两个细节gc-interval的最小值被钳制为 1 小时如果传入一个非零且小于 1 小时的值JuiceFS 会记录警告日志并强制重置为 1h避免过短的时间窗口导致大量旧版本尚未被读取就被回收。默认值 3h 对应代码中的interval : time.Hour * 3。挂载时观察日志即可确认当前生效的 GC 间隔默认gc-interval的挂载 log sudo ./juicefs mount tikv://localhost:2379 ~/mnt/jfs 2023/04/06 20:23:34.741432 juicefs[17286] INFO: Meta address: tikv://localhost:2379 [interface.go:491] 2023/04/06 20:23:34.741561 juicefs[17286] INFO: TiKV gc interval is set to 3h0m0s [tkv_tikv.go:84] ...设置gc-interval后的挂载 log sudo ./juicefs mount tikv://localhost:2379?gc-interval1h ~/mnt/jfs 2023/04/06 20:25:58.134999 juicefs[17395] INFO: Meta address: tikv://localhost:2379?gc-interval1h [interface.go:491] 2023/04/06 20:25:58.135113 juicefs[17395] INFO: TiKV gc interval is set to 1h0m0s [tkv_tikv.go:84] ...主动设置 safe-pointgc 子命令除了客户端周期性设置safe-point还可以通过juicefs gc子命令主动触发。gc命令在 cmd/gc.go 中定义其完整能力包括扫描对象存储与元数据中的切片做对比、触发切片合并--compact、清理泄漏对象与延迟删除的切片/文件--delete等。 ./juicefs gc -v tikv://localhost:2379?gc-interval1h --delete ... 2023/04/06 20:41:57.145692 juicefs[18531] DEBUG: TiKV GC returns new safe point: 440606737600086016 (2023-04-06 19:41:57.139 0800 CST) [tkv_tikv.go:248] ...这条日志对应的底层实现位于 pkg/meta/tkv_tikv.go 的gc()方法客户端获取当前时间戳后减去gcInterval得到目标 safe point再调用 TiKV 客户端的GC接口func (c *tikvClient) gc() { if c.gcInterval 0 { return } currentTs, err : c.client.CurrentTimestamp(oracle.GlobalTxnScope) ... safePoint, err : c.client.GC(context.Background(), oracle.GoTimeToTS(oracle.GetTimeFromTS(currentTs).Add(-c.gcInterval))) ... }该gc()方法会在执行清理任务时被调用调用点位于 pkg/meta/tkv.go 的doCleanupSlices中func (m *kvMeta) doCleanupSlices(ctx Context, count *uint64) error { if m.Name() tikv { m.client.gc() } ... }:::tip 提示juicefs gc --delete同时会清理 JuiceFS 产生的「泄漏对象」和「待清理对象」。建议先阅读 状态检查 维护结合自身场景确认是否应当使用该命令。 :::TiKV 的垃圾回收模式TiKV 侧支持两种 GC 执行模式需要在部署时根据元数据引擎的性能诉求权衡gc-worker通过 TiKV 配置启用。gc-worker 模式下垃圾会被及时回收但大量额外的磁盘读写可能会影响元数据引擎性能。[gc] enable-compaction-filter falsecompaction-filter默认TiKV 默认通过 compaction-filter 机制进行垃圾回收由 RocksDB 的 Compaction 过程来完成 GC不再使用单独的 GC worker 线程。这样做的优点是避免 GC 引起额外的磁盘读取也避免清理掉的旧版本残留大量删除标记影响顺序扫描性能。由于 compaction-filter 模式依赖 RocksDB compaction设置safe-point之后垃圾并不会被及时回收需要后续持续写入触发 compaction 才能完成 GC。如果需要主动触发 GC可以通过tikv-ctl工具对集群执行 compaction从而触发全局 GC tikv-ctl --pd 127.0.0.1:2379 compact-cluster -b -c default,lock,write元数据备份注意事项对于大规模文件系统需要调高tikv_gc_life_time参数否则可能因为GC life time is shorter than transaction duration导致备份失败。其原因是备份任务通常需要开启长事务读取全部元数据如果 GC 生命周期短于事务持续时长事务读取的旧版本数据可能已被清理从而报错中断。因此在运行juicefs dump元数据备份/导出等长事务任务前应先评估并放宽 TiKV 侧的 GC 保留时间使tikv_gc_life_time覆盖备份事务的持续时间。运行环境与调优硬件选型根据 TiDB 官方软硬件环境建议TiKV 支持部署在 Intel x86-64 架构的 64 位通用硬件服务器平台或 ARM 架构服务器平台。以下为开发、测试及生产环境的服务器硬件配置要求不包含操作系统本身的占用开发与测试环境| 组件 | CPU | 内存 | 本地存储 | 网络 | 实例数量最低要求 | |-|-|-|-|-|-| | PD | 4 核 | 8 GB | SAS200 GB | 千兆网卡 | 1 | | TiKV | 8 核 | 32 GB | SSD200 GB | 千兆网卡 | 3 |:::note 说明如进行性能相关的测试避免采用低性能存储和网络硬件配置防止对测试结果的正确性产生干扰。TiKV 的 SSD 盘推荐使用 NVME 接口以保证读写更快。 :::生产环境| 组件 | CPU | 内存 | 本地存储 | 网络 | 实例数量最低要求 | |-|-|-|-|-|-| | PD | 8 核 | 16 GB | SSD | 万兆网卡2 块最佳 | 3 | | TiKV | 16 核 | 64 GB | SSD | 万兆网卡2 块最佳 | 3 |:::note 说明 TiKV 硬盘大小配置建议PCI-E SSD 不超过 2 TB普通 SSD 不超过 1.5 TB。 :::网络要求TiKV 正常运行需要网络环境提供如下端口配置管理员可根据实际部署方案在网络侧和主机侧开放相关端口| 组件 | 默认端口 | 说明 | |-|-|-| | TiKV | 20160 | TiKV 通信端口 | | TiKV | 20180 | TiKV 状态信息上报通信端口 | | PD | 2379 | 提供 TiDB 和 PD 通信端口 | | PD | 2380 | PD 集群节点间通信端口 |磁盘空间要求| 组件 | 磁盘空间要求 | 健康水位使用率 | |-|-|-| | PD | 数据盘和日志盘建议最少各预留 20 GB | 低于 90% | | TiKV | 数据盘和日志盘建议最少各预留 100 GB | 低于 80% |硬件调优在满足 TiKV 组件最低硬件要求的基础上还可以对操作系统与硬件参数做针对性优化以降低元数据引擎的延迟抖动。CPUCPU 选型可分为计算型和存储型。计算型需要更多 CPU 核心和更高主频存储型 CPU 配置可相对低一些。以 JuiceFS 的使用场景来看PD 和 TiKV 以存储型为主没有太高的计算负载可提前规划使硬件采购更合理、节省成本。CPU 架构X86/ARMX86 架构Intel/AMD采用复杂指令集是目前最主流服务器的 CPU 架构ARM 架构 CPU 出现在手机、Mac 笔记本以及华为等国产服务器厂商的产品中。TiKV 对两种架构均有支持可根据实际部署情况选择。NUMA 绑核多核心 CPU 的各核心会被分配到不同 NUMA node每个 NUMA node 有自己专属/本地的主存访问本地主存比跨 NUMA node 访问内存更快。开启 NUMA 会优先就近使用内存在单机多节点部署时推荐此配置。CPU 动态节能技术cpufreq 是动态调整 CPU 频率的模块支持五种模式。为保证服务性能应选用 performance 模式将 CPU 频率固定在其支持的最高运行频率上以获取最佳性能。系统一般默认 powersave可通过cpupower frequency-set修改。Memory关闭 Swapswap 用硬盘承接达到一定阈值的内存访问由vm.swappiness参数控制默认 60即系统内存使用到 40% 时开始使用 swap。TiKV 运行需要足够的内存若内存不足不建议用 swap 作为缓冲因为会降低性能。建议关闭系统 swap。设置min_free_kbytes该内核参数控制多少内存应保持空闲而不被文件系统缓存占用。默认情况下内核会用文件系统缓存占据几乎所有的空闲内存并按需释放供进程分配。数据库会在共享内存中执行大量分配默认内核值可能导致意外的 OOMOut-of-Memory kill。在总内存大于 40G 的情况下建议将该参数配置为至少 1GB但不超过总内存的 5%确保 Linux 始终保持足够的内存可用。关闭透明大页THP数据库的内存访问模式往往稀疏而非连续。当高阶内存碎片化比较严重时分配 THP 页面会出现较高延迟若开启针对 THP 的直接内存规整功能还可能出现系统 CPU 使用率激增的现象因此建议关闭 THP。调整虚拟内存dirty_ratio/dirty_background_ratiodirty_ratio是绝对的脏页百分比限制当脏的 page cache 总量达到系统内存总量的该百分比后系统开始使用 pdflush 将脏的 page cache 写入磁盘默认值为 20%到达该值时可能导致应用进程的 IO 等待通常不需调整。dirty_background_ratio是触发后台写脏页的百分比默认值为 10%如果后台刷脏页慢而数据写得快容易触发dirty_ratio限制通常也不需调整。对于高性能 SSD如 NVMe 设备设置较低的值有利于提高内存回收时的效率。数据存储硬盘选型可参考以下四类SAS一般与 RAID 卡搭配实现 RAID 0/1/10/5 等阵列扩展。SATA支持热插拔接口最高 6G/s。PCIE传输速率更高8G/s支持多通道可线性扩展速率。AHCI 为 SAS 和 SATA 设计NVMe 协议为 PCIE SSD 设计、性能更优核心的高 I/O 数据库一般选用该类型 SSD。持久内存如傲腾提供丰富的底层接口成本很高适合需要极致写入性能的场景。I/O 调度算法方面Linux 常见算法对数据库类负载的影响如下noopno operation内核中最简单的 IO 调度算法将 IO 请求放入 FIFO 队列逐个执行只对磁盘上连续的 IO 请求做适当合并。适合不希望调度器重新组织 IO 请求顺序的应用因为内核的 I/O 调度操作本身会导致性能损失。NVMe SSD 这类高速 I/O 设备可直接将请求下发给硬件从而获得更好的性能。CFQCompletely Fair Queuing尝试提供由发起 I/O 进程决定的公平调度为每个进程分配一个时间窗口在窗口内允许进程发出 IO 请求。通过时间窗口在不同进程间的移动保证所有进程都有公平发出 IO 请求的机会但如果少数进程存在大量密集的 I/O 请求会出现明显的 I/O 性能下降。deadline主要针对 I/O 请求的延时每个 I/O 请求都被附加一个最后执行期限。读请求和写请求分成两个队列默认优先处理读 IO除非写快到 deadline 时才调度。当系统中 I/O 请求进程数量较少时与 CFQ 相比deadline 算法能提供较高的 I/O 吞吐率。常见问题多机并发读写同一个目录如何避免持续的事务重启现象当多个客户端在同一个目录下频繁创建/删除子目录时可能会出现持续的事务重启现象。JuiceFS v1.1 版本开始提供--skip-dir-nlink挂载选项用于指定「跳过目录 nlink 检查之前」的重试次数默认值为 20 次。该选项在 cmd/flags.go 中定义cli.IntFlag{ Name: skip-dir-nlink, Value: 20, Usage: number of retries after which the update of directory nlink will be skipped (used for tkv only, 0 means never), },并在 cmd/mount.go 中通过conf.SkipDirNlink c.Int(skip-dir-nlink)写入挂载配置。可以适当调小该值或者设置为 0 禁止重试从而避免持续的事务重启现象。完整的挂载参数说明可参考 command_reference.mdx 中的 mount 元数据选项部分。总结把 TiKV 用作 JuiceFS 的元数据引擎时可以从三个层面保障集群的稳定运行GC 层面理解 MVCC 与safe-point的关系通过gc-interval控制 JuiceFS 周期性的 GC 窗口默认 3h、最小 1h需要时用juicefs gc主动推进 safe point并结合 compaction-filter 或 gc-worker 两种 TiKV 侧模式规划回收策略。部署层面按生产环境硬件要求配置 PD/TiKV 的 CPU、内存、SSD 与网络端口注意磁盘健康水位与备份任务的tikv_gc_life_time匹配。调优层面从 CPUNUMA 绑核、performance 频率模式、内存关闭 swap/THP、调整内核参数到存储NVMe SSD、I/O 调度算法逐项优化并将--skip-dir-nlink等挂载选项纳入多机并发场景的故障预案。【免费下载链接】juicefsJuiceFS is a distributed POSIX file system built on top of Redis and S3.项目地址: https://gitcode.com/GitHub_Trending/ju/juicefs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考