news 2026/9/15 15:20:33

ScyllaDB 数据存储与 SSTable 排障完全指南:磁盘空间、损坏恢复与无效压缩

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ScyllaDB 数据存储与 SSTable 排障完全指南:磁盘空间、损坏恢复与无效压缩

ScyllaDB 数据存储与 SSTable 排障完全指南:磁盘空间、损坏恢复与无效压缩

【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb

导读

本指南围绕 ScyllaDB 官方排障文档 docs/troubleshooting/storage/index.rst 展开,系统讲解数据存储层(SSTable)最常见的四类生产问题:运行期磁盘空间持续增长、DROP/TRUNCATE 后空间无法回收、SSTable 损坏导致节点无法启动、以及大量"无效"压缩消耗 CPU 与 I/O。读完本文,你将掌握每类问题的诊断命令、根因分析(结合源码佐证)与可落地的修复步骤,并理解 ScyllaDB 快照机制、Tombstone 清理启发式与压缩策略等底层原理。

1. 存储排障导航:四个核心问题域

ScyllaDB 作为基于 Seastar 框架的 NoSQL 数据存储(兼容 Apache Cassandra 与 Amazon DynamoDB),其持久化数据以SSTable(Sorted String Table)文件形式组织。当集群出现存储层面的异常时,官方排障索引将问题归纳为四类核心场景:

问题典型现象对应文档
正常运行期空间持续上升压缩完成后磁盘占用不回落space-up.rst
DROP/TRUNCATE 后空间不回收删除表后du显示磁盘未释放drop-table-space-up.rst
SSTable 损坏无法启动节点状态为 DN,日志报 malformed_sstable_exceptionsstable-corruption.rst
大量无效单表压缩CPU 高、日志出现大量Compacted 1 SSTables to ... (~100% of original)pointless-compactions.rst

关联文档中还包含一条指向监控文档的外部链接(Compaction Takes Lots of Memory and CPU),其核心涉及重型压缩的资源占用问题,可结合本指南第 5 节中关于压缩触发条件的源码分析一并理解。

2. 问题一:正常运行期磁盘空间持续上升

2.1 问题现象与原因

在集群的生命周期中,旧数据会通过压缩(Compaction)合并进新的 SSTable,同时删除旧文件。压缩期间存储使用量出现瞬时尖峰是正常现象——压缩过程需要同时存在新旧两代文件。但如果一次压缩结束后空间仍未回落,则可能存在问题。

根因通常是:某些进程仍持有已删除 SSTable 文件的文件描述符,导致文件虽已从目录结构中移除,但磁盘块并未真正释放。

2.2 诊断:使用 lsof 检查已删除但仍被占用的文件

使用 Linux 的lsof工具可以列出 ScyllaDB 进程打开的所有文件,其中标记为(deleted)的行即表示"已删除但引用未释放"的文件:

lsof -p `pidof scylla`

输出示例:

scylla 5864 scylla 936r REG 9,127 106689876 17184087558 /var/lib/scylla/data/<keyspace>/<table>/la-21647-Data.db (deleted) scylla 5864 scylla 938r REG 9,127 199501989 17184087553 /var/lib/scylla/data/<keyspace>/<table>/la-21609-Data.db (deleted)

字段解读:REG表示常规文件,随后的数字为文件大小(字节),(deleted)标记是关键信号。若大量旧 SSTable 以(deleted)状态被 scylla 进程持有,即确认空间被"滞留引用"占用。

2.3 解决方案(按优先级)

  1. 排查 repair 与大范围读操作:如果正在运行修复(repair)或大规模读取,这些操作会持有旧文件的引用。监控这些操作,观察其结束后空间占用是否自然回落。
  2. 收集证据并上报:若问题持续且未运行 repair 或大读,可能是 ScyllaDB 的缺陷。按官方要求收集以下数据:
    • journalctl -u scylla-server > scylla_logs.txt—— 收集 scylla-server 服务日志
    • ls -lhRS find /var/lib/scylla/data/ > file_list.txt—— 递归按大小排序列出数据目录文件清单
  3. 临时恢复手段:重启 ScyllaDB 节点会释放滞留的文件引用并回收空间。重启命令可参考 docs/rst_include/scylla-commands-restart-index.rst 中的指引(不同发行版对应的systemctl restart scylla-server等命令)。

