| pgpool-II多种应用场景性能测试报告 原作者:阿弟 创作时间:2017-08-13 11:00:58+08 |
doudou586 发布于2017-08-13 11:00:58
评论: 2
浏览: 28056
|
欢迎大家踊跃投稿,投稿信箱: press@postgres.cn
| 项目 | 型号或大小 |
|---|---|
| CPU | Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz 8核心 16线锃 * 1 |
| RAM | 64G |
| 硬盘 | 4*600G SAS 15k 组成raid10 |
| 列阵卡 | H710 Mini |
| 写入方式 | Write Back |
| 项目 | 型号或大小 |
|---|---|
| CPU | Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz 6核心 12线锃 * 1 |
| RAM | 32G |
| 硬盘 | 300*1 SAS 15k |
| 列阵卡 | H310 Mini |
| 写入方式 | Write Through |
和
| 项目 | 型号或大小 |
|---|---|
| CPU | Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz 8核心 16线锃 * 1 |
| RAM | 64G |
| 硬盘 | 4*600G SAS 15k 组成raid10 |
| 列阵卡 | H310 Mini |
| 写入方式 | Write Through |
| 项目 | 型号或大小 |
|---|---|
| CPU | Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz 6核心 12线锃 * 1 |
| RAM | 32G |
| 硬盘 | 300*1 SAS 15k |
| 列阵卡 | H310 Mini |
| 写入方式 | Write Through |
| 项目 | 版本号 |
|---|---|
| OS | Centos6.9 |
| Postgresql | 9.6.1 |
| pgpool | pgpool-II-3.6.4 |
| Gcc | 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) |
listen_addresses = '0.0.0.0' port = 9610 max_connections = 500 shared_buffers = 16384MB work_mem = 4MB maintenance_work_mem = 512MB autovacuum_work_mem = -1 checkpoint_timeout = 60min max_wal_size = 6GB min_wal_size = 2GB checkpoint_warning = 30s wal_level = replica max_wal_senders = 3 wal_keep_segments = 8000 hot_standby = on max_standby_archive_delay = 1800s max_standby_streaming_delay = 1800s log_destination = 'csvlog' logging_collector = on log_min_duration_statement = 1000 log_checkpoints = on autovacuum = on log_autovacuum_min_duration = 0 autovacuum_max_workers = 3 timezone = 'PRC'
host all all 127.0.0.1/32 md5 host all all 192.168.1.0/24 md5 host replication postgres 192.168.1.0/24 md5
standby_mode = 'on' primary_conninfo = 'host=192.168.1.146 port=9610 user=postgres password=pgsql' recovery_target_timeline = 'latest'
[root@pgpool-01 source]# wget http://www.pgpool.net/download.php?f=pgpool-II-3.6.4.tar.gz
[root@pgpool-01 source]# tar zxf pgpool-II-3.6.4.tar.gz [root@pgpool-01 source]# cd pgpool-II-3.6.4 [root@pgpool-01 pgpool-II-3.6.4]# ./configure --prefix=/usr/local/pgpool-II-3.6.4/ --with-pgsql=/usr/local/pgsql9.6.1 --with-openssl [root@pgpool-01 source]# gmake [root@pgpool-01 source]# gmake install
为pgpool 软连接一个标准运行目录
[root@pgpool-01 pgpool-II-3.6.4]# ln -s /usr/local/pgpool-II-3.6.4 /usr/local/pgpool
[root@pgpool-01 pgpool-II-3.6.4]# cd /usr/local/pgpool/etc [root@pgpool-01 etc]# cp pgpool.conf.sample-stream pgpool.conf [root@pgpool-01 etc]# vim /usr/local/pgpool/etc/pgpool.conf #监听参数配置 listen_addresses = '*' port = 9999 socket_dir = '/tmp' pcp_listen_addresses = '*' pcp_port = 9898 pcp_socket_dir = '/tmp' #节点参数配置 #节点一 backend_hostname0 = '192.168.1.146' backend_port0 = 9610 backend_weight0 = 0 backend_data_directory0 = '/home/postgres/data9.6.1' backend_flag0 = 'ALLOW_TO_FAILOVER' #节点二 backend_hostname1 = '192.168.1.12' backend_port1 = 9610 backend_weight1 = 0 backend_data_directory1 = '/home/postgres/data9.6.1' backend_flag1 = 'ALLOW_TO_FAILOVER' #认证方法配置 enable_pool_hba = on pool_passwd = 'pool_passwd' #连接池配置 num_init_children = 200 max_pool = 4 #日志配置 log_destination = 'syslog' log_connections = off log_hostname = off log_statement = off log_per_node_statement = off syslog_facility = 'LOCAL0' syslog_ident = 'pgpool' #pid文件及状态文件存放路径 pid_file_name = '/usr/local/pgpool/pgpool.pid logdir = '/usr/local/pgpool' #pgpool工作方式,负载+复制(流复制方式) load_balance_mode = on master_slave_mode = on master_slave_sub_mode = 'stream' #连接状态检查 sr_check_period = 10 sr_check_user = 'postgres' sr_check_password = 'pgsql' sr_check_database = 'postgres'
生成pcp工具连接用户名及密码
[root@pgpool-01 etc]# pg_md5 -u pgpool -p password: ba777e4c2f15c11ea8ac3be7e0440aa0
配置pcp.conf文件
[root@pgpool-01 etc]# cp pcp.conf.sample pcp.conf [root@pgpool-01 etc]# vim pcp.conf # USERID:MD5PASSWD pgpool:ba777e4c2f15c11ea8ac3be7e0440aa0
[root@pgpool-01 etc]# vim pool_hba.conf host all all 127.0.0.1/32 md5 host all all 192.168.1.0/24 md5
[root@pgpool-01 etc]# pg_md5 -m -u postgres pgsql [root@pgpool-01 etc]# cat pool_passwd postgres:md5859b0f43555758bfa7e9cc24a8a964c1 [root@pgpool-01 etc]#
在/etc/profile文件中增加下面内容
PATH=/usr/local/pgpool/bin:$PATH export PATH
环境变量生效
[root@pgpool-01 etc]# source /etc/profile [root@pgpool-01 etc]# which pgpool /usr/local/pgpool/bin/pgpool
[root@pgpool-01 etc]# vim /etc/rsyslog.conf local0.* /var/log/pgpool.log [root@pgpool-01 etc]# service rsyslog restart 关闭系统日志记录器: [确定] 启动系统日志记录器: [确定] [root@pgpool-01 etc]#
[postgres@gpool-01 etc]$ vim /home/postgres/.pgpass *.:9610:*:postgres:pgsql *.:9999:*:postgres:pgsql [postgres@ppool-01 etc]$ chmod 0600 /home/postgres/.pgpass
[root@pgpool-01 etc]# su postgres [postgres@pgpool-01 etc]$ pgpool
1)、发单进程的pgbench使用的CPU为100%时需要分成三个进程的pgbench同时跑
2)、跑pgbench需要在另外一台机器上执行,否则会占用比较多的pgpool或postgresql的系统资源
3)、pgbench的latency average计算是包括向测试终端输出信息事个过程,所以测试时需要把pgbench输出导向文件,才能获取比较准确的tps和qps,否则相差几十倍的性能值都有可能。
4)、跑pgbench前先用 ethtool em1检查网卡当前工作速率,有些网卡是10/100/1000MB自适用,以确认网卡带宽是否足够,pgbench测试过程中网络带宽经常也会成为瓶颈。
[postgres@pgbench-01 ~]$ vim /home/postgres/.pgpass *:9610:*:postgres:pgsql *:9999:*:postgres:pgsql [postgres@pgbench-01~]$ chmod 0600 /home/postgres/.pgpass
1)、生成测试数据
create table t (id serial not null unique ,remark text); insert into t (remark) select md5(random()::text) from generate_series(1,1000000); vacuum; analyze;
2)、编写测试脚本
[postgres@pgbench-01 shell]$ vim sele_bench.sql
\set id random(1, 1000000)
select * from t where id=:id;
执行的开销少于0.1ms
postgres=# explain (analyze,buffers) select * from t where id=1000000;
QUERY PLAN
-----------------------------------------------------------------------------
Index Scan using t_id_key on t (cost=0.42..8.44 rows=1 width=37)
(actual time=0.020..0.021 rows=1 loops=1)
Index Cond: (id = 1000000)
Buffers: shared hit=4
Planning time: 0.107 ms
Execution time: 0.055 ms
(5 rows)
3)、测试结果
#直接连接pg /usr/local/pgsql9.6.1/bin/pgbench -h 192.168.1.146 -U postgres -d postgres -p 9610 -M prepared -c 8 -T 60 -f /home/postgres/shell/sele_bench.sql > /home/postgres/146bench_8c_60s_1.txt 2 > &1 #连接pgpool /usr/local/pgsql9.6.1/bin/pgbench -h 192.168.1.21 -U postgres -d postgres -p 9999 -M prepared -c 8 -T 60 -f /home/postgres/shell/sele_bench.sql > /home/postgres/21bench_8c_60s_1.txt 2 > &1
| 项目 | Qps |
|---|---|
| 直连8个并发 | 31634 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz 6核心 | |
| 连接pgpool--两节点8个并发 | 6298 |
| 连接pgpool--两节点16个并发 | 9097 |
| 连接pgpool--三节点24个并发 | 10610 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz 8核心 | |
| 连接pgpool--两节点8个并发 | 7166 |
| 连接pgpool--两节点16个并发 | 11948 |
| 连接pgpool--三节点24个并发(pgpool与pg同一节点)1-1-1权重分发 | 18263 |
| 连接pgpool--三节点8个并发(pgpool与pg同一节点)1-1-2权重分发 | 10262 |
| 连接pgpool--三节点8个并发(pgpool与pg同一节点)0-0-1权重分发 | 13240 |

