ZFS 事务延迟
当后端存储无法适应传入写入的速率时,ZFS 写入操作会被延迟。这个延迟过程被称为 ZFS 写入节流。
如果已经有一个写入事务在等待,延迟是相对于该事务完成等待的时间计算的。因此,计算的延迟时间与并发执行事务的线程数量无关。
如果只有一个等待者,延迟是相对于事务开始的时间计算的,而不是当前时间。这为事务“已经服务的时间”提供了信用。例如,如果一个写入事务需要先读取间接块,则延迟在事务开始时计算,就在间接块读取之前。
事务的最小时间计算如下:
min_time = zfs_delay_scale * (dirty - min) / (max - dirty)
min_time 然后被限制在 100 毫秒
延迟有两个可以通过可调参数调整的自由度:
开始延迟的脏数据百分比由 zfs_delay_min_dirty_percent 定义。这通常位于或高于 zfs_vdev_async_write_active_max_dirty_percent,以便在全速写入无法跟上传入写入速率后发生延迟。
曲线的比例由 zfs_delay_scale 定义。粗略地说,这个变量决定了曲线中点的延迟量。
delay
10ms +-------------------------------------------------------------*+
| *|
9ms + *+
| *|
8ms + *+
| * |
7ms + * +
| * |
6ms + * +
| * |
5ms + * +
| * |
4ms + * +
| * |
3ms + * +
| * |
2ms + (midpoint) * +
| | ** |
1ms + v *** +
| zfs_delay_scale ----------> ******** |
0 +-------------------------------------*********----------------+
0% <- zfs_dirty_data_max -> 100%
请注意,由于延迟是添加到最近事务的剩余未完成时间上的,延迟实际上是 IOPS 的倒数。这里的中点 500 微秒转换为 2000 IOPS。选择曲线的形状使得在曲线的前 3/4 部分,脏数据量的微小变化会产生相对较小的延迟差异。
当延迟量以对数刻度表示时,效果更容易理解:
delay
100ms +-------------------------------------------------------------++
+ +
| |
+ *+
10ms + *+
+ ** +
| (midpoint) ** |
+ | ** +
1ms + v **** +
+ zfs_delay_scale ----------> ***** +
| **** |
+ **** +
100us + ** +
+ * +
| * |
+ * +
10us + * +
+ +
| |
+ +
+--------------------------------------------------------------+
0% <- zfs_dirty_data_max -> 100%
请注意,只有当脏数据量接近其限制时,延迟才开始迅速增加。适当调优的系统的目标应该是通过首先确保为 I/O 调度器设置适当的限制以达到后端存储的最佳吞吐量,然后通过更改 zfs_delay_scale 的值来增加曲线的陡度,从而将脏数据量保持在该范围之外。