2.4 源码佐证:SSTable 组件的生命周期

从源码结构看,ScyllaDB 的 SSTable 由多个组件文件组成,Data是存放行数据的主体组件,见 sstables/sstables.cc 中generate_toc()DataIndexSummaryFilterStatistics等组件的注册逻辑。压缩完成时旧世代文件被 unlink(sstable::unlink_component,见 sstables/sstables.cc 第 261 行附近),但若读端(如正在进行的读/修复)仍持有 mmap 或打开句柄,unlink 后的磁盘块会等到句柄关闭才释放——这正是lsof能看到(deleted)条目的底层原因。

3. 问题二:DROP/TRUNCATE 表或 Keyspace 后磁盘空间不回收

3.1 问题现象与根因

对表或 keyspace 执行DROPTRUNCATE操作后,用du等外部工具查看磁盘使用量并未下降。这并非空间泄漏,而是 ScyllaDB 的默认安全机制所致:默认情况下,ScyllaDB 会对每个被删除的表自动创建快照(Snapshot)。空间只有在快照被删除后才会真正回收。

官方在 conf/scylla.yaml 中对auto_snapshot的注释直接点明了设计意图:

"The STRONGLY advised default of true should be used to provide data safety. If you set this flag to false, you will lose data on truncation or drop."(强烈建议保持默认值 true 以保障数据安全;若设为 false,截断或删除将导致数据丢失。)

3.2 解决方案

  1. 定位快照目录并删除:找到被删除表的数据目录/var/lib/scylla/data/<your_keyspace>/<your_table>,其下的snapshots子目录保存着被删数据。使用 nodetool 按标准流程删除快照,具体步骤见 docs/operating-scylla/procedures/backup-restore/delete-snapshot。
  2. 删除整个 keyspace 时:需对 keyspace 内每一个表重复上述快照删除流程。
  3. 关闭自动快照(不推荐):该行为由/etc/scylla/scylla.yaml中的auto_snapshot标志控制,默认true。若确实要停止删除时自动快照,将其改为false并重启所有节点。

注意:也可以直接用 Linuxrm删除快照文件,但rm不了解快照与现存 keyspace 的关联关系,可能误删仍被现有 keyspace 引用的快照;nodetool 则能正确处理这种关联。

3.3 配置与源码佐证

  • 配置层面:auto_snapshot在 db/config.cc 中注册,默认值为true,且标记为LiveUpdate(支持在线更新);同文件还注册了auto_snapshot_ttl,声明见 db/config.hh。
  • 现代版本中还支持自动快照 TTL机制:auto_snapshot_ttl以秒为单位,指定自动快照的存活时间,0表示永久保留。当前仓库默认配置为864000秒(10 天),到期后过期快照会被自动清理以回收磁盘空间(见 conf/scylla.yaml 第 375-383 行注释)。
  • 关联佐证:truncate_timeout等协调器超时配置的注释也提及"默认长超时值允许在移除数据前先拍摄快照;若禁用 auto_snapshot(不推荐),可缩短该超时"(见 db/config.cc 第 1164 行附近),进一步印证快照是删除路径上的默认环节。

4. 问题三:SSTable 损坏导致节点无法启动

4.1 问题现象与日志定位

ScyllaDB 节点因 SSTable 损坏而无法启动,nodetool status显示节点状态为DN(Down, Normal)。损坏可能源于 Bug、磁盘故障或人为失误(例如误删了某个 SSTable 组件文件)。

