Skip to the content.

文件分区

1. 文件分区是指什么?

文件分区很少有资料介绍,但是在众多数据库组件的最佳实践中通常会以 benchmark 告诉我们这一个建议。

文件分区包括两件事:

  1. 将原本一个大文件分为多个小文件。例如,将一个大数据量的文件分为多个小文件进行存储。例如 Kafka 中为避免 WAL Log 过大,使用了 LogSegment 概念,当某一个 LogSegment 足够大时,就创建一个新的 LogSegment,用于后续的日志写入;
  2. 将用途不同的文件存储于不同的磁盘上。例如,MySQL 通常推荐将事务日志文件与数据文件分别存储于本机挂载的不同磁盘上。

下面我们分析一下文件分区的意义。

2. 文件分区的意义

2.1 减少文件锁粒度,提高并发 I/O 潜力

正如 如何实现顺序读写中指出,为了确保实现物理上真正的顺序 I/O,在涉及多线并发读写时,我们必须使用锁机制。这里的锁通常是文件锁,一个文件一把锁。锁可以由操作系统提供,但更常见的是在用户应用中额外使用一把锁。

依赖于锁机制的线程并发能力提高可以通过细化锁粒度实现。一个大文件分为多个小文件,意味着将一个大锁分为多个小锁,这样一来,锁粒度细化,线程冲突可能性降低,系统的整体 I/O 能力得到提高。

2.2 简化索引实现

一般的日志存储系统有如下特点:

为了提高日志存储系统的查询效率,我们必然需要实现索引。

在不进行日志文件分区的情况下,即只有一个日志文件,那么如果要提供随机日志查询与范围查询的能力,那么索引系统必须为每一条日志设计一个 Tree 上的节点。但是如果日志非常多,那么索引 Tree 将拥有非常多的节点,存在查询效率降低的问题。

如果进行日志分区,大日志文件分为多个小日志文件进行存储,那么如果要提供随机日志查询与范围查询能力,那么我们可以为每一个小日志文件分别设计一个索引文件,由于每一个索引 Tree 的节点数不会特别多,因此我们总是能够确保较好的查询效率。

Kafka 的日志索引就基于此思想实现。

2.3 分磁盘存储文件提高磁盘 I/O 效率

文件分区的另一个含义是将不同文件存储于不同磁盘上,不过前提自然是你拥有多个磁盘与需要多个文件。正如前文所属,MySQL 通常推荐将事务日志文件(WAL)与数据文件(B+Tree)分别存储于本机上挂载的不同磁盘上。

分磁盘存储文件的优势主要有如下:

  1. 实现并行磁盘 I/O;
  2. 不同文件的 I/O 模式特质不同(顺序 or 随机);
  3. 更可靠的持久化保证;

1.并行磁盘 I/O

多个磁盘具备属于各自的驱动,因此可以进行并行的磁盘 I/O(你可以想象多个磁盘的磁头在并行移动),比单磁盘的操作系统在磁盘 I/O 具备更好的性能。

2.屏蔽不同磁盘 I/O 方式之间的干扰

另一方面,不同文件的 I/O 模式特性不同。例如,MySQL 中的事务日志文件主要进行顺序 I/O 读写,而数据文件(B+Tree)主要进行随机 I/O 读写。如果随机 I/O 与顺序 I/O 共用一块磁盘,那么随机 I/O 会影响顺序 I/O 的磁盘调度,导致磁盘吞吐量下降。

3.更可靠的持久化保证

如果数据本身所在的磁盘损坏了,但是你有在另一个磁盘上存储着 tail-of-the-log backup,那么重新执行一遍写日志那么就能够得到完全一样的数据。这种情况下,持久化机制更可靠了。例如假设一个磁盘一年内发生损坏的概率为 2%,那么持久化的可靠性可以通过双磁盘提高至 1-2%*2% =99.96%。

REFERENCE