You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RocksDB手动压缩需大量空闲空间问题求助

问题场景

我们有一个写密集型应用,每小时向MariaDB的RocksDB表写入数千条日志,需要处理磁盘空间即将耗尽的情况。当前的处理流程是:

  • 当磁盘空闲空间达预设阈值时,拆分小批次执行删除最旧的1%日志(避免磁盘过载):
    DELETE FROM log_table LIMIT 1000000;
    
  • 但删除仅生成tombstone(墓碑标记),不会直接释放磁盘空间,导致无法判断是否已获得足够空间而重复执行删除;因此删除完成后会手动触发压缩来释放空间:
    SET GLOBAL `rocksdb_compact_cf` = 'log_family';
    
  • 核心问题:手动压缩过程需要约两倍于当前数据库大小的空闲空间,不得不预留一半磁盘容量,造成极大浪费。

平台信息:

OS:   OpenSUSE 15.5
DBMS: MariaDB 10.6.14

当前MariaDB配置:

[mysqld]
plugin-load-add=ha_rocksdb

rocksdb_compaction_sequential_deletes = 10000
rocksdb_compaction_sequential_deletes_count_sd = true

rocksdb_max_total_wal_size = 128MB
rocksdb_keep_log_file_num = 1

rocksdb_delete_obsolete_files_period_micros = 30000000

rocksdb_max_background_jobs = 2
rocksdb_max_subcompactions = 2

rocksdb-override-cf-options='default={compression=kZlibCompression; bottommost_compression=kZlibCompression; max_write_buffer_number=6; write_buffer_size=16m; min_write_buffer_number_to_merge=2; level0_file_num_compaction_trigger=4; max_bytes_for_level_base=128m; max_bytes_for_level_multiplier=10; target_file_size_base=12800k; target_file_size_multiplier=10; level0_slowdown_writes_trigger=16; level0_stop_writes_trigger=20;}'
优化建议

1. 改用范围删除触发顺序删除优化

当前的DELETE ... LIMIT是随机定位删除,没法充分利用你已经配置的rocksdb_compaction_sequential_deletes。因为日志是按时间顺序写入的,最旧日志肯定有连续的主键(比如自增ID或时间戳主键),改成范围删除:

-- 按自增ID删除前100万条旧日志
DELETE FROM log_table WHERE log_id <= (SELECT MIN(log_id) FROM (SELECT log_id FROM log_table ORDER BY log_id LIMIT 1000000) AS t);

或者按时间戳删除:

DELETE FROM log_table WHERE created_at <= '2024-01-01 00:00:00';

这样RocksDB会识别为顺序删除,若某个SST文件内的数据全被删除,会直接标记文件可删除,不需要后续全量压缩,大幅减少压缩所需空间。

2. 调整压缩策略,优化空间占用

(1)开启刷盘时清理冗余数据

在列族配置中添加purge_redundant_kvs_while_flush=true,这样memtable刷写到磁盘时就会清理tombstone,不用等到压缩阶段,提前释放空间。

(2)调整压缩优先级

修改列族配置,添加compaction_pri=kMinOverlappingRatio,让RocksDB优先压缩重叠最少的文件,减少压缩过程中临时文件的占用空间。

(3)启用动态Level大小调整

添加level_compaction_dynamic_level_bytes=true到列族配置,让RocksDB根据数据量自动调整各Level的大小,避免底层Level文件过大导致压缩时占用过多空间。

3. 避免全量压缩,改用针对性压缩

不要对整个列族执行全量压缩,只处理包含tombstone的文件:

  • 先查询INFORMATION_SCHEMA.ROCKSDB_CF_STATS找到tombstone占比高的SST文件路径
  • 执行局部压缩:
    SET GLOBAL rocksdb_compact_file = 'log_family,/path/to/target_sst_file.sst';
    

或者直接指定删除的范围,只压缩该范围内的文件:

SET GLOBAL rocksdb_compact_range = 'log_family,start_key,end_key';

这样只会处理需要清理的部分,不需要两倍于整个库的空间。

4. 优化后台资源与清理周期

(1)增加后台压缩线程

当前rocksdb_max_background_jobs=2,可以根据CPU核心数提高到4-6,让压缩和清理过期文件的速度更快,避免tombstone堆积。

(2)缩短过期文件清理周期

当前rocksdb_delete_obsolete_files_period_micros=30000000(30秒),可以缩短到10秒(10000000),压缩完成后尽快删除旧的SST文件,释放空间。

5. 启用TTL自动清理过期数据

如果日志有固定保留期限,给表设置TTL,让RocksDB自动清理过期数据,不用手动删除和压缩:

ALTER TABLE log_table TTL = 86400 * 7; -- 保留7天,单位为秒

RocksDB会在压缩时自动清理过期数据,空间释放更高效。

6. 调整压缩算法平衡效率与空间

当前使用kZlibCompression,压缩率高但速度慢,压缩时临时文件占用也大。可以改成上层Level用kLZ4Compression(快速压缩),底层Level保留kZlibCompression(高压缩率),修改列族配置:

rocksdb-override-cf-options='default={compression=kLZ4Compression; bottommost_compression=kZlibCompression; ...}'

内容的提问来源于stack exchange,提问作者AshkanVZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 04:56:36