PostgreSQL 网络延迟 瓶颈定量分析

6 minute read

背景

在使用sysbench或者pgbench测试数据库性能时,连unix socket, loop address性能差异是非常大的,特别是非常小的事务,例如基于KEY的查询,或者select 1这样的简单查询。

原因是这种查询在数据库端的处理非常快,从而网络延迟在整个耗时占比上就会比较大。

还有一种场景结果集比较大,网络延迟在整个耗时占比上也会比较大。

那么如何来定量分析呢?

1. 分析包的大小,可以通过tcpdump抓包,取得数据库请求过程中传输的包大小和数量。

2. 或者从PostgreSQL源码中,根据实际的查询计算对应的包大小,例如libpq。

网络延迟的定量分析

以 select 1; 为例分析。

如何计算出一个请求在数据库处理的耗时,以及在网络传输段的耗时?

网络传输端的耗时,可以通过前面拿到的包大小,然后使用网络延迟分析工具例如 qperf 得到。

例子:

假设通过tcpdump得到的 select 1; 的包大小为16字节(去除TCP包头)。

使用qperf测试单会话下的16字节包tcp延迟。

启动qperf服务端

yum install -y qperf  
  
qperf -lp 8888 &  

测试回环地址8-16字节 TCP包延迟

qperf 127.0.0.1 -lp 8888 -t 6 -oo msg_size:8:64:*2 -v tcp_lat &    
latency        =  5.16 us  
    msg_rate       =   194 K/sec  
    msg_size       =    16 bytes  
    time           =     6 sec  
    loc_cpus_used  =  86.8 % cpus  
    rem_cpus_used  =  86.8 % cpus  

测试 select 1 的qps

vi test.sql    
select 1;    
  
pgbench -M prepared -n -r -P 1 -f ./test.sql -c 1 -j 1 -T 10 -h 127.0.0.1    
tps = 36938.282331 (including connections establishing)    

根据以上QPS以及qperf测出来的网络延迟,计算出select 1的数据库处理时延,注意需要计算回包的时间,所以TCP延迟*2

(1000000/36938.03) - (5.16*2) = 16.75 us  

同局域网主机的延迟测试

qperf xxx.xxx.xxx.xxx -lp 8888 -t 6 -oo msg_size:8:64:*2 -v tcp_lat &  
tcp_lat:  
    latency        =  13.6 us  
    msg_rate       =  73.8 K/sec  
    msg_size       =    16 bytes  
    time           =     6 sec  
    loc_cpus_used  =  8.67 % cpus  
    rem_cpus_used  =   9.5 % cpus  

使用以上值,以及前面得到的数据库处理延迟,计算理论上在这台机器连接到数据库服务器进行tps测试的结果应该是

1000000 / (16.75 + 13.6*2) = 22753  tps  

实际测试得到的tps, 基本一致

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 1 -j 1 -T 10 -h xxx.xxx.xxx.xxx  
tps = 24724.666217 (including connections establishing)  

并发情况下的网络延迟分析。
启动多个qperf服务端

qperf -lp 8888 &  
qperf -lp 8889 &  
qperf -lp 8890 &  
qperf -lp 8891 &  
qperf -lp 8892 &  
qperf -lp 8893 &  
qperf -lp 8894 &  
qperf -lp 8895 &  
qperf -lp 8896 &  
qperf -lp 8897 &  
qperf -lp 8898 &  
qperf -lp 8899 &  
qperf -lp 8900 &  
qperf -lp 8901 &  
qperf -lp 8902 &  
qperf -lp 8903 &  
qperf -lp 8904 &  
qperf -lp 8905 &  
qperf -lp 8906 &  
qperf -lp 8907 &  
qperf -lp 8908 &  
qperf -lp 8909 &  
qperf -lp 8910 &  
qperf -lp 8911 &  
qperf -lp 8912 &  
qperf -lp 8913 &  
qperf -lp 8914 &  
qperf -lp 8915 &  
qperf -lp 8916 &  
qperf -lp 8917 &  
qperf -lp 8918 &  
qperf -lp 8919 &  
qperf -lp 8920 &  
qperf -lp 8921 &  
qperf -lp 8922 &  
qperf -lp 8923 &  
qperf -lp 8924 &  
qperf -lp 8925 &  
qperf -lp 8926 &  
qperf -lp 8927 &  
qperf -lp 8928 &  
qperf -lp 8929 &  
qperf -lp 8930 &  
qperf -lp 8931 &  
qperf -lp 8932 &  
qperf -lp 8933 &  
qperf -lp 8934 &  
qperf -lp 8935 &  
qperf -lp 8936 &  
qperf -lp 8937 &  
qperf -lp 8938 &  
qperf -lp 8939 &  
qperf -lp 8940 &  
qperf -lp 8941 &  
qperf -lp 8942 &  
qperf -lp 8943 &  
qperf -lp 8944 &  
qperf -lp 8945 &  
qperf -lp 8946 &  
qperf -lp 8947 &  
qperf -lp 8948 &  
qperf -lp 8949 &  
qperf -lp 8950 &  
qperf -lp 8951 &  

并发测试延迟

qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8888 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8889 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8890 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8891 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8892 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8893 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8894 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8895 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8896 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8897 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8898 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8899 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8900 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8901 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8902 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8903 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8904 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8905 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8906 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8907 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8908 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8909 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8910 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8911 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8912 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8913 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8914 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8915 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8916 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8917 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8918 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8919 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8920 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8921 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8922 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8923 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8924 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8925 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8926 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8927 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8928 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8929 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8930 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8931 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8932 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8933 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8934 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8935 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8936 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8937 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8938 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8939 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8940 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8941 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8942 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8943 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8944 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8945 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8946 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8947 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8948 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8949 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8950 tcp_lat &  
qperf 127.0.0.1 -t 6 -oo msg_size:16:16:*2 -v -lp 8951 tcp_lat &  

回环地址,64个并发的延迟约11.8us

latency        =   11.8 us  

测试64个并发的tps,并计算出数据库端的耗时(64核的机器)

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 64 -j 64 -T 10 -h 127.0.0.1  
  
tps = 1575989.161924 (including connections establishing)  

计算出数据库的RT
与单进程的RT基本一致,说明现在PostgreSQL在高并发下的处理能力已经非常强大了,充分利用了CPU的多核,并且性能是线性的。

(1000000/(1575989.161924/64)) - (11.8*2) = 17 us  

在远端主机测试网络延迟
从测试结果来看,已经大大超出了数据库本地处理的时间,网络成了最大的瓶颈

qperf xxx.xxx.xxx.xxx -t 6 -oo msg_size:16:16:*2 -v -lp 8888 tcp_lat &  
...  
qperf xxx.xxx.xxx.xxx -t 6 -oo msg_size:16:16:*2 -v -lp 8951 tcp_lat &  
  
latency        =  61.8 us  

推算出64并发的TPS

(1000000/(17 + 61.8*2)) * 64 = 455192  

推算出来的TPS与实际测出来的TPS基本一致

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 64 -j 64 -T 10 -h xxx.xxx.xxx.xxx  
tps = 466737.781999 (including connections establishing)  

以上是网络延迟的定量分析,网络延迟在高并发的数据库应用中,影响还是非常大的。

参考

1. man tcpdump

2. man qperf

3. man iperf

4. http://blog.yufeng.info/archives/2234

Flag Counter

digoal’s 大量PostgreSQL文章入口