nginx的directio_alignment仅控制directio读取时缓冲区内存地址对齐,不涉及写入;真正实现文件块与底层对齐需确保文件偏移、i/o长度和缓冲区地址三者均满足设备逻辑扇区(如4096字节)约束,并通过blockdev或lsblk确认真实参数,xfs/nvme等场景须设为4096。

Nginx 的 directio_alignment 参数本身不控制写入对齐,它仅影响 directio 模式下读取时缓冲区内存地址的对齐要求。真正决定“文件块与底层文件系统完全对齐”的,是三个要素的协同:文件偏移(offset)、I/O 长度(count)和用户态缓冲区地址(buf)——这三者都必须满足底层块设备的逻辑扇区对齐约束。
所以优化目标不是调大 directio_alignment 就完事,而是让整个 I/O 路径在读/写时都符合设备真实对齐边界。
确认底层设备的真实对齐参数
别凭经验猜。用命令查清物理和逻辑扇区大小、对齐偏移:
-
逻辑扇区大小(LSS):运行
sudo blockdev --getss /dev/sdX(常见为 512 或 4096) -
物理扇区大小(PSS):运行
sudo blockdev --getpbsz /dev/sdX(NVMe/XFS 常为 4096) -
对齐偏移(ALIGNMENT):运行
sudo blockdev --getalignoff /dev/sdX(多数为 0,表示 LBA 0 对齐) - 一键汇总:
lsblk -o NAME,LOG-SEC,PHY-SEC,ALIGNMENT /dev/sdX
若设备报告 PHY-SEC=4096 且 ALIGNMENT=0,则所有 I/O 必须以 4096 字节为单位对齐起始 offset 和长度,缓冲区地址也需 4096 对齐。
在 Nginx 中正确配置 directio_alignment
该参数只对 Nginx 启用 directio(即带 O_DIRECT 的读操作)生效,且仅约束其内部分配的读缓冲区地址对齐。它不影响你用 alias 或 root 提供的文件本身的布局。
- 默认值
512适用于传统 ext4 + SATA HDD 场景 - 使用 XFS 文件系统时,必须设为
4096(XFS 默认 stripe unit 是 4K,且元数据/extent 对齐强制 4K) - 若后端是 NVMe 或 Ceph RBD,且
rbd info显示 object-size=4M、alignment=4096,也应配directio_alignment 4096 - 配置位置只能是
http、server或location块,例如:
location /static/ {
alias /data/static/;
directio 1m;
directio_alignment 4096;
}确保文件内容本身物理对齐(常被忽略的关键)
Nginx 不会重排你的文件。如果文件是用普通 cp 或 echo 写入的,很可能未对齐——尤其是小文件或追加写场景。这会导致即使 Nginx 缓冲区对齐了,实际读取仍触发内核 fallback 到 buffered I/O,失去 directio 效果。
- 创建新文件时,用
dd指定oflag=direct和对齐的bs,例如:dd if=/dev/zero of=/data/static/video.mp4 bs=4096 count=1024 oflag=direct - 已有文件可检查是否对齐:
stat -c "size:%s offset:%o" /data/static/video.mp4→ 看 size 和 offset 是否都是 4096 的倍数 - XFS 用户可用
xfs_info /mount/point查看agsize和sectsize,再配合xfs_db -r -c "freesp -h" /dev/sdX观察空闲空间分布
写入路径不走 Nginx directio,需单独处理
Nginx 本身不提供 directio 写入能力(directio 指令仅作用于 响应体读取,即 sendfile/directio 读磁盘文件发给客户端)。如果你的应用有大文件上传并希望直写磁盘:
- 后端服务(如 Go/Python)需自行用
O_DIRECT打开文件,并用posix_memalign(..., 4096, ...)分配缓冲区 - 上传临时文件应先写入对齐 buffer,再
pwrite到对齐 offset;避免lseek + write因中间状态不对齐而失败 - 不要依赖
sync_file_range()或fdatasync()替代对齐——它们解决持久化,不解决对齐