1)、生成测试数据
drop table t; create table t (id serial not null ,remark text); insert into t (remark) select md5(random()::text) from generate_series(1,10000); vacuum; analyze;
2)、编写测试脚本
[postgres@pgbench-01 shell]$ vim sele_bench.sql
\set id random(1, 10000)
select * from t where id=:id;
#执行的开销少于2ms
postgres=# explain (analyze,buffers) select * from t where id=10000;
QUERY PLAN
----------------------------------------------------------------------
Seq Scan on t (cost=0.00..209.00 rows=1 width=37)
(actual time=1.720..1.720 rows=1 loops=1)
Filter: (id = 10000)
Rows Removed by Filter: 9999
Buffers: shared hit=84
Planning time: 0.057 ms
Execution time: 1.743 ms
(6 rows)
3)测试结果
| 项目 | Qps |
|---|---|
| 直连8个并发 | 6721 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz 6核心 | |
| 连接pgpool--两节点8个并发 | 2568 |
| 连接pgpool--两节点16个并发 | 5540 |
| 连接pgpool--三节点24个并发 | 6241 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz 8核心 | |
| 连接pgpool--两节点8个并发 | 3025 |
| 连接pgpool--两节点16个并发 | 6421 |
| 连接pgpool--三节点24个并发 | 8078 |

