Linux 7.0 稳定版还有半个月就要发布了,但 AWS 工程师发现采用 Linux 7.0 内核的PostgreSQL数据库服务器(AWS Graviton4服务器)性能下降了,吞吐量只有原来内核版本的一半。
那到底怎么一回是事情呢?我觉得还挺有意思的。
在 Linux 7.0 之前的内核版本中,Linux 内核调度器的抢占策略包含三种,大概含义如下:
- • PREEMPT_VOLUNTARY 半抢占模式
很明显,对于 PostgreSQL 来说,PREEMPT_NONE 对它更有利,PostgreSQL 内部大量使用spinlock(自旋锁),采用的就是PREEMPT_NONE,它拿到锁后基本就不会被打断,减少了上下文切换,性能就高了。
如果此时另外一个程序也在竞争spinlock,就只能一直空转等待。当然如果数据库服务器一般不会安装其它服务,这种设计还是可以的。
而 Linux 7.0 内核干了一件事情,废除了 PREEMPT_FULL、PREEMPT_NONE,新增了 PREEMPT_LAZY。
现在 Linux 7.0 抢占策略包括两种了:
- • PREEMPT_FULL 完全抢占模式,就是说内核随时可以切换上下文
- • PREEMPT_LAZY 比 PREEMPT_NONE 灵活一些,内核会去切换,但会晚一点
Linux 7.0 内核默认抢占模式是 PREEMPT_LAZY。
这导致 PostgreSQL 随时可能被内核切换,但 spinlock 锁又卡住了,而其它也使用 spinlock 的程序就一直空转,导致白费 CPU,吞吐量下降了。
Linux 内核社区认为新的调度器抢占策略更公平,你觉得呢?
考虑到 Ubuntu 26.04 LTS(采用Linux 7.0 内核) 还有一个月就要发布,PostgreSQL 社区希望先恢复原有的调度器抢占策略。
这招真熟悉啊,工作中遇到过很多这样的事情,“现在时间太少了,这项目太重要,先帮我恢复解决下,我后续改”,但其实没后续了。
Linux 内核社区建议 PostgreSQL 采用 rseq slice extension 扩展,注意这个扩展并不在内核中,就算能解决 PostgreSQL 问题,也需要发行版自己编译安装。
对于 PostgreSQL 来说这是致命的,依赖一个不在内核中的扩展,将来安装维护太费劲了。
rseq slice extension 能解决实际问题吗?
大概的意思就是程序告诉内核,我这个任务可能需要多一些时间运行,你先别内核切换,看上去。
但Linux内核开发者说了,你用的时候别太过分,如果长时间不运行完成,可能还是会被切换。
静待这件事情的后续。也欢迎进群聊聊技术: