LSM 的 Compaction 策略怎么选?Size-Tiered 和 Leveled 有什么区别?
自测:先别看答案
试着用 1~2 分钟把这道题讲出来(说出声或写下要点),再展开对照。
面试怎么回答
Size-Tiered 把大小相近的文件凑够数量再合并,数据重写次数少、写放大低,但同层文件 key 重叠,读放大和空间放大高,适合写多读少;Leveled 保证每层内 key 不重叠,读一层最多查一个文件,读放大和空间放大低,但数据逐层重写、写放大高,RocksDB 默认就是它。我会按业务的读写比例、点查延迟要求和磁盘余量来选,同时限制 Compaction 的 IO 和线程,避免和前台请求抢资源。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
接着上一题,面试官常追问:Compaction 有哪些策略?HBase、RocksDB 各用什么?怎么根据业务选?
Size-Tiered:大小相近的文件凑够数量就合并
文件按大小分层,同一层积累到一定数量的相近大小文件后,合并成一个更大的文件放到下一层。
- 优点:每条数据被重写的次数少,写放大低,适合写多读少。
- 缺点:同一层的文件 key 范围互相重叠,读要查的文件多,读放大高;合并时新旧文件同时存在,空间放大高,极端情况下需要额外一倍空间。
Leveled:每层内部 key 不重叠
除第 0 层外,每一层内部的文件 key 范围互不重叠,层与层之间按固定倍数(比如 10 倍)增长。上一层的文件要和下一层 key 范围重叠的文件合并。
- 优点:每层最多查一个文件,读放大低;空间放大低,旧版本很快被清理。
- 缺点:数据从上往下每层都要被重写,写放大高。
RocksDB 默认使用 Leveled;Cassandra 两种都提供;HBase 的 Minor / Major Compaction 更接近 Size-Tiered 的思路,Major Compaction 会把一个 Store 的文件全部合并。
怎么选
- 写入量大、读取主要是近期数据或范围扫描:倾向 Size-Tiered,或者分层混合策略(比如 RocksDB 的 Universal)。
- 点查多、对读延迟敏感、磁盘空间紧张:倾向 Leveled。
- 时序或日志类数据按时间过期:可以选按时间窗口的 Compaction,过期数据整文件删除,避免无意义的重写。
无论哪种,都要关注 Compaction 和前台读写抢资源的问题:限制 Compaction 的线程和 IO 带宽,或者把重 Compaction 安排在低峰期。