# 常见问题处理 - Write Stall（B）

![`left`](./student-guide/diagram/08-Write-Stall-02-01.png)

-------------------------------------------------------------
常见问题处理 - Write Stall
1. Write Stall 触发原因与相关参数

- memtables 数量过多

当写入 memtable 的数据大小达到 write_buffer_size 参数设置值，memtable 会转变成 immutable 等待 flush 到 L0 层。如果 memtable 已经达到 write_buffer_size 大小，内存中 memtable 数据量达到了 max_write_buffer_number 限制，那么会触发 RocksDB 的 write stall ，等待 immutable flush 到 L0 层。

这种由于 memtable 太多导致 stall 的情况一般是因为瞬间写入量比较大，memtable flush 到磁盘比较慢导致的。如果磁盘写入速度不能改善，并且只有业务高峰值会出现这种情况，可以通过调大对应 cf 的 max_write_buffer_number 参数来缓解。

write_buffer_size 控制一个写内存 memtable 的大小，当这个 memtable 写满之后数据会被固化到磁盘上，这个值越大批量写入的性能越好。max_write_buffer_number 控制写内存 memtable 数目数量。但是这两个值不是越大越好，太大会延迟一个 DB 被重新打开时的数据加载时间。

在这一步骤可能会有 memtable 文件过多导致 write stall，影响写入速度。
该情况一般发生在瞬间写入量比较大，并且 memtable flush 到磁盘的速度比较慢的情况下。如果磁盘写入速度不能改善，并且只有业务峰值会出现这种情况，可以通过调大对应 cf 的 max-write-buffer-number (默认是 5)来缓解。

- level0 文件数量过多

L0 Compaction 采用 Universal Compaction（size tiered） 的方式进行 Compaction。触发 Compation 条件：L0 层 SST 文件数量达到 level0-file-num-compaction-trigger 设定值，TiKV 中默认是 4。
当 L0 层 SST 文件数量达到 level0-slowdown-writes-trigger 设定值之后，TiKV 中默认是 20。RocksDB 会减慢写入速度，让 L0 尽快 Compaction 下去。
当 L0 层 SST 文件数量达到 level0-stop-writes-trigger 设定值之后，TiKV 中默认是 36，RocksDB 会停止写入文件，尽快对 L0 进行 Compaction
在这一步骤可能会有 level0 sst 文件过多导致 write stall，影响写入速度。
如果是 level0 sst 文件过多导致 stall ，可以修改 TiKV 参数 rocksdb.max-sub-compactions 默认值是 3 。加快 level0 sst 往下 compact 的速度，该参数的意思是将 从 level0 到 level1 的 compaction 任务最多切成 max-sub-compactions 个子任务交给多线程并发执行。

- pending bytes 过大

immutable 刷到 L0 是 flush ,L0~L6 刷到下一层是 compaction，Compaction pending bytes 表示等待 compaction 的大小。 Compaction pending bytes 太多会导致 write stall，当 Compaction pending bytes 达到 rocksdb.defaultcf.soft-pending-compaction-bytes-limit 参数值（默认是 64G）之后，RocksDB 会放慢写入速度；如果 Compaction pending bytes 达到 rocksdb.defaultcf.hard-pending-compaction-bytes-limit 参数值（默认是 256G）之后，RocksDB 会停止写入。

immutable 刷到 L0 是 flush ,L0~L6 刷到下一层是 compaction，Compaction pending bytes 表示等待 compaction 的大小。 Compaction pending bytes 太多会导致 write stall，当 Compaction pending bytes 达到 rocksdb.defaultcf.soft-pending-compaction-bytes-limit 参数值（默认是 64G）之后，RocksDB 会放慢写入速度；如果 Compaction pending bytes 达到 rocksdb.defaultcf.hard-pending-compaction-bytes-limit 参数值（默认是 256G）之后，RocksDB 会停止写入。

如果是 Compaction pending bytes 过多导致 write stall 有几种解决方案：
    1. 调大 soft-pending-compaction-bytes-limit 和 hard-pending-compaction-bytes-limit 参数，防止触发 write stall ，但是这个只是治标不治本，根本原因应该是 compaction 慢, 确认用户是否有做过 compaction 限流，如果有，那需要放开一点限制看看
    2. 如果磁盘 IO 能力持续跟不上，建议扩容。
    3. 如果磁盘的吞吐达到了上限导致 write stall ，但是 CPU 资源比较充足，可以尝试采用压缩率更高的压缩算法来缓解磁盘压力，使用 CPU 资源换磁盘资源。比如 default cf compaction 压力比较大，调整参数 `[rocksdb.defaultcf] compression-per-level = [“no”, “no”, “lz4”, “lz4”, “lz4”, “zstd”, “zstd”]` 改成 `compression-per-level = [“no”, “no”, “zstd”, “zstd”, “zstd”, “zstd”, “zstd”]`