1)、生成测试数据
drop table t; create table t (id serial not null ,remark text); insert into t (remark) select md5(random()::text) from generate_series(1,60000); vacuum; analyze;
2)、编写测试脚本
[postgres@pgbench-01 shell]$ vim sele_bench.sql
\set id random(1, 60000)
select * from t where id=:id;
#执行的开销10ms以上
postgres=# explain (analyze,buffers) select * from t where id=60000;
QUERY PLAN
----------------------------------------------------------------------------
Seq Scan on t (cost=0.00..1250.00 rows=1 width=37)
(actual time=10.371..10.372 rows=1 loops=1)
Filter: (id = 60000)
Rows Removed by Filter: 59999
Buffers: shared hit=500
Planning time: 0.076 ms
Execution time: 10.399 ms
(6 rows)
3)测试结果
| 项目 | Qps |
|---|---|
| 直连8个并发 | 1672 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz 6核心 | |
| 连接pgpool--两节点8个并发 | 1202 |
| 连接pgpool--两节点16个并发 | 2486 |
| 连接pgpool--三节点24个并发 | 3231 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz 8核心 | |
| 连接pgpool--两节点8个并发 | 1308 |
| 连接pgpool--两节点16个并发 | 2617 |
| 连接pgpool--三节点24个并发 | 3576 |