排查未知问题时,必须先检查日志(使用journalctl -xe)。典型损坏日志如下:

scylla[28659]: [shard 0] database - Exception while populating keyspace '<mykeyspace>' with 'test' table from file '/var/lib/scylla/data/mykeyspace/test-fa9994e02fd811e7a4ee000000000000': sstables::malformed_sstable_exception (At directory:/var/lib/scylla/data/mykeyspace/test-fa9994e02fd811e7a4ee000000000000: no TOC found for SSTable with generation 2!. Refusing to boot)

本例中,缺少TOC文件导致节点拒绝启动(Refusing to boot)。SSTable 损坏也可能是其他文件缺失或不可读,但下述解决方案适用于所有场景。

4.2 为什么缺少 TOC 会导致拒绝启动

TOC(Table Of Contents)是 SSTable 的组件清单文件。从源码看,启动时 sstable 会调用read_toc()(见 sstables/sstables.cc 第 927 行附近)解析 TOC 中登记的组件列表,若 TOC 文件不存在会抛出malformed_sstable_exception(日志中的 "file not found" 分支,见同一文件第 955 行)。因此 TOC 缺失时,ScyllaDB 无法确认该代(generation)SSTable 的完整性,选择拒绝启动以避免读入不完整数据。

4.3 解决方案(五步恢复)

  1. 定位损坏世代的所有文件:按日志中的 generation 编号(示例中为2)定位。SSTable 默认位于/var/lib/scylla/data/keyspace_name/table_name-UUID/
  2. 删除该世代的所有 SSTable 文件(该代数据可通过后续 repair 从其他副本恢复):
sudo rm test-ka-2*

删除前目录中该代文件清单如下(同一代由多个组件文件构成):

-rw-r--r-- 1 scylla scylla 66 May 8 14:17 test-ka-2-CompressionInfo.db -rw-r--r-- 1 scylla scylla 357 May 8 14:17 test-ka-2-Data.db -rw-r--r-- 1 scylla scylla 10 May 8 14:17 test-ka-2-Digest.sha1 -rw-r--r-- 1 scylla scylla 24 May 8 14:17 test-ka-2-Filter.db -rw-r--r-- 1 scylla scylla 140 May 8 14:17 test-ka-2-Index.db -rw-r--r-- 1 scylla scylla 38 May 8 14:17 test-ka-2-ScyllaDB.db -rw-r--r-- 1 scylla scylla 4446 May 8 14:17 test-ka-2-Statistics.db -rw-r--r-- 1 scylla scylla 92 May 8 14:17 test-ka-2-Summary.db
  1. 启动节点
sudo systemctl start scylla-server
  1. 验证节点恢复:使用nodetool status,节点状态应变回UN(Up Normal)。
  2. 执行修复:对损坏过 SSTable 的节点运行nodetool repair(命令细节见 docs/operating-scylla/nodetool-commands/repair),从其他副本恢复被删除世代的数据,弥补数据缺失。

提示:组件文件名模式为<table>-<format>-<generation>-<Component>.<ext>,例如ka表示格式标识、2为世代号。组件清单参见 sstables/sstables.cc 的generate_toc()(注册 Data/Index/Summary/Filter/Statistics/CompressionInfo/Digest 等),可作为识别文件归属的参考。

5. 问题四:大量"无效"压缩(Single-SSTable Compactions)

5.1 现象

ScyllaDB 的 CPU 利用率异常偏高,但在没有大量 WRITE/UPDATE/DELETE/TTL 操作的情况下,压缩频繁发生;系统日志中出现大量类似消息:

compaction - Compacted 1 SSTables to ... (~100% of original) ...

"~100% of original" 意味着压缩前后体积几乎不变——压缩什么都没清理掉。

5.2 根因:Tombstone 清理启发式

