zoukankan      html  css  js  c++  java
  • pgbouncer连接池

    背景

    在做一站式项目的过程中发现当大量的服务连接到同一个库,以及大量的开发人员连接到同一个库的时候,数据库的2000连接不够。当然和使用c3p0连接池有关系,以前默认都是将最大最小连接数设置为一样,但现在都是用druid连接池,所以最大和最小连接数不必设置为一样。这样可以减少连接数,当然这只是一方面,今天我们要说的是当有大量连接的时候pgbouncer连接池的使用

    如果没有数据库连接池

    数据库在没有任何连接池的情况下,应用程序必须直接访问数据库来建立连接。打开的一个连接的消耗,关闭一个连接的消耗,而这样的消耗,伴随着你打开的连接越多,则消耗的就越多。还有短连接,可能同时并发的连接多,但占用这个连接的时间很短。这就会引起另一个问题,你设置的连接数和突入起来的连接数不匹配的情况,最后就会造成拒绝连接的问题。

    所以这就对数据库的连接提出一个问题,复用,连接的复用对数据库非常重要,这可以降低某些快速连接,快速断开的连接的数据库访问对数据库性能的消耗和产生的一些不必要的麻烦。

    版本

    PgBouncer 1.11.x已经可以支持PostgreSQL 12

    PgBouncer 1.14.0也已经发布与PostgreSQL 13新功能匹配

    pgbouncer的作用

    既然应用已经使用了durid连接池了,那么pgbouncer还有什么用呢?

    虽然我们每个服务都使用了连接池,但是各个服务之间是相互独立的,当有许多的服务去连一个数据库的时候,对数据库来说这么多连接还是不受保护的。(如果数据库仅有少数的应用连接,那么可以只使用程序自带的连接池就够了,但如果有大量的服务在连接数据库,数据库其实还是没有收到连接池的保护

    另外,PG是多进程结构,每个进程大概耗费10MB左右内存,所以连接越多,耗费的内存也就越多。

    使用软件架构池对数据库进行连接

    使用durid连接池如下面所示,当有大量的应用连接数据库的时候其实对数据库来说这些连接还是没有受到控制

    1593310945(1).jpg

    使用pgbouncer连接池的方式对数据库进行连接

    pgbouncer是在数据库端加了一个池子,也就是所有的连接经过数据库都需要进入这个池子

    1593311236(1).jpg

    采用pgbouncer来管理连接池的话,相当于在众多的软件druid连接池下面加了一个大的池子,来管理连接。这样来保证数据库的稳性。

    当然,pg的连接池不仅仅pgbouncer、还有pgpoolpgbouncer功能更加精简,配置简单。

    安装配置:

    安装参考安装文档

    数据库里面对应的数据库信息需要在pgbouncer.ini配置里面配置,listen_port是连接池对外的端口,应用配置时需要配置listen_port,如果直接配置数据库的端口,那么就没有通过连接池

    vi pgbouncer.ini
    
    [databases]
    pgbenchdb =  host=localhost port=6543 user=sa dbname=pgbenchdb  password=xxxx connect_query='SELECT 1' pool_size=100
    
    [pgbouncer]       
    logfile = /etc/pgbouncer/pgbouncer.log
    pidfile = /etc/pgbouncer/pgbouncer.pid
    auth_type = hba
    auth_file = /etc/pgbouncer/userlist.txt
    auth_hba_file =/etc/pgbouncer/pg_hba.conf
    admin_users = sa
    stats_users = sa
    pool_mode = transaction
    max_client_conn = 1000
    default_pool_size = 228
    ;min_pool_size = 0
    reserve_pool_size = 10
    listen_addr = 0.0.0.0    
    listen_port = 5432  
    
    --登录到pgbouncer,可以看到对应的版本为1.12.0
    [thunisoft@sqlfx ~]$ psql -Usa -d pgbouncer -p 5432
    psql (11.1, server 1.12.0/bouncer)
    Type "help" for help.
    
    --show help
    pgbouncer=# show help;
    NOTICE:  Console usage
    DETAIL:  
    	SHOW HELP|CONFIG|DATABASES|POOLS|CLIENTS|SERVERS|USERS|VERSION
    	SHOW FDS|SOCKETS|ACTIVE_SOCKETS|LISTS|MEM
    	SHOW DNS_HOSTS|DNS_ZONES
    	SHOW STATS|STATS_TOTALS|STATS_AVERAGES|TOTALS
    	SET key = arg
    	RELOAD
    	PAUSE [<db>]
    	RESUME [<db>]
    	DISABLE <db>
    	ENABLE <db>
    	RECONNECT [<db>]
    	KILL <db>
    	SUSPEND
    	SHUTDOWN
    
    SHOW
    
    pgbouncer=# show databas;
    ERROR:  invalid command 'show databas;', use SHOW HELP;
    pgbouncer=# show databases;
       name    |     host      | port | database  | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections | paused | disabled 
    -----------+---------------+------+-----------+------------+-----------+--------------+-----------+-----------------+---------------------+--------+----------
     pgbenchdb | xxxxxx | 6543 | pgbenchdb | sa         |       100 |           10 |           |               0 |                   0 |      0 |        0
     pgbouncer |               | 5432 | pgbouncer | pgbouncer  |         2 |            0 | statement |               0 |                   0 |      0 |        0
    (2 rows)
    
    

    性能测试

    短链接

    使用连接池:5985tps

    
    [thunisoft@sqlfx ~]$ pgbench -M extended -v -r -P 1 -S -C -c 100 -j 100 -T 60 -p 5432 -Usa pgbenchdb
    starting vacuum...end.
    starting vacuum pgbench_accounts...end.
    progress: 1.0 s, 6175.1 tps, lat 6.959 ms stddev 2.293
    、、、
    progress: 60.0 s, 6607.6 tps, lat 6.676 ms stddev 1.708
    transaction type: <builtin: select only>
    scaling factor: 100
    query mode: extended
    number of clients: 100
    number of threads: 100
    duration: 60 s
    number of transactions actually processed: 359203
    latency average = 7.426 ms
    latency stddev = 5.283 ms
    tps = 5985.437222 (including connections establishing)
    tps = 13415.041978 (excluding connections establishing)
    statement latencies in milliseconds:
             0.003  set aid random(1, 100000 * :scale)
             7.425  SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
    

    不使用连接池:752tps

    
    [thunisoft@sqlfx ~]$ pgbench -M extended -v -r -P 1 -S -C -c 100 -j 100 -T 60 -p 6543 -Usa pgbenchdb
    starting vacuum...end.
    starting vacuum pgbench_accounts...end.
    progress: 1.1 s, 656.3 tps, lat 8.981 ms stddev 7.668
    、、、
    progress: 60.0 s, 713.3 tps, lat 8.220 ms stddev 5.773
    transaction type: <builtin: select only>
    scaling factor: 100
    query mode: extended
    number of clients: 100
    number of threads: 100
    duration: 60 s
    number of transactions actually processed: 45235
    latency average = 7.972 ms
    latency stddev = 6.182 ms
    tps = 752.359996 (including connections establishing)
    tps = 12079.524918 (excluding connections establishing)
    statement latencies in milliseconds:
             0.005  set aid random(1, 100000 * :scale)
             7.966  SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
    

    短链接情况下使用连接池和不使用连接池,差别非常大。原因是建立大量的连接需要耗费大量的时间

    高并发

    使用连接池:565tps

    --使用连接池,数据库连接数为100
    --这个地方的100是和pgbouncer.ini里面的pool_size一致
    pgbenchdb=# select count(*) from pg_stat_activity where state !='idle' and application_name = 'pgbench';
     count 
    -------
       100
    (1 row)
    
    
    --初始化数据
     pgbench -i -s 20 pgbenchdb
    dropping old tables...
    creating tables...
    generating data...
    、、、
    2000000 of 2000000 tuples (100%) done (elapsed 13.11 s, remaining 0.00 s)
    vacuuming...
    creating primary keys...
    done.
    
    --测试
    [thunisoft@sqlfx ~]$ pgbench -M extended  -r -P 1   -c 1000 -j 1000 -T 60 -p 5432 -Usa pgbenchdb
    starting vacuum...end.
    、、、
    transaction type: <builtin: TPC-B (sort of)>
    scaling factor: 20
    query mode: extended
    number of clients: 1000
    number of threads: 1000
    duration: 60 s
    number of transactions actually processed: 34907
    latency average = 1734.514 ms
    latency stddev = 406.066 ms
    tps = 565.477219 (including connections establishing)
    tps = 565.611196 (excluding connections establishing)
    statement latencies in milliseconds:
             0.006  set aid random(1, 100000 * :scale)
             0.001  set bid random(1, 1 * :scale)
             0.001  set tid random(1, 10 * :scale)
             0.001  set delta random(-5000, 5000)
          1471.673  BEGIN;
             2.593  UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
             1.302  SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
           105.564  UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
           122.611  UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
             2.311  INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
            29.079  END;
    
    
    

    不使用连接池:406tps

    --不使用用连接池,数据库连接数为1000
    pgbenchdb=# select count(*) from pg_stat_activity where state !='idle' and application_name = 'pgbench';
     count 
    -------
      1000
    (1 row)
    
    --初始化数据
    [thunisoft@sqlfx ~]$  pgbench -i -s 20 pgbenchdb
    dropping old tables...
    creating tables...
    generating data...
    、、、
    2000000 of 2000000 tuples (100%) done (elapsed 13.46 s, remaining 0.00 s)
    vacuuming...
    creating primary keys...
    done.
    
    --测试
    [thunisoft@sqlfx ~]$  pgbench -M extended  -r -P 1   -c 1000 -j 1000 -T 60 -p 6543 -Usa pgbenchdb
    starting vacuum...end.
    progress: 2.5 s, 443.8 tps, lat 362.341 ms stddev 407.794
    、、、
    transaction type: <builtin: TPC-B (sort of)>
    scaling factor: 20
    query mode: extended
    number of clients: 1000
    number of threads: 1000
    duration: 60 s
    number of transactions actually processed: 24946
    latency average = 2375.957 ms
    latency stddev = 3390.823 ms
    tps = 406.784046 (including connections establishing)
    tps = 409.912851 (excluding connections establishing)
    statement latencies in milliseconds:
             0.016  set aid random(1, 100000 * :scale)
             0.001  set bid random(1, 1 * :scale)
             0.001  set tid random(1, 10 * :scale)
             0.003  set delta random(-5000, 5000)
             4.545  BEGIN;
             4.436  UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
             2.508  SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
          1950.669  UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
           369.524  UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
             3.705  INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
            40.694  END;
    
    

    可以看到使用pgbouncer连接池的tps要比不使用pgbouncer要稍高。使用了pgbouncer后,连接到数据库的连接数为100,而不使用pgbouncer的连接数为1000

    总结

    1、在使用durid连接池的时候,最大最小连接池不必设置成一样,这样可以减小连接池开销

    2、durid连接池是应用端的池子,当连接数据库的应用变多了以后,数据库任然不受保护,并且连接越多耗费的内存越多

    3、pgbouncer相当于在数据库端加了一个池子,所有的连接过来都需要经过这个池子,负责连接的打开和关闭

    4、当有大量的服务连接到数据库时,虽然有durid应用端连接池,但是对于数据库来说,仍然像没有使用连接池一样,pgbouncer是数据库端的连接池,用来控制应用端的连接

    参考资料:

    官网

    pgbouncer使用

    Scaling Connections in Postgres

    PostgreSQL 与 Pgbouncer We are brotherhood

  • 相关阅读:
    fabric.js 学习
    前端基础回顾
    ubuntu16 mysql 远程连接
    Django rest_framework API 随笔
    django 学习笔记
    vue 返回上一页在原来的位置
    Django mysql 改用pymysql 驱动
    Material-UI
    设置placeholder的样式
    Cookie、session和localStorage、以及sessionStorage之间的区别
  • 原文地址:https://www.cnblogs.com/zhangfx01/p/14872431.html
Copyright © 2011-2022 走看看