1)、生成测试数据
drop table t;
create table t (id serial not null unique ,remark text);
insert into t (remark) select repeat('hello pg,我是阿弟', 1000) from
generate_series(1,10000);
vacuum;
analyze;
每条数据大约12K
2)、编写测试脚本
[postgres@pgbench-01 shell]$ vim sele_bench.sql \set id random(1, 10000) select * from t where id=:id;
3)测试结果
| 项目 | Qps |
|---|---|
| 直连8个并发 | 5586 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz 8核心 | |
| 连接pgpool--两节点8个并发 | 3447 |
| 连接pgpool--两节点16个并发 | 4246 |
| 连接pgpool--三节点24个并发(pgpool与pg同一节点)1-1-1权重分发 | 5180 |
| 连接pgpool--三节点8个并发(pgpool与pg同一节点)1-1-2权重分发 | 3961 |
| 连接pgpool--三节点8个并发(pgpool与pg同一节点)0-0-1权重分发 | 5051 |

1)、生成测试数据
drop table t; create table t (id serial not null unique,remark text); vacuum; analyze;
2)、编写测试脚本
[postgres@pgbench-01 shell]$ vim insert_bench.sql insert into t(remark) values(md5(random()::text));
3)测试结果
| 项目 | Qps |
|---|---|
| 直连8个并发 | 13677 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz 6核心 | |
| 连接pgpool--两节点8个并发 | 5792 |
| 连接pgpool--三节点8个并发 | 5745 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz 8核心 | |
| 连接pgpool--两节点8个并发 | 6626 |

1)、生成测试数据
drop table t; create table t (id serial not null ,remark text); insert into t (remark) select md5(random()::text) from generate_series(1,10000); vacuum; analyze;
2)、编写测试脚本
[postgres@pgbench-01 shell]$ vim update_bench.sql
\set id random(1, 10000)
update t set remark=md5(random()::text) where id=:id
#执行开销
explain (analyze,buffers) update t set remark =md5(random()::text) where id=1;
QUERY PLAN
------------------------------------------------------------------------------
Update on t (cost=0.00..209.01 rows=1 width=42)
(actual time=1.885..1.885 rows=0 loops=1)
Buffers: shared hit=85
-> Seq Scan on t (cost=0.00..209.01 rows=1 width=42)
(actual time=1.856..1.857 rows=1 loops=1)
Filter: (id = 1)
Rows Removed by Filter: 9999
Buffers: shared hit=84
Planning time: 0.086 ms
Execution time: 1.924 ms
3)测试结果
| 项目 | Qps |
|---|---|
| 直连8个并发 | 5001 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz 6核心 | |
| 连接pgpool--两节点8个并发 | 3100 |
| 连接pgpool--三节点8个并发 | 3015 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz 8核心 | |
| 连接pgpool--两节点8个并发 | 3513 |

1)、生成测试数据
drop table t; create table t (id serial not null ,remark text); insert into t (remark) select md5(random()::text) from generate_series(1,60000); vacuum; analyze;
2)、编写测试脚本
[postgres@pgbench-01 shell]$ vim update_bench.sql
\set id random(1, 60000)
update t set remark=md5(random()::text) where id=:id
#执行开销
postgres=# explain (analyze,buffers) update t set remark =md5(random()::text)
where id=60000;
QUERY PLAN
-------------------------------------------------------------------------------
Update on t (cost=0.00..1250.01 rows=1 width=42)
(actual time=10.616..10.616 rows=0 loops=1)
Buffers: shared hit=506 read=1 dirtied=1
-> Seq Scan on t (cost=0.00..1250.01 rows=1 width=42)
(actual time=10.485..10.487 rows=1 loops=1)
Filter: (id = 60000)
Rows Removed by Filter: 59999
Buffers: shared hit=500
Planning time: 0.124 ms
Execution time: 10.656 ms
(8 rows)
3)测试结果
| 项目 | Qps |
|---|---|
| 直连8个并发 | 1470 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz 6核心 | |
| 连接pgpool--两节点8个并发 | 1294 |
| 连接pgpool--三节点8个并发 | 1308 |
| Pgpool服务器CPU--Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz 8核心 | |
| 连接pgpool--两节点8个并发 | 1370 |

