撕裂写防护
撕裂写防护是由 AWS 设计的块存储功能,可提高 I/O 密集型关系数据库工作负载的性能并减少延迟,而不会对数据弹性产生负面影响。使用 InnoDB 或 XtraDB 作为数据库引擎的关系数据库,例如 MySQL 和 MariaDB,将受益于撕裂写防护这一功能。
通常,使用大于存储设备断电原子性的页面的关系数据库使用数据记录机制来防止撕裂写。MariaDB 和 MySQL 在将数据写入数据表之前使用双写缓冲区文件来记录数据。如果写入事务期间由于操作系统崩溃或断电导致写入不完整或撕裂,数据库可以从双写缓冲区恢复数据。与写入双写缓冲区相关的 I/O 额外开销会影响数据库性能和应用程序延迟,并减少每秒可处理的事务数量。有关双写缓冲区的更多信息,请参阅 MariaDB
借助撕裂写防护功能,可以在全有或全无的写入事务中将数据写入存储,这样就无需使用双写缓冲区。这样可以防止在写入事务期间因操作系统崩溃或断电将部分或撕裂的数据写入存储。在不影响工作负载弹性的情况下,每秒处理的事务数量最多可增加 30%,写入延迟最多可减少 50%。
定价
使用撕裂写防护功能不会产生额外费用。
支持的块大小和块边界对齐
撕裂写防护支持 4 KiB、8 KiB 和 16 KiB 数据块的写入操作。数据块起始逻辑块地址(LBA)必须与 4 KiB、8 KiB 或 16 KiB 的相应块的边界大小对齐。例如,对于 16 KiB 写入操作,数据块起始 LBA 必须与 16 KiB 的块边界大小对齐。
下表显示了跨存储和实例类型的支持。
4 KiB 块 | 8 KiB 块 | 16 KiB 块 | |
---|---|---|---|
实例存储卷 | 所有 NVMe 实例存储卷都附加到当前 I 代新系列实例。 | AWS Nitro SSD 支持 I4i、Im4GN 和 Is4Gen 实例。 | |
Amazon EBS 卷 | 所有 Amazon EBS 卷都附加到基于 nitro 的实例。 |
要确认您的实例和卷是否支持撕裂写防护,请查询以检查该实例是否支持撕裂写防护以及其他详细信息,例如支持的块和边界大小。有关更多信息,请参阅检查撕裂写防护支持和配置。
要求
要使撕裂防护功能正常运行,I/O 操作必须符合 NTWPU
、NTWGU
、NTWBU
字段中指定的大小、对齐方式和边界要求。在提交到设备之前,必须配置操作系统,确保特定的存储子系统(文件系统、LVM、RAID 等)不会修改存储堆栈中的 I/O 属性,包括块合并、拆分或块地址重新定位。
已使用以下配置测试了撕裂写防护功能:
-
支持所需块大小的实例类型和存储类型。
-
Amazon Linux 2 或更高版本(内核版本为 5.10)。
-
已启用
bigalloc
的 ext4,集群大小为 16 KiB,还有最新的 ext4 实用程序(e2fsprogs 1.46.5 或更高版本)。 -
O_DIRECT
文件访问模式可绕过 Linux 内核缓冲区缓存。
注意
您无需禁用 MySQL 和 MariaDB 工作负载的 I/O 合并。
检查撕裂写防护支持和配置
要确认您的实例和卷是否支持撕裂写防护,并查看包含撕裂写防护信息的 NVMe 命名空间供应商的特定数据,请使用以下命令。
$
sudo nvme id-ns -vdevice_name
注意
该命令以带有 ASCII 解释的十六进制形式返回供应商特定信息。您可能需要在应用程序中构建类似 ebsnvme-id
的工具,以读取和解析输出。
例如,以下命令返回 NVMe 命名空间供应商特定数据,其中包含 /dev/nvme1n1
的撕裂写防护信息。
$
sudo nvme id-ns -v /dev/nvme1n1
如果您的实例和卷支持撕裂写防护功能,其会在 NVMe 命名空间供应商特定数据中返回以下 AWS 撕裂写防护信息。
注意
下表中的字节表示从 NVMe 命名空间供应商特定数据开头的偏移量(以字节为单位)。
字节 | 描述 |
---|---|
0:31 |
设备附件挂载点的名称,例如 /dev/xvda 。您在卷附件请求期间提供此信息,Amazon EC2 实例可用其来创建指向 NVMe 区块设备的符号链接(nvmeXn1 )。 |
32:63 |
卷 ID。例如,vol01234567890abcdef 。此字段可用于将 NVMe 设备映射到附加的卷。 |
64:255 |
留待将来使用。 |
256:257 |
命名空间撕裂写防护单元大小(NTWPU)。此字段表示在断电或发生错误时,保证以原子方式写入 NVM 的写入操作的命名空间特定大小。此字段在逻辑块中指定,从以零开始的值表示。 |
258:259 |
命名空间撕裂写防护粒度大小(NTWPG)。此字段表示在断电或发生错误时,保证以原子方式写入 NVM 的写入操作的 NTWPU 下的命名空间特定大小增量。也就是说,大小应为 NTWPG * n <= NTWPU ,其中 n 为正整数。写入操作 LBA 偏移量也必须与该字段对齐。此字段在逻辑块中指定,从以零开始的值表示。 |
260:263 |
命名空间撕裂写防护边界大小(NTWPB)。此字段表示该 NTWPU 值的此命名空间的原子边界大小。在断电或发生错误时,无法将保证跨原子边界写入此命名空间的操作以原子方式写入 NVM。值为 0h 表示断电或发生错误时没有原子边界。所有其他值使用与 NTWPU 字段相同的编码以逻辑块形式指定大小。 |
配置您的软件堆栈以防止撕裂写
具有支持卷的受支持的实例类型上默认启用撕裂写防护功能。您无需启用任何其他设置即可启用卷或实例的撕裂写防护功能。
注意
对不支持撕裂写防护的工作负载不会产生性能影响。您无需对这些工作负载进行任何更改。
支持撕裂写防护但未配置使用该功能的工作负载会继续使用双写缓冲区,不会获得任何性能优势。
要将 MySQL 或 MariaDB 软件堆栈配置为禁用双写缓冲区并使用撕裂写防护功能,请完成以下步骤:
-
将您的卷配置为使用带有 BigAlloc 选项的 ext4 文件系统,并将集群大小设置为 4 KiB、8 KiB 或 16 KiB。使用集群大小为 4 KiB、8 KiB 或 16 KiB 的 BigAlloc,可确保文件系统分配与各自边界对齐的文件。
$
mkfs.ext4 -O bigalloc -C4096|8192|16384
device_name
注意
对于 MySQL 和 MariaDB,必须使用
-C 16384
来匹配数据库页面大小。将分配粒度设置为页面大小倍数以外的值可能会导致分配与存储设备撕裂写防护边界不匹配。例如:
$
mkfs.ext4 -O bigalloc -C 16384 /dev/nvme1n1 -
将 InnoDB 配置为使用
0_DIRECT
刷新方法并关闭 InnoDB 双写模式。使用首选文本编辑器打开/etc/my.cnf
,更新innodb_flush_method
和innodb_doublewrite
参数,如下所示:innodb_flush_method=O_DIRECT innodb_doublewrite=0
重要
如果您使用的是逻辑卷管理器(LVM)或其他存储虚拟化层,请确保卷的起始偏移量以 16 KiB 倍数对齐。这是相对于底层 NVMe 存储而言,用以考虑存储虚拟化层使用的元数据标头和超级块。如果您向 LVM 物理卷添加偏移量,则可能引起文件系统分配与 NVMe 设备的偏移量有偏差,从而导致撕裂写防护失效。有关更多信息,请参阅 Linux manual page--dataalignmentoffset
。