天天看點

從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》

祝大家玩得開心,歡迎随時來 阿裡雲促膝長談業務需求 ,恭候光臨。

阿裡雲的小夥伴們加油,努力 做好核心與服務,打造最貼地氣的雲資料庫 。