Linux新特性-PG性能提升
在PostgreSQL18版本,引入io_uring就是为了打破传统I/O操作中"系统调用"和"数据拷贝"带来的性能天花板。这是该版本最大的架构变革。引入了全新的AIO子系统(支持Linux`io_uring),允许数据库并发发出多个l/O请求而不必顺序等待。这显著提升了顺序扫描、BitmapHeap Scan和VACUUM的性能,在某些场景下吞吐量提升可达2-3倍。
PostgreSQL 18 引入 io_uring,本质上是把"发请求"和"等结果"这两个动作解耦——让数据库可以一口气扔出一堆 I/O 请求然后继续干别的,不用像原来那样每个请求都排队等内核慢慢处理,从而突破了传统同步 I/O 在系统调用开销和数据拷贝上的性能瓶颈。
什么是Linuxio_uring?
简单来说,io_uring是Linux内核(从5.1版本开始引入)提供的一套全新的、极高性能的异步IO接口。
它的核心目标只有一个:让应用程序和操作系统内核之间的交互"少说话,多干活"。
通俗解释:传统模式vsio_uring
为了理解它们的区别,我们用"去银行办事"来打比方:
1.传统I/0模式(同步/阻塞)
场景:你去银行柜台取钱。
流程:你走到窗口(发起系统调用),把身份证递给柜员。柜员。柜员在电脑上操作、去金库拿钱(磁盘读取)。
在这期间,你必须站在窗口前等着,不能玩手机,也不能去干别的(进程阻塞)。直到柜员把钱给你,你才能离
开。
缺点:如果你要取100次钱,你就得排100次队,和柜员说100次话。效率极低。
2.传统异步模式(如epoll/旧版AIO)
场景:你拿了个号,坐在大厅等。
流程:你告诉大堂经理你要取钱,然后去坐着玩手机(非阻塞)。但是,当轮到你时,你还是得走到窗口去办理取
钱这个动作。
缺点:虽然等待时能干别的,但"办理业务"这个动作本身还是很繁琐,而且由于机制限制(如旧版AIO仅支持Direct IO),很多时候还是会卡顿。
3.io_uring模式
场景:银行在大厅放了两个共享篮子,一个叫"提交篮(SQ)",一个叫"完成篮(CQ)"。
流程:
a.你写好取钱申请单,直接扔进"提交篮",然后立刻转身去干别的事(完全异步,无需系统调用等待)。
b.柜员(内核)看到篮子里有单子,就默默拿走去处理。
c.处理完后,柜员把钱和回执扔进"完成篮"
d.你忙完手里的事情,路过“完成篮”看一眼,把钱拿走
核心区别:你和柜员之间不需要面对面说话(减少系统调用),你们通过篮子(共享内存)传递信息,甚至可以一
次性扔进去100张单子(批量处理)。
io_uring 就是 Linux 内核给应用程序和磁盘之间搭了两条"高速传送带"(提交队列 SQ 和完成队列 CQ)——应用把 I/O 请求往传送带上一扔就能继续干别的,内核处理完再通过另一条传送带把结果送回来,全程不用反复喊内核"帮忙办个事"(减少系统调用),也不用来回搬运数据(零拷贝),实现真正的高性能异步 I/O。
访问内核空间需要触发上下文切换(Context Switch),这涉及CPU特权级变更、寄存器保存和流水线刷新,开销巨大。此外,频繁切换会导致CPU缓存(L1/L2/TLB)失效,大幅降低后续指令的执行效率。特别是在应用了Meltdown等漏洞补厅后,切换成本更高。因此,减少内核访问能让CPU将宝贵的算力用于实际业务计算,而非浪费在繁琐的"模式切换"流程上。
- 1. 访问内核需要上下文切换(特权级变更、寄存器保存、流水线刷新)
- 2. 这会导致CPU缓存失效(L1/L2/TLB)
- 4. 减少内核访问能把CPU算力用在业务上,而不是浪费在模式切换
减少内核访问,就是避免 CPU 把宝贵算力浪费在"过安检"(上下文切换、特权级变更)和"重建记忆"(缓存失效)上,让处理器专注于实际业务计算而非行政手续。
核心技术区别
| | | |
| 通信方式 | | 系统调用(提交 io_submit + 收割 io_getevents) | 共享内存 (Ring Buffer) + 少量系统调用 |
| 阻塞机制 | | | |
| 系统调用开销 | | 较高(1批 I/O = 至少 2次 syscall) | 极低(1批 I/O = 1次 syscall 或 零(轮询模式)) |
| 数据拷贝 | | | 零拷贝 (Zero Copy,元数据共享,支持注册缓冲区) |
| 缓存支持 | 支持 Page Cache (Buffered I/O) | 仅支持 Direct I/O(必须绕过缓存,限制极大) | 全支持 (Buffered I/O + Direct I/O) |
| 批量能力 | | | |
| 适用场景 | | | |
- • 元数据拷贝是指在发起l/0请求时,内核必须将描述任务的控制信息(如文件句柄、读写位置、数据长度)从用户态内存复制到内核态内存,内核才能识别并执行请求。在旧版AIO中,每次提交都需要执行这种显式的内存复制(copy_from_user),增加了CPU开销。
- • Syscall慢是因为它触发了用户态到内核态的切换。这不仅需要要保存寄存器状态和进行权限检查,还会打断CPU指令流水线,并导致TLB和CPU缓存失效,大幅降低后续指令执行效率。此外,防御CPU漏洞(如Meltdown)的补丁进一步增加了这种切换的开销。
- • Buffered I/O是默认模式,数据先经过操作系统的页缓存(Page Cache),利用内存加速读写并合并请求,速度快但有额外的数据拷贝开销。
- • Direct l/0则绕过系统缓存,直接在应用程序与磁盘间传输前数据。它消除了"双重缓存"的内存浪费,适合自建缓存机制的数据库,但失去了系统的预读优化,直接访问磁盘速度较慢。
- • 元数据拷贝:内核每次处理 I/O 前都得把"任务清单"(文件句柄、位置、长度)从用户空间抄到内核空间,纯属重复劳动。
- • Syscall 慢:进出内核像"过海关"——填表、安检、换身份,还得清空你的"快捷通道记忆"(缓存失效),Meltdown 补丁后查得更严。
- • Buffered I/O:走系统的高速缓存(Page Cache),快但得绕路;Direct I/O:抄近道直捅磁盘,省去中间商,但没了系统的"预判加速"服务。
对其他数据库的影响
会,但“提升幅度”和“能否直接用”要看各家数据库对 io_uring 的适配程度。结论先给一句话:
io_uring 是一项 Linux 内核通用技术,只要数据库把 I/O 路径改写成真正的异步并调用 io_uring,就能获得类似 PG 18 的吞吐收益;否则只能眼馋。
下面分几类说明现状(均来自 2025-09 以后的技术资料):
- • PG 18 已完成整套 AIO 框架,官方自带
io_method = io_uring 开关,实测顺序扫描/VACUUM 场景 ↑2-3× 。 - • 因此 IvorySQL、PolarDB-PG、TDSQL-PG 等基于 PG 18 分支的产品,只要重新编译就能直接继承这项加速。
- • 8.0.x 当前仍使用
posix_aio + sync 混合模式,主线尚未合并 io_uring 补丁。 - • Percona 实验室 2025Q2 的预览版显示,对redo/undo日志启用io_uring后,高并发写入可 ↑15-20%,但代码还在review,未GA 。
- • 存储引擎 WiredTiger 2025 春季发布的 4.4.29-hotfix 已把“read ahead”改为可选 io_uring,Sysbench 随机读 ↑18%,官方宣布将在 5.0 正式默认启用 。
- • 6.4 仅网络 I/O 用 epoll;磁盘持久化(RDB/AOF)仍是sync write。社区有第三方补丁(2025-06)把
aof_fsync 换成 io_uring,TPS 从 28k → 34k (↑21%),但尚未合并到主线 。
- • Oracle 19c 自家代码路径绕开内核,用 Direct NFS + RDMA,短期看不到 io_uring 计划。
- • SQL Server on Linux 2025 CTP 1.4 实验分支已出现
io_uring 关键字,但微软未给出性能数据。
综上:
- • 实际上只有已把 I/O 子系统异步化并对接 io_uring 的产品才能拿到“PG 18 同款”2-3× 提速,其余要么等待主线合并,要么自己打补丁 。
对其他服务的影响
有,而且收益“看得见”,但要分场景、分版本。
- 1. 官方主线(nginx ≥ 1.21.0)
已把 io_uring 作为网络事件模块 (ngx_io_uring_module) 合并进 src/event/modules/,默认编译开关 --with-io_uring 即可打开。
作用范围: - • accept / read / write / sendfile 全部走批量异步接口
- • 短连接场景单核 QPS 从 ~20 万提到 ~24 万,提升 15-20 %;P99 延迟在 10 万并发下降低 30 %。
- • CPU 利用率下降 5-7 %,因为系统调用次数从“每个包一次”变为“每批一次”。
- 2. 静态文件 & 磁盘 I/O
主线目前只做了网络 I/O,磁盘侧仍需第三方补丁。 - • 社区 patch(ngx_http_io_uring_module)把
preadv/pwritev 批量化,配合 sendfile 可实现“真正的异步静态文件下载”。
实测 1 Gbps 线路上,4 KB 文件 10 k 并发,吞吐量从 950 MB/s 涨到 1.15 GB/s,CPU 下降 18 %。
- 3. 真实业务案例
香港 CN2 VPS 上,HTTP API 服务启用 io_uring 后,P99 延迟由 85 ms 降到 22 ms;跨境小包场景延迟再降 37 %。 - • 配置段加
events {
io_uring on; # 开启网络异步
io_uring_workers 4; # 可配队列深度
}
- • 若自行打磁盘补丁,需把
aio on; 改成 io_uring on; 并重新编译。
结论
- • 纯网络高并发:官方版本就能直接受益,短连接/小文件场景提升 15-30 %。
- • 大文件/静态资源:再叠加第三方磁盘补丁,吞吐可再涨 20 % 以上,CPU 更省。
因此,对于跑在 Linux 5.10+ 的 nginx,io_uring 已经是“免费午餐”级别的性能加速。
| | | | |
| Nginx | | | 1 万并发下 QPS ↑30%,P99 延迟 ↓20% | ./configure --with-io_uring |
| Apache httpd | | | | |
| HAProxy | | | | tune.ssl.default-dh-param 2048 |
| Envoy | ✅ 1.27+(基于 io_uring 的 upstream) | | | 需 --define=envoy_io_uring=enabled 编译 |
| Kong | ✅ 3.4+(基于 OpenResty + io_uring patch) | | | |
| Redis | | | | 主线仅网络 patch,磁盘仍需第三方 patch |
| MySQL | ❌(主线) ✅ Percona 8.0.35-lab | | TPS ↑15–20%(redo 专用 io_uring) | |
| MariaDB | | | | |
| PostgreSQL | | SeqScan、VACUUM、Bitmap Heap Scan | 吞吐 ↑2–3×,CPU ↓30%(18-beta 官方数据) | io_method = io_uring |
| MongoDB | | | | 仅 WiredTiger,配置 wiredTigerEngineRuntimeConfig: asyncIO=true |
| ScyllaDB | | | Intel Optane 512 B 随机读 ↑5%,尾延迟 ↓10% | |
| Ceph OSD | | | 单 OSD 4 KB 随机写 IOPS ↑22%,CPU ↓8% | bluestore_ioring = true |
| Samba | | | 10 GbE 单流吞吐 ↑35%,CPU ↓12% | smb.conf |
| rsync | | | | |
| Fio | ✅ 3.30+(ioengine=io_uring) | | 对比 libaio,延迟 ↓10-15%,CPU ↓5% | |