SSTable 中可能包含已过期或即将过期的 Tombstone(删除标记),它们由 DELETE 操作、TTL 数据、插入 null 字段或集合(collection)的使用产生,需要被清理。压缩会清除已过期 Tombstone,但若当前恰好没有压缩在运行,ScyllaDB 会启动启发式逻辑:当某个单独的表含有一定比例过期 Tombstone 时,强制对其发起压缩

可以用sstable dump-statistics命令验证被压缩的 SSTable 确实含 Tombstone:

scylla sstable dump-statistics /var/lib/scylla/data/some_ks/some_cf-UUID/some_ks-ka-*-Data.db | jq .sstables[].stats.estimated_tombstone_drop_time

输出示例(Estimated droppable tombstones 为可丢弃 Tombstone 占比估计值):

Estimated droppable tombstones: 0.08672144669324656 Estimated droppable tombstones: 0.08935147496746765 Estimated droppable tombstones: 0.11850671228977766 Estimated droppable tombstones: 0.08511697234511045 Estimated droppable tombstones: 0.035764466964587543 Estimated droppable tombstones: 0.1894537114259597 Estimated droppable tombstones: 0.13213090183839682 Estimated droppable tombstones: 0.1208004932191389 Estimated droppable tombstones: 0.07019800509981686 Estimated droppable tombstones: 0.12196540423823726 Estimated droppable tombstones: 0.11981627152867445 Estimated droppable tombstones: 0.11780386543765468 Estimated droppable tombstones: 0.17214256718348064

启发式并不完美:它可能在没有可丢弃 Tombstone的情况下发起压缩,导致一次无意义的 Tombstone 压缩白白消耗 CPU 与 I/O,压缩后表与原始 SSTable 相比毫无变化。

5.3 源码原理:worth_dropping_tombstones 决策逻辑

在 compaction/compaction_strategy.cc 的compaction_strategy_impl::worth_dropping_tombstones()(第 61-77 行)中,决策链路如下:

  1. _disable_tombstone_compaction为 true,直接不参与 Tombstone 压缩;
  2. 时间门槛:若now - _tombstone_compaction_interval < sst->data_file_write_time(),即该 SSTable 写入时间距今不足一个tombstone_compaction_interval,则跳过——避免对刚写入的数据反复压缩形成循环,只考虑"足够老"的 SSTable;
  3. unchecked 开关:若_unchecked_tombstone_compaction为 true,直接判定值得压缩(不再检查阈值);
  4. 否则计算estimate_droppable_tombstone_ratio(),当该比值 ≥_tombstone_threshold(默认 0.2,即 20%)时判定值得压缩。

三个关键参数的默认值与常量定义见 compaction/compaction_strategy_impl.hh:

static constexpr float DEFAULT_TOMBSTONE_THRESHOLD = 0.2f; // tombstone_threshold 默认 0.2 static constexpr std::chrono::seconds DEFAULT_TOMBSTONE_COMPACTION_INTERVAL() { return std::chrono::seconds(86400); } // 默认 86400 秒 = 1 天 static constexpr auto DEFAULT_UNCHECKED_TOMBSTONE_COMPACTION = false; // 默认关闭

参数校验逻辑位于 compaction/compaction_strategy.cc:tombstone_threshold必须介于 0.0 与 1.0 之间,tombstone_compaction_interval必须为正数,unchecked_tombstone_compaction解析为布尔值。理解了这条决策链,就清楚为什么"压缩了却什么都没压缩掉"——阈值命中与可丢弃 Tombstone 的存在并非严格一一对应。

5.4 解决方案

  1. 拉长自动 Tombstone 压缩的间隔:将tombstone_compaction_interval调大(整数,单位为秒),抑制过于频繁的自动触发。例如改为 4 天(345600 秒):
ALTER table <your table name> with compaction = { 'class' : 'SizeTieredCompactionStrategy', 'tombstone_compaction_interval' : 345600 };
  1. 确保unchecked_tombstone_compaction为 false:若为 true,tombstone_threshold将被忽略,只要tombstone_compaction_interval时间一到就会无条件运行压缩:
