天天看点

从PostgreSQL支持100万个连接聊起

100万个数据库连接,绝逼疯了,常人怎么会干这种事情。

没错,数据库支持100万个连接意味着什么呢?不能用连接池吗?

除了抱着玩一玩的心态,也能了解到操作系统层的一些知识,何乐不为?

根据我前几天写的《如何度量kernel resources for postgresql》,我们可以评估得出,如果要支持100万个数据库客户端连接,操作系统应该如何配置。

<a href="https://yq.aliyun.com/articles/58690">https://yq.aliyun.com/articles/58690</a>

但是实际上能如愿吗?

以postgresql 9.5为例,100万个连接,需要多少信号量?

需要多少组信号量?

100万连接,semmni &gt;= 62500

需要多少信号量?

100万连接,semmns &gt;= 1062500

每组需要多少信号量?

测试环境如下

centos 6.x x64, 512gb内存。

以上内核配置,信号量完全满足100万连接需求。

那么数据库能启动吗?

启动失败。

报错来自如下代码:

使用semget创建sem失败。

src/backend/port/sysv_sema.c

semget之所以失败,并不是kernel.sem的配置问题,而是操作系统内核的宏限制。

sem的分组数量不能大于semvmx,也就是说,最多能开50多万个连接。

如下

kernels/xxx.x86_64/include/uapi/linux/sem.h

超过32767个array后会报错

使用ipcs -l也能查看到当前值

这个值只能重新编译内核来修改。

在semctl和semop的手册中也能看到,有此说法。

100万连接没戏了吗?

当然可以办到。

例如修改semvmx,并重新编译内核显然是一条路,但是还有其他路子吗?

我们前面看到,报错的代码是

internalipcsemaphorecreate@src/backend/port/sysv_sema.c

查看对应头文件,发现pg支持几种创建信号量的方式,真的是柳暗花明又一春 :

sysv, posix(named , unamed), win32

对应的头文件源码如下

src/include/storage/pg_sema.h

其中posix的named和unamed分别使用如下系统调用

posix named 方式创建信号 :

posix unamed 方式创建信号 :

posix源码如下,注意用到的宏

src/backend/port/posix_sema.c

从src/include/storage/pg_sema.h 可以看到,在pg_config.h中必须有一个指定的use_xxx_semaphores symbols。

这个symbol不是直接设置pg_config.h来的,是在configure时设置的,会自动加到pg_config.h 。

默认使用sysv,如果要使用其他的sem方法。

可以这么做

记得加-lpthread ,否则报错

通过这些系统调用的linux编程帮助文档,了解一下posix的信号量管理

可以得知sem_open 也受到semvmx的限制

因此为了在不修改内核的情况下,实现postgresql支持100万个连接,甚至更多。

必须使用use_unnamed_posix_semaphores

使用use_unnamed_posix_semaphores编译

修改参数,允许100万个连接

重启数据库

pgbench是很好的测试工具,只不过限制了1024个连接,为了支持100万个连接测试,需要修改一下。

代码

测试表

测试脚本

开始压测,遇到第一个问题

这个问题还好,是打开文件数受限,改一些限制就可以解决

修改ulimit

修改内核参数

重测,再次遇到问题,原因是pgbench使用了ip地址连接pg,导致pgbench的动态端口耗尽。

换成unix socket连接即可解决。

不能fork new process,后面跟了个cannot allocate memory这样的提示,我看了当前的配置

于是我加了交换分区,同时改了几个参数

重新测试,发现还是有问题

使用以下手段观测,发现在约连接到 65535 时报错

找到了根源,是内核限制了

修改一下这个内核参数

重新测试

继续观测

连接到26万时,内存用了约330gb,每个连接1mb左右。

看起来应该没有问题了,只要内存足够是可以搞定100万连接的。

为了让postgresql支持100万个并发连接,除了资源(主要是内存)要给足。

数据库本身编译也需要注意,还需要操作系统内核也需要一些调整。

编译postgresql 时使用 posix unname sem 。

如果你不打算使用unnamed posix sem,那么务必重新编译操作系统内核,增加semvmx.

打开文件数限制

ulimit

使用unix socket

突破pgbench测试时,动态端口数量限制。

每个连接约1mb,100万个连接,需要约1tb内存,需要给足内存。

启用swap

实际上还是发生了oom,而且hang了很久。

最大pid值的限制

加大

pgbench客户端的限制

修改源码,支持无限连接。

ipcs不统计posix sem的信息,所以使用posix sem后ipcs看不到用了多少sem.

system v 与 posix sem

《dba不可不知的操作系统内核参数》

<a href="https://yq.aliyun.com/articles/58751">https://yq.aliyun.com/articles/58751</a>

《如何度量kernel resources for postgresql》

祝大家玩得开心,欢迎随时来 阿里云促膝长谈业务需求 ,恭候光临。

阿里云的小伙伴们加油,努力 做好内核与服务,打造最贴地气的云数据库 。