发送select * from t where id=100这样的语句
#客户端-〉pgpool
17:38:25.026869 IP 192.168.1.11.36426 > 192.168.1.21.distinct: Flags [P.], seq 35:70,
ack 124, win 29, length 35
#Pgpool-〉pg
17:38:25.085689 IP 192.168.1.21.hexarc > 192.168.1.146.9610: Flags [P.], seq 1:36,
ack 1, win 31, length 35
#执行结果返回
#Pg->pgpool
17:38:25.086287 IP 192.168.1.146.9610 > 192.168.1.21.hexarc: Flags [P.], seq 1:124,
ack 36, win 39, length 123
17:38:25.086299 IP 192.168.1.21.hexarc > 192.168.1.146.9610: Flags [.],
ack 124, win 31, length 0
#Pgpool-〉客户端
17:38:25.027795 IP 192.168.1.21.distinct > 192.168.1.11.36426: Flags [P.], seq 124:177,
ack 70, win 29, length 53
17:38:25.027812 IP 192.168.1.11.36426 > 192.168.1.21.distinct: Flags [.],
ack 177, win 29, length 0
17:38:25.027819 IP 192.168.1.21.distinct > 192.168.1.11.36426: Flags [P.], seq 177:241,
ack 70, win 29, length 64
17:38:25.027826 IP 192.168.1.11.36426 > 192.168.1.21.distinct: Flags [.],
ack 241, win 29, length 0
17:38:25.027832 IP 192.168.1.21.distinct > 192.168.1.11.36426: Flags [P.], seq 241:247,
ack 70, win 29, length 6
17:38:25.027839 IP 192.168.1.11.36426 > 192.168.1.21.distinct: Flags [.],
ack 247, win 29, length 0
当客户端向pgpool发出select * from t where id=100;这样的查询时,pgool会把语句转发给pg--这个通信没问题。但当数据返回时pgpool的处理就有问题了,pg直接一次返回给pgpool,但pgpool竟然分三次返回。
发送这样的insert into t(remark) values(md5(random()::text));语句
#客户端-〉pgpool 17:11:40.851896 IP 192.168.1.11.42150 > 192.168.1.21.distinct: Flags [P.], seq 196:252, ack 582, win 29, length 56 #Pgpool-〉pg 17:11:40.898114 IP 192.168.1.21.dtserver-port > 192.168.1.146.9610: Flags [P.], seq 1185:1241, ack 1023, win 31, length 56 #执行结果返回 #Pg->pgpool 17:11:40.906169 IP 192.168.1.146.9610 > 192.168.1.21.dtserver-port: Flags [P.], seq 1023:1045, ack 1241, win 39, length 22 17:11:40.906183 IP 192.168.1.21.dtserver-port > 192.168.1.146.9610: Flags [.], ack 1045, win 31, length 0 #Pgpool-〉客户端 17:11:40.860338 IP 192.168.1.21.distinct > 192.168.1.11.42150: Flags [P.], seq 582:598, ack 252, win 29, length 16 17:11:40.860353 IP 192.168.1.11.42150 > 192.168.1.21.distinct: Flags [.], ack 598, win 29, length 0 17:11:40.860360 IP 192.168.1.21.distinct > 192.168.1.11.42150: Flags [P.], seq 598:604, ack 252, win 29, length 6 17:11:40.860364 IP 192.168.1.11.42150 > 192.168.1.21.distinct: Flags [.], ack 604, win 29, length 0
当客户端向pgpool发出insert into t(remark) values(md5(random()::text));这样的插入语句时,pgool会把语句转发给pg--这个通信没问题。但当返回执行结果通知时就有问题了,pg直接一次返回给pgpool,但pgpool这次分二次返回,update、delete的通信也跟insert一致。
1)、pgpool返回结果时会拆包,这个跟pgboucner或者haproxy不拆包有区别。
2)、pgpool及时发送零碎小数据包,减少数据存入缓冲区,通常情况下系统性能会更高,但如果高并发时,由于每个包都带有包头和交互次数增加,反而就会占用更大的网络io。
3)、就测试来看,pgpool比较适合于对于查询开销比较大(1ms以上),或者查询返回的流量比较大的应用。
http://www.pgpool.net
http://www.pgpool.net/docs/latest/tutorial-zh_cn.html
http://francs3.blog.163.com/blog/static/4057672720149285445881/
http://www.postgres.cn/docs/9.6/pgbench.html