ALTER table <your table name> with compaction = { 'class' : 'SizeTieredCompactionStrategy', 'unchecked_tombstone_compaction' : false };

实操建议:上述参数可通过ALTER TABLE ... WITH compaction = {...}按表调整;对于 Tombstone 密集型的队列类工作负载,还应关注tombstone_warn_threshold等扫描期 Tombstone 阈值(见 conf/scylla.yaml 中相关注释),从源头减少无效压缩的资源浪费。

6. 排障通用流程与操作底线

四类存储问题的处理都遵循"定位 → 取证 → 处置 → 验证"的通用流程:

  1. 先查日志journalctl -xe/journalctl -u scylla-server是定位一切存储异常的第一手段;
  2. 用工具取证lsof查滞留文件句柄、du查目录真实占用、scylla sstable dump-statistics查 Tombstone 统计、nodetool status查节点状态;
  3. 最小化处置:优先等待(repair/大读结束后自动回落)、清理快照、删除损坏世代并 repair,最后才考虑重启节点;
  4. 验证结果:通过nodetool status(UN)、磁盘占用回落情况确认问题解决。

操作底线提醒auto_snapshot是数据安全的重要防线,除非明确知晓后果,否则不要关闭;删除任何 SSTable 或快照前,务必确认对应数据可从其他副本恢复(有足够副本数且可 repair),避免不可逆的数据丢失。

7. 延伸阅读

  • SSTable 整体架构:docs/architecture/sstable/index
  • 删除快照的标准流程:docs/operating-scylla/procedures/backup-restore/delete-snapshot
  • nodetool repair 命令:docs/operating-scylla/nodetool-commands/repair
  • 日志与排障总览:docs/troubleshooting/index.rst、docs/getting-started/logging
  • 配置参考:/etc/scylla/scylla.yaml与仓库内 conf/scylla.yaml

【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 15:20:13

Word页眉形状自动调整全攻略:从相对定位到VBA动态控制

1. 写在前面&#xff1a;为什么会有这篇“Word页眉形状自动调整”的折腾记录先交代一下背景。我平时的工作里&#xff0c;有相当一部分时间在跟 Word 排版打交道&#xff0c;特别是标书、技术方案、验收报告这类文档。这类文档有个共同的审美需求&#xff1a;页眉不能光秃秃地放…

作者头像 李华
网站建设 2026/9/15 15:17:27

用Codex合并CSV文件:一份清晰需求文档如何让AI自动搞定数据清洗

1. 项目背景与需求拆解1.1 为什么选 Codex 来干这活儿先交代一下背景。我手头有三份 CSV&#xff0c;分别是用户订单明细、用户基础信息、商品类目映射&#xff0c;需要按用户ID和商品ID合并成一份宽表&#xff0c;给下游的看板用。三份文件加起来大概两万行左右&#xff0c;不…

作者头像 李华
网站建设 2026/9/15 15:17:18

怎么报考Python技术应用工程师证 在哪个行业能用

技术应用工程师, 即熟练掌握编程语言之熟练精通编程语言并能够将其应用于实际实际项目项目当中开发与与解决棘手问题之的专业人士。接下来善恩教育小编将为你详细深入进行详细相关技术应用工程师相关报考情况情况之之后续解读。想了解证书报名条件、报名入口、流程、科目、时间…

作者头像 李华
网站建设 2026/9/15 15:14:31

用 Trae AI 编程实战:从零开发 Flutter Web 2048 小游戏

最近我把主力开发工具换成了 Trae&#xff0c;起因是看到别人用 AI 对话就把一个完整的游戏做出来了&#xff0c;几乎没怎么手写代码。我决定亲自验证一下这件事到底靠谱不靠谱&#xff0c;于是给自己定了个目标&#xff1a;用 Trae 从 0 到 1 开发一个 Flutter Web 小游戏 204…

作者头像 李华