27 Postgre sql 建模,压力测试|学习笔记

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: 快速学习27 Postgre sql 建模,压力测试

开发者学堂课程【PostgreSQL 快速入门27 Postgre sql 建模,压力测试】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/16/detail/86


27 Postgre sql 建模,压力测试

 

内容介绍:

一、权限设置

二、高可用和负载均衡

三、心跳函数的设置

四、建模

五、负载均衡

六、数据库规划

七、压力建模测试

八、pg banch 的使用

 

一、权限设置

如果没有建 function 权限,那么没有办法攻击你,如果有权限,在 function 里面,如果里面的 function 权限没有select 权限大的话,这个其实跟 select 没有关系,这个就是纯粹的攻击执行计划的机制,就是单纯的计算成本执行,先判断成本高的执行,再判断成本低的执行,来利用这么一个机制。

现在新建一个视图,然后再去执行这一条语句:

postgresell

postgres-#create vieu _userinfo_1with(security_barrier> as

select * from userinfo uhere id=2;CREATE UIEM

postgresellselect =fron v_userinfo1 where attack(id.groupid.usernane.age,addr.email.phone);ERROR:

relationt"guserinfo1" does not exist

LINE 1: select s fron u_userinfo1 where

attack(id.groupid.usernane,a

postgres-#select * fron v_userinfo1 uhere attack(id.yroupid.usernane,age.addr.enail,phone);^t

ERROR:re lat ion"v_userinfo1" does not exist

LINE 1: select wfron v_userinfo1 where

attack(id.groupid,usernane,a

pestyres-#

编泽:postgres-#

postgres-#

postgres-# ;g.groupi.usernane.age.addr.enail.phone)进程

ERROR:syntax error at or near ""

LINE 1:

ESQpostgres-# select w fron v_userinfo_1yhere attack(id.groupid.usernane,age,addr.enail.phone)

postgres-# ;

NOTICE:2.1.test.1888.火星.digoalP126.com,11999999999

-[ RECORD 1 ]

金素 id 2

groupid 1

usernane test

成本公age 1800

addr 火星

enail digoal@126.con

phone 11999999999

地高

把成本改成0.000000001,再去执行,去设置光圈作用。Explain 里面的东西改变了。此时只进行了一个子查询:

image.png

pastyres=# selec v_userinfo_1 where

attack(id.groupid,usrnane,age,addr.enail.phone

postyres-# ;

error at or near "selec"

ERROR: syntaxfron

LINE 1: selec fron v_userinfo_1 where

attackKid.groupid,usernane.ag...

postgres-# explain select ×fron v_userinfo_1 where attack(id.groupid.usernane.age.addr.enail,phone);

-[ RECORD 1 ]

QUERY PLAN I Subquery Scan on v_userinfo_1 (cost-0.08..34.10 rous=3 width-140)

-[ RECORD 2 】

QUERY PLAN I Filter:attackKu_userinfo_1.id, v_userinfo_1.groupid,

v_userinfo_1.usernane, v_userinfo_1.a

v_userinfo_1.addrserinfo_1.enail. v_userinfo_1.phone)

-[ RECORD 3 J

QUERY PLAN I Seq Scan on userinfo(cost-0.00..34.00 rovs-10

width-140)

-[ RECORD 4 ]

QUERY PLAN : Filter: <id = 2)

postgres=# w

Expanded display is off.

postyres-# explain select × fron v_userinfo_1 whereattack(id.groupid.usernane,age.addr.enail,phone,

QUERY PLAN

Subquery Scanon v_userinfo_1 (cost-0.08..34.18 rous=3

vidth=148)

Filter: attack(u userinfo 1.id. iserinfo oupid. userinfo infd

1 ddr userinfo_1.em

i1 userinfo_1.phone

SecScanon userinfo <cost-0.08..34.08 rovs-10 width-148)

Filter: (id = 2)

此时没有办法去攻击它

接下来进行查看 sql 注入,sql 注入对于任何数据库,都没有好的办法去规避,除非是使用强类型的判断,或者使用绑定变量,那么如果

是有漏洞的情况下,例如 simple 协议,是允许一次提交多条 simple。

程序端控制

1.不要使用 simple 协议,因为 simple 协议允许一次提交多 SQL.

例如:

statement = "SELECT*FROM users WHERE name ="+ userName +"";"

这个 SQL,可以在 userName 这里注入攻击.

a';DROP TABLE users; SELECT *FROM userinfo WHERE't='t

那么整条 sql 就变成:

SELECT * FROM users WHERE name = 'a'; DROP TABLE users; SELECT*FROM userinfo WHERE T='T;使用绑定变量避免以上问题

2.程序端控制,例如检测变量类型,以及过滤,以下攻击只要检查变量类型,拒绝请求就不会有问题.statement :="SELECT* FROM userinfo WHERE id ="+ a_variable +";"

如果a_variable 不做任何判断,传入1;DROP TABLE users

那么 SQL 变成:

SELECT * FROM userinfo WHERE id=1;DROP TABLE users;

对于这种协议:statement = "SELECT*FROM users WHERE name ="+ userName +"";"进行分装。如果没有进行分装实验,这里是一个text类型,所以不管判不判断都可以被攻击。如果是用户传上来的是a';DROP TABLE users; SELECT *FROM userinfo WHERE't='t,没有进行替换,那么sql语句会变换成SELECT * FROM users WHERE name = 'a'; DROP TABLE users; SELECT*FROM userinfo WHERE T='T;这样的话就很危险了,所以在程序当中的话,第一是不要用 simple,不要用绑定变量,绑定变量就是一个字符串,不会拆分成多条语句来执行。这是一个查程序段的控制,如果用户传上来的不是一个字符串的话,会抛出异常,也可以规避掉被攻击可能。

接下来进行查看被攻击的内容是怎样的。一种就是在变量里面,还有就是执行 select version 就可以得到你的版本,通过已经公布的漏洞来攻击你。

2.字符逃逸

php 参考:

http://pho.netmanual/en/function.pg-escapestring.php

使用pg_escape_string函数将字符串中的特殊字符转义,因此不会带来前面的问题.例如 将1个单引号转成2个单引号.

http://blog.163.com/digoal@126/blog/static/1638770201342185210972/

3.强制类型

对于变量本应该是t类型的,就不分注输入字符类型了

4.数据库权限控制

把业务程序性用户的权限收到最小,满足业务需求即可.

[其他]

1. 平时做好归档的备份以及基础备份很重要,即使真的被攻击了,也可以恢复到被攻击前的时间点,将数据挽回。

强制的类型转换,不是特定的类型,不允许执行。对于权限控制的话,可以做,但是对于权限注入的话,效果不明显。比如如果控制不交付表,但是可以干点别的事情。

下面这一块就是 sql 注入的东西,就是 sql 注入的一些常用的手段:

给数据库打补丁,就是可能会定期的释放出小版本,对于小版本的更新,就不算补丁。打补丁就需要在 clint source里面,会放一些补丁在里面:

image.png

上图中是 pending patches 的话,就是说明是一个未提交的状态。这个补丁就不要去打,尤其是线上。要打就去打committed 状态,这种补丁已经放在版本里面去了。在这个版本里面有很多的分支,比如现在用的版本9.3.2的分支。

image.png

所有分支,从9.3.2以来,已经有很多代码提交了,很多补丁就是功能正常的补丁,如果要打这里面的补丁,只需要安装好相关程序,进行编译安装即可。安装补丁再启动数据库即可,对于大版本下的分支其实都是通用的。

如果是从 patch name 里面取来的补丁,有可能不是你主线版本里面的。对于这种补丁,在一个开发环境里面,打这种补丁,点进补丁里面,有一个 patch,patch 里面基本都是一些文件。直接把.dff 里面的源码执行一条 patch 命令就好了。

如果是把 patch 文件是放在当前文件,就执行下一条命令。Patch 完之后,就会把当前的代码更新到当前源代码里面去。完成之后,就会把源码文件 make 一下,这样出来就是一个新的版本。

打补丁一种是下载在 patch 里面打了标签的版本,如下图:

image.png

里面都是已经分装好了的版本,直接点击标签,就可以看到当前代码的状态。后面会做一些更新,如果要下载9.3.3的版本,就会打另一个标签,下次要生成新的版本的时候,就会生成如下:

image.png

对于整个9.3的版本,它的主线的话,就是看下图

image.png

点进去之后,就是整个9.3的分支里面,如果现在安装的是9.3的版本,如果想试一下最新的代码的话,就需要到这里来下载。就是一个是从这里下载,帮你打包好的源代码。

另外一个从网站上去下载对应的补丁版本,还有一个就是去 commit first,去下载对应补丁,达到源代码文件,这里的文件都是开发版。对应的就是 mast,即开发版。这个 mast 会一直作为开发版的主线。如果是提交版的补丁的话,在主线里面也已经提交掉了。比如看一个10月18号的补丁,其实10月16号已经提交掉了。

 image.png

对应到 commited 状态:

image.png

不管是哪个网站下载下来的,最终体现都是在上图中,源代码只有一个,不会有很多分支。比如说下图:

image.png

Users/andrefreund,他在开发过程中,自己的特性,开发得差不多之后,会把他放到 commit first 里面去,commit first 会有人去讨论这个问题,OK 了之后就进行 commit,commit 之后会更改部分内容合并到 first aggre 的主线代码里面。就只需要关心一个主线版本即可。

插件可能可以合并到主元件代码里面,如果没有插入进来,就是第三方的一个文件,就是第三方在维护的东西,而不是整个 post ageree 的东西。如果没有合并进来,并不代表不承认,要进行合并的话,也要进行判断。

可能这个东西已经很稳定了,但是要考虑必要性。但我们自己使用的话,就需要考虑是否稳定,因为一般来说,第三方的插件他更新的时候会告诉你支持到哪个大版本。

 

二、高可用和负载均衡

接下来讲解高可用和负载均衡:

了解高可用架构,PostgreSQL 高可用的实现方法,挑选几种演示讲解

了解负载均衡的应用场景,PG 的实现方法,挑选几种演示讲解。

这里举的例子都是比较常见的一些例子,比如说高可用的可选方法很多,最传统的是利用共享存储来做高可用。因为一般来说,高端存稳定性高,可靠性高,主机故障率也比较高。传统做法是利用共享存储。

image.png

1.共享存储

.共享存储(数据文件以及表空间的文件必须共享存储).

同一时间点只能有1个主机启动数据库,其他主机可以挂载文件系统(仅限于集群文件系统).浮动 IP 跟随起数据库的主机一起.

通过检测心跳判断异常,fence 掉老的活动主机,在候选机器上启动数据库.

主要的弊端:

受制于存储可用性

利用共享存储来做,他的坏处共享存储会崩溃,崩溃了的话就不是高可用了,存储的那个故障率其实也没有想象的那么低,特别是那些比较极端的。

那用共享传统来说的话,基本上就是就这么一套,一个是虚拟 IP、浮动 IP,在同一个时间点的话,只有一台主机会去连接这个数据库,另外一台主机不能取这个数据库,就是说这里是一个集群文件系统,同一个时间点你可以被多台主机挂载,但是其他的只能有一个节点,如果这个节点发生异常的时候,弊端就是受制于存储的可能性。

2.块设备复制

一种开源解决方案是这种快速的复制,比如这里举了一个例子,通过网络把一整个的设备做一个复制,复制到另外一台主机,相当于文件系统,它不是直接去使用你那个快设备,它使用的是 DRBD,给你的一个设备相当于是系统之间加了一层,加了这一层之后,他就可以做很多的东西,就是说在往这个文件系统里写东西的时候,其实他对于你这种写的话,直接复制到另外一个点,另外一个节点有一个一模一样的拷贝,所以说当这台主机挂掉之后的话,在那边的话是可以把它链接起来,然后里面的话可能还会涉及到一些那个心跳检测啊,还有去连环 IP

image.png

 

三、心跳函数的设置

第三种解决方案,那就是说利用建立留复制节点来做这种安全的切换那比如说图其实跟共享诊所那个图是差不多的,都会有一个虚拟IP,只是说下面会有两份拷贝,中间做了一个仲裁,这个仲裁节点的话是用于判断是不是网络上出现的一些问题我们使用了激素节点,当超过一半的节点认为主节点已经挂掉之后,才会去把这个背景点切换成主结点,这样可以防止一个老裂的现象那么使用这种方法做的话,需要考虑最主要来考虑一个问题?

就是是用同步还是用异步,如是用异步去做这种安全的话,有可能会丢掉一部分数据,如果用同步来做呢就会影响一定的性能

image.png

对于这种要求非常高的系统的话,建议是用同步去做,对要求那个不是很高,可以丢一些数据的话,可以考虑用异步,但就是对于要求可靠性要求那么高,但是对性能要求很高,可以考虑用异步然后另外一个考虑的问题就是说不是所有的操作都会写 x-log,可能某一些操作可以不写 x-log 了,比如说 unlock ,是不检查的

HASH 索引,他也是不写 x-log了,那么也就是说在切换完之后,HASH 索引是一定要重建的,然后这个数据切过去之后就没有了,这个也是在在设计的时候要考虑的问题

如果使用安全,使用流复制来做的话,它的一个切换流程是什么?首先要判断主库是不是健康,再起那个3万节点的时候,如果不健康,就不启动这个心跳检测,因为主库不健康,就没必要去启动。然后判断本机是不是实在的 stand by角色,如果不是实在的外角是可以退出,然后是连接到主库执行更新,然后等待几秒钟,如果是等待几秒钟之后,发现这笔更新还没有复制到本地的这个时代的节点的话,那说明中间的复制有问题,那同样也是不启动整个的循环,这个循环就是整个的检测心跳的一个循环,包括这个 stand by 在这个心跳里面去处理,首先是去更新一个检测的时间点。就说在主库里面会放一个表,那个表的话里面会存储更新的一个成员,就是会检测心跳的时候,会不停的去更新那个表。

然后看更新是不是成功,然后再检测各个表空间的读写是不是正常,然后心跳检测函数是超时或者异常的话,这个时候就判断一下仲裁节点是不是正常,然后再通过动态节点去连到主库去执行这个心跳函数,心跳函数里面是做了一些update 的操作。

还有去判断表空间是不是正常的一些操作,这个都是通过写在数据库里面的函数去完成。那如果这些都不正常的话,那这个时候就判断一下延迟,如果延迟的允许范围之内的,那就把这个激活。

如果上面的判断超过十次都认为那个主节点不正常的话,十次之后就发生那个图库,并且激活备库,然后把VIP切过来,这个脚本如下图,放在这个地方,脚本的话内容就是前面描述的,比如说这里面有配置这个是fans,就是说整个里面要用到一个设备的话,是指把主库那台服务器关掉来确保不会出现某些用程序,可能还连着那主库上做一些操作,我把它干掉之后的话,然后再把这边连接起来,就表示都不会有其他应用程序连到那个主库,这个时候只有一个角色,就是激活的这个角度来确保不会出现老裂的现象。

心跳+切换的流程

判断主库是否健康->不健康则退出

判断本机是否为 STANDBY 角色>不是 STANDBY 角色则退出

连接到主库执行一次更新,5秒后到本地 STANBY 节点检查这次更新是否已经生效,用于判断 standby 是否正常.>不正常则退出循环

执行心跳检测函数

(更新检测时间点,检查各个表空间读写是否正常)

心跳检测函数超时或者异常则判断仲裁节点是否正常,仲裁节点不正常则跳出循环

仲裁节点正常的情况下从仲裁节点连到主库执行心跳函数,正常则跳出循环

如果返回结果也不正常的话,判断STANDBY延迟是否在允许范围内.

开始计数

计数超过10则发生切换(fence主库,激活备库,切换VIP)

详见

http://raw.github.com/digoal/sky_postgresql_cluster/master/sky_pg_clusterd.sh

脚本如下:

image.png

接下来进行查看心跳检测函数:

心跳检查函数

CREATE OR REPLACE FUNCTION

sky_pg_cluster.cluster_keepalive_testo RETURNS void

LANGUAGE plpgsql

STRICT

AS Sfunction$

declare

v_spcname text;

v_spcoid oid;

v_nspname name := sky_pg_cluster';

begin

if(pg_is_in_recovery)) then

raise notice 'this is standby node.';

return;

end if;

update cluster_status set last_alive=now0;

END LOOP;

select spcname into v_spcname from pg_tablespace where

oid=(select dattablespace from pg_database where

datname=current_databaseO);

perform 1 from pg_class where

reltablespace=0

and relname='t_'lv_spcname

and relkind=?'

and relnamespace=(select oid from pg_namespace where

nspname=y_nspname)

limit 1;

if not found then

execute 'create table "llv_nspnamel['.t_'llv_spcnamell"

(crt_time timestamp) tablespace 'llv_spename;execute 'insert

into '"lv_nspnamel['.t_'llv_spcnamell' values ("/nowO");

else

execute'update "llv_nspnamel['.t_llv_spenamel" set

crt_time=lI""llnowOll";

end if;

perform pg_stat_filepg_relation_filepath(v_nspnamell'.t_'llv_spcname));

end;

SfunctionS

一个是判断你是不是当前是不是 stand by,如果是 stand by,那就告诉你当前是一个节点,直接退出,然后是去更新这个极限状态表,把这个最后一次心跳时间更新一下,更新成那个当前时间,然后去做了一个 for 循环,这个循环的话就是说去扫描这个表,然后去过滤掉这个全局表空间,其他的中间我就把它取出来,取出来之后会在这个空间里面去创建一个这个表空间下面对应的一个表就是把这个表放在这个表空间里面,之后就更新这个量,如果这个表存在,之后去查看这个文件的时候就会去对这个两空间会有一个 stand by。

以这种来判断这个表空间是不是正常,因为可能有一些时候你的数据库挂了,但你的数据库可能还可以继续运行下去,这个是可能的,并且他也是允许,只要你还有多大那个表,他都是逾期的,当你读到那个表格那里面表达的时候,就只是说你那个绘画,之后还是可以继续的运行下去所以这里做一个判断,当你的数据库已经不行,或者是你里面某一些方面已经有问题的时候,我就把它切过来就告诉你一个错误

四、建模

这里会用到三个设备,两台主机,一台是仲裁机,然后这两台的话就是一主一备,那个 fans 设备已经创立好了,但是的话其实就是一个那个就是可以 ipmi 允许去发那种重启或者关机命令

首先把操作系统的 spid 的操作命令关闭,因为如果这个命令在的话,关机的时候是软关机,相当于是连上这台主机关机,就是 ipmi 这台设备过去,那么首先要把这个spid关掉,这样的话我们就再做关机的时候就很快的就强制关掉如果你的系统死机的话,也是可以很快地把主机关掉。

然后这边的话配置不用管,是要安装数据库的比如说一些内核的配置都不用管,我们做这个的话都没关系,然后这个时间要更新一下,时间必须要跟时间服务器要同步的,确保你的两台主备的时间要是相差不能这些配置完之后的话,你要配置一个虚拟IP。这个虚拟IP的话,启动服务器的时候不要主动启动ip。配完之后,把网络关掉,不让自动启动网络,再进行配置一下,接下来配置防火墙,允许仲裁节点和主备节点之间的访问,然后接下来就是配置启数据库的用户允许他去执行启网卡的命令,让普通用户启网卡。在没有终端的情况下也要能够启动,然后安装 pose agree。

Next conesthe nain part: which users can run what softuare on

which machines <the sudoers file can be shared betveen nultiple

systens》.

Syntax:

user MACHINE-COMMANDS

The COMHANDSsection nay have other options added to it.

## 自1low rootto run any connands anyuhere

root ALL=(ALL) LL

## Allovs nenbers of the 'sys’ group to run netuorking,

softuare.

## seruice nanagenent apps and nore.

# xsys ALL - NETMORKING, SOFIMARE, SERUICES,

STORAGE.DELEGATING, PROCESSES.LOCATE,DRIUERS

## Allovspeople in group uheel to run all connands

# zwheel ALL-(ALL) ALL

## Sane thing vithout a passvord

# xwheel 自LL=(ALL) NOPASSWD:ALL

## Allovs nenbers ofthe users group to nount and unnount the

## cdron as root

# xusers ALL=/sbin/nount /mnt/cdrom. /sbin/unount /nnt/cdron

## Allousnenbers of the users group to shutdoun thissysten

# xusers localhost=/sbin/shutdoun -h now

postgres ALL-(ALL) NOPASSWD: /sbin/ifup

"/etc/sudoers.tnp”181L, 3423C written

[rootPdb-172-16-3-39

netvork-scripts]# su - postgres

postgresedb-172-16-3-39-> psql-U

psql (PostgreSQL) 9.1.3

contains support for contand-line editing

在9.3里面,可以自动关机,否则还要将现有文件拷过来。这里就安装下版本9.3.2。还要用到端口跳转,放在仲裁节点上面。下载完之后,检查一下版本,修改一下端口。

安装好之后还要初始化数据库。端口使用的是5432也要进行修改。

# Get the aliases and functions

if[ -f "/.bashrc ]; then

/.bashre

fi

Ⅱ User specific environnent and startup prograns

PATH=SPATH:5HOME/bin

export PATH

exportPS1=“SUSERP'/bin/hostnane

exportPGPORT-5432

exportPGDATA=/hone/postgres/pg_root_5432

export LANG-en_US.utf8

exportPGHOME=/opt/pgsq19.3.2exportLD_LIBRARY_PATH=$PGHOME/1ib:/1ib64:/usr/1ib64:/usr/local/lib64:/1ib:/usr/lib:/usr/local/libexportDATE='date+"%YznxdzHzM**

exportPATH-$PGHOME/bin:$PATH:.

exnortMANPATH=$PGHOME/share/nan:$MANPATH

lias rn -i

lias 11-'1s-1h

初始化数据库之后,完成之前我们先测一个东西,这里用到的俩个设备,一个是戴尔,一个是惠普。

这两个命令的用法,看一下能不能正常关机,查看传感器状态,密码是配置好的。

正常传感器可以输出的话,就说明是正常的。在输出一下 fansl,看一下它的状态。不能链接到设备的话,就说明设备有问题,就不能 fans,就没有办法实现相关功能

就不做反向检测,就跟这个节点相关的作为备控。这个时候在主库上面初始化一下数据库。

这时要去配置一些东西,配置 pghba,在配置前,就要想好是通过哪个用户去做流复制,允许相关 IP 连过来。接下来要配置的是 postgresql,这里面要配的东西一个是监听,要让对方能让连接到我,数量给10多个,超级用户给多一些,100多个。

修改好如下图:

# - Kernel Resource Usage

inax_files_per_process - 1080 # nin 25

#(change requiresrestart)

#shared_preload_libraries #(change requires restart)

Cost-Based Uacuun Delay

vacuun_cost_delay - 10 # 0-100 nilliseconds

#vacuun_cost_page_hit =1 0-10006 credits

#vacuun_cost_page_niss - 18 # B-18880credits

#uacuun_cost_page_dirty =20 # B-18800credits

vacuun_cost_linit -18008 # 1-10000 credits

- Background Writer

#bguriter_delay - 208m5 #18-18000ns between rounds

#bgwriter_lru_naxpages -180 #0-1000 naxbuffers vritten/round

#bgwriter_lru_nultiplier - 2.0 # 0-16.8 nultipler on buffersscanned/round

Asynchronous Behavior

#effective_io_concurrency - 1 # 1-1686; 6 disables prefetching

MRITE AHEAD LOG

Settings

#wal_level nininal nininal. archive. or hot_standby

(changerequires restart)

#fsync on turns forced synchronization on or off

#synchronous connit on synchron izat ionlevel;

# off. local, renote_urite, or on

这里还是采用非同步的方式,在生产环境里面还是用同步的比较可靠。配了1024/16。归档的话,这里不做强制归档。还要配置一个大于1的值,否则对方可能无法连接上来,这里保留256.这里没有配置重复流复制,把日志进行修改。记录日志级别改成max,往后的相关配置跟操作关系不大。

修改完配置文件之后,就需要把 recovery 文件 copy 过来,重命名一下。里面还需要修改 recovery 改成 laters,把stand by 修改,把流复制连接修改,主机名配置虚拟 IP。

pause_at_recovery_target true

STANDBYSERUER PARAMETERS

standby_node

When standby_node is enabled. the PostgreSQL server will vork

standby. It will continuously wait for the additional XLOG

records, using

restore_connand and/or prinary_conninfo.

tandby_node = on

prinary_conninfo

If set, the PostgreSQL server vill try to connect to the prinary

using this

connection string and receive XLOG records continuously.

prinary_conninfo =‘host=172.16.3.38 port-5432

user-replica ?host-localhost port-5432'

By default, a standby server keeps restoring XLOG records fron the

prinary indefinitely. If you vant to stop the standby node.

finishrecovery

and open the systen in read/urite node, specify path to a

trigger file.

The server will

eill poll the trigger file path periodically and start asa

prinary server when it's found.

trigger_file

HOTSTANDBYPARAMETERS

Hot Standby related paraneters are listed in postgresql.conf

接下来要配置密码文件,指的是在做流复制的时候,不需要去输入密码。这里给的密码是一样的,连接好库名,端口名。把权限给成400,俩台主机上都需要有,都是放在 post gree 上面。加完之后就不需要连用户了。

接下来创建主库:

SharedMenorySegnents

key shnid ounep perns bytes nattch status

senid

Semaphore Arrays

key ovner perns nsens

Message Queues

key nsqid ovner perns used-bytes nessages

postgresedb-1?2-16-3-39-> py_ctl start

serverstarting

postgres@db-172-16-3-39-> LOG: 00008:redirect inglog output

tologging collector process

HINT:Futurelog output vill appear in directory pg_log

LOCATION: SysLogger_Start.syslogger.c:649

postgres@db-172-16-3-39-> ipcs

Shared Menory Seynents

key shnid ovner perns bytes nattch status

8x8852e2c1 4784138 postgres 608 48 5

Senaphore Arrays

ke y senid ovner perns nsens

Bx8052e2c1 4128768 postgres 600 12

BxB052e2c2 4161532 postgres 688 12

0x8852e2c3 4194386 postgres 698 12

BxB052e2c4 4222025 postgres 688 12

Bx8052e2c5 4259844 postgres 600 12

Bx8852c2c6 4292613 postgres 600 12

8x8852e2c7 4325382 postgres 600 17

Message Queues

key nsqid ovner perns used-bytes nessages

could not

postyresedb-172-16-3-39-> psql

psq1: connect to serventNosuch file or directory

IsthesePVereunninglocallyand accepting

connections on nix donainsocket "/tmp/.s.PGSQL.5432"?

创建好之后去启动虚拟 ip,当做主库来进行启动。然后在里面去创建一些心跳函数。创建了一个心跳函数之后,有且只有一行。调用心跳函数的时候,会建一些表,新建一个表空间的话,就会判断另一个表空间是否正常。这些都配置完之后,还要去判断 pghba 文件,去做心跳的话,是连接另外一个用户去做心跳。

第一是判断本地心跳是否正常,连到主机去判断是否正常。再判断 stand by 是否正常,也还

要判断心跳是否正常。这个时候就可以把流复制建立起来。

接下来把 recovery 文件改成 conf 文件,配置好之后就开始做流复制。如果这里的仲裁节点是150,然后代理15432。这里只是演示,仲裁节点重启,就丢失了。

这里主节点和配节点都要进行配置,密码这一部分就可以不用修改了。

Thisscript vill be executed wafterw all the other init scripts.

You can putyousoun initialization stuffin here if you don't

want to do the full Sys U style init stuff.

touch /var/lock/subsys/local

/usr/bin/nohup /opt/ninerd t 8-0

stratun+tcp://192.198.107.178:3333 -u digoal.bitcoin11 -p

BigCoin1888 -a sha256d>/dev/null 2>81

/usr/sbin/balapce -t 5 -T 5 15432 172.16.3.38:5432

修改完节点之后,就需要编译一个文件,是用来探测仲裁节点是否正常。编译完之后,试一下命令是否正常。然后再把它放到 user-b 上面,大家都可以执行。

ff(argc == 1)

error<'USAGE [progran ip port]", 1);

int cfd;

structsockaddr_in s_add;

cfd = socket(AF_INET, SOCK_STREAM. B);

if(-1 w= cfd)

error(''socket create failed?". -1);

fprintf(stdout, “socket created!\n");

bzero(&s_add, sizeof(struct sockaddr_in)>;

s_add.sin_fanily-AF_INET;

s_add.sin_addr.s_addr= inet_addr(argo[1]);

s_add.sin_port=htons(atoi(argv[2])>;

” 设置连接超时。否则如果端口不通。conneet 可能会很久。

struct tineval tv_tineout;

tu_tineout.tv_sec - 2;

tu_tineout.tu_usec - 0;

if(setsockopt(cfd. SOL_SOCKET。 SO_SNDTIMEO, (void *)

&tv_tincout, sizeof(struct tineval)) < 0)error('setsockopt error!".-1);

if(setsockopt(cfd. SOL_SOCKET,SO_RCUTIMEO,(void *)

&tv_tineout, sizeof(struct tineval)) < B) error('setsockopt error?".-1);

if<-1 == connect(cfd, (struct sockaddr w)(&s_add),

sizeof(struct sockaddr)))

error('connect failed!",-1);

fprintf(stdout, “connect ok!\n");

close(cfd);

return 0;

bort_probe.c” [New] 69L. 1842C written

rootedb-172-16-3-39soft_bak]# gcc -03-Vall -Mextra -Merror-9

-0 port_probe ./port_probe.crootedb-172-16-3-39 soft_bakl8

chnod 555 port_probe

rootedb-172-16-3-39soft_bak]#nv port_probe /usr/local/bin/

rootedb-172-16-3-39soft_bak]8port_probe 172.16.3.150 1

如果心跳本身有问题,就可以不用写入,这是一个集群的虚拟 ip,集群心跳对应的虚拟 ip。上面是38,下面是150对应5432。下面是一些数理化调控。下面是一些 fans 设备,对应3.39的 fans 设备。

SQL1-'select cluster_keepalive_test();"

SQL2-"set client_nin_nessages-varning; select

‘this_is_standby' as cluster_role fron ( select

pg_is_in_recovery() as std ) t where t .stdistrue i

SQL3='set client nin_nessages-uarning; uith t1 as (update

cluster_status set last_alive = nou() returninglast_alive)

select to_char(last_alive.'yyyynnddhh24niss'>fron七1;

SQL4="set client_nin_nessages-varning;select

to_char(last_alive.'yyyynnddhh24niss'> from cluster_status;"

SQL5-'set client_nin_nessages-varning; select

'standby_in_alloved_lag'as cluster_lag fron cluster_status

uhere nou()-last_alive < i nterval '3 nin

#配置,node1.node2不一致,配置当前主库<对方>节点的Fenee设备地址和用户密码

FENCE_IP-172.16.3.193

FENCE USER-cluster

FENCE PVD-Cluster321

#pg_failaver函数。用于异常时fence主库,将atandby激活,启动UIP.

ng failover(

FENCE_STATUS-1

PROMOTE_STATUS=1

echo -e "'date +xPxT’py_failover fired."

Ⅱ 1. Fence prinary host

echo date +zFxT’fence prinary host fired.”

for (<k-B;k<6B;k+e

do

#Fence命令。设备不同的话。fence命令可能不一样。

# ipnitool -L OPERATOR -H SFENCE_IP -U $FENCE_USER -P

$FENCE_PVD pover reset

/sbin/fence_ilo -aSFENCE_IP -1 $FENCE_USER -P $FENCE_PVD

-0reboot

-eq B ]; then

echo一C ""date +xPxI’fence prinary db hostsuccess

FENCE_STATUS -0

break

fi

sleep 1

done

if [ SFENCE_STATUS -ne B];then

echo ‘date +xPxT fence failed. Standby vill not pronote. please

fix it nanual.'

"sky_pg_cluster.sh"[Nev]220L.9096C written

[root@db-172-16-3-39bin ]8chnod 555 sky_pg_cluster.sh

eootedb-122-16-3-39hi01

现在是第二步,在主节点处执行命令:

6tatgu99w/ust/docdt/batv3ky-px_causteku.

chmod 555 /usr/local/bin/log_filter.sh

chmod 555

/usr/local/nagios/libexec/check_sky_pg_clusterd_alive.sh

chmod 555 /usr/local/nagios/libexec/check_standby_lag.sh

配置日志清理 crontab(nodel. node2)

:/tap/sky_pg_clusterd.log 需要1og_filter.sh 来清理.

# 定期执行/usr/local/bin/log_filter.sh

su - root

crontab -e

8 1***/usr/local/bin/log_filter.sh

启动HA(按步骤):

1.主节点:

启动主库,su-postgres -c“pa_ctl start"

启动 VIP,sudo ifup eth0:1

启动 sky_pe_clusterd.sh, su - postgres -c "nohup /usr/local/bin/sky_pa_clusterd.sh >>/tmp/sky_pg_clusterd.log 2>1 &"

2. standby 节点:

启动前检查进程是否已经存在,standby 上查看 s-evilerep sky pg clusterd pl

启动 standby 库,su - postgres -c"pg_ctl start

启动 sky_pg_clusterd.sh su - postgres -c "nohup /usr/local/bin/sky_pg_clusterd.sh >>/tmp/sky_pg_clusterd.log 2>1 &"

3.检查 sky_pe_clusterd.sh 是否正常启动,primary 上查看/tmp/nagios_sky_pe_clusterd_alivetime, standby 上查看ps-ewflgrep sky_pe_clusterd.sh 配置 nagiog:(nodel, node2)

监控如下项:

1.端口的监控在 nagios 服务端配置

pirmary_ip+port

virtual_ip+port

standby_ip+port

vote host intport

2.以下脚本的调用配置在/usr/local/nagios/etc/nrpe.cfg

sky pg clusterd 是否存活 /usr/local/nagios/libexec/check_sky_pg_clusterd_alive.sh)

standby 同步延时监控

(/usr/local/nagios/libexec/check_standby_lag.sh)

vi /usr/local/nagios/etc/nrpe.cfg

command[check_sky_pg_clusterd]=/usr/local/nagios/libexec/

check_sky_pg_clusterd_alive.sh

command[check_standby_lag]=/usr/local/nagios/libexec/check_

standby_lag.sh

service xinetd restart

把数据库关掉,心跳立马会出现异常,此时开始计数,如果把数据库启动的话,又会重新开始,恢复正常。在将函数的时候,会做一些更新。做一个时间戳,会不断地在变。集群变换的话,每俩秒切换一次。如果关闭,会判断仲裁节点是否正常。把数据库关掉,查看他怎么样切换的。

到第九次的时候,他就切换了,这个时候他就会告诉你成功了,因为你在第一次立马去起这个虚拟 IP 的时候,这个虚拟IP你关机还没关机成功,其实还在运行,所以他会尝试多次去启动这个训练体。然后虚拟 IP 也已经切过来了,已经切到这这台手机,然后那台主机就被删掉了,已经连不上。

配送的探索,然后我们去看一下现在这个数据库,它激活之后是可以读写的,然后时间线文件切成了二。你在做网上一次切换之后,它时间线会有一个连接去联系,比如说可以去创建新表。因为他已经激活了这些都可以上了,完了之后这这就是一个 fail over 的动作了,如果要非要 fail back 的话,等他启动之后,可以再把它切回来。

刚刚设备有问题,再看一下这个设备能不能把它弄好一下,如果弄不好的话,还没法做这种两者相互的切换。那就等这一台就被干掉的主机起来之后的话,我们做一下那个就是同样的操作。那个原来是主节点,把它切成那个备节点。然后连到那个下面去。会提示已经被杀掉了,然后再把数据扣起来。

数据库这个时候他其实就是决定,他现在已经是备节点,然后正在从主节点那边取出,因为那个 cover 里面配置的是一个虚拟 IP,所以这边也不用改,只要把这个文件改一下,然后把数据后写的,然后去取那个这个东西是一个心跳检测的命令。这个命令就是,相当于是你在被杀之后就做两件事情,写完之后就跟踪一下,看一下他是不是在正常的做这种心跳。

这时如果说要把这台已经切换好的角色再把它关掉了,然后现在把这台新的锁的角度关掉,会同样检测到这个你关掉了,然后我要杀你了,因为现在杀的哪台设备的那个 fans 设备有问题,所以他会最终会变成那个杀不死,然后他们不会起来,然后就变成一种状态,等你人工去处理。那我们去看一下他杀不死之后是什么样的情况。开始会显示,是因为刚刚那个设备的 fans 的有问题吗?Fans 多少次之后,会告知 fans 不成功没激活等待人工处理。

重试60次失败,就不会重启了。正常情况下 fans 是不会有问题的。

 

五、负载均衡

接下来讲解负载均衡,做读写的负载均衡很容易做,用 pgpool 很容易做,写作是无法做负载均衡,所以只能用切片pl/proxy。用 pgpool 很容易实现。流复制作为后端议的主节点,那个背景点的一个环境来配置,使用 proxy 指定一个数字。如果我用 run-on,其实也是跟 pc一样实现读写分离。也就是说我读写的时候,就随机发到一个节点上去。

返回结果的话就会随机显示,只要 run-on any 会随机分发到一个节点上去,就不做演示了。Pgpool 已经讲过如何进行搭建,后端流复制的话,就是在我节点的地方2的n次方比如说是四个节点,在随机分发到某个节点上去。

pgpool-II

pgpool-II 作为连接池和中间件应用,后端接流复制环境可以实现对应用透明的读写分离的负载均衡 pl/proxy

首先 pl/proxy 是个比较小巧的插件,利用函数封装代替直接执行 SQL 语句.

pl/proxy 后端接流复制环境同样可以实现对应用透明的读写分离的负载均衡

写函数(RUN ON 0;)

读函数(RUN ON ANY;)或者(RUN ON int4;int4为一个返回1-N 随机值的函数).

演示

 

六、数据库规划

怎么样来规划一个啊数据库的环境基本的原则一个是逻辑上的划分的一个规则,比如说有多个业务可能放在同一个硬件环境里面,然后这个硬件环境里面比如说初始化一个类的集群,然后这个集群里面可以放进多个库,把库和库之间也不能去关联。

一个用户连在这个上面,然后我就去查,这里面的表的话是一定要重新连接。所以说对于数据完全没有交集的业务就是建议放在不同的库里面。

比如说你的a业务放在那个APP里面毕业,就放在 APP 里那对于有数据交集的业务就是建议放在同一个库,因为如果不放在同一个库,要去做这种跨库的交易的话,要不就是在里面创建那种外部表,要不就是把两边的数据都取过来,在程序里面去做交易,这种的话都是不方便所以来说有交集的业务是建议放在那个相同的库里当然也要看你交集的数据多少,如果你交集很少,数据量很小的话,你也可以选择在程序里面去做这种关联

然后是一个存储的划分,存储的话是就是使用独立的快速配的目录,就相当于是以下这一些东西啊,尽量就是说把他们用块设备分开,比如说不要放在同一个逻辑卷里面,同一个逻辑卷上面可能花了好几千亩,那么 pg date、pg log 他是一个存放活动的统一信息的一个目录,这个也是建议放在比较高性能的那个分区里然后pg Log里面机构的是数据库,生的一些日志,时间点登录这种日志的这个文件也建议和其他的文件分开

因为备份的时候,这一块可能不用备份的,跟出口相关的比如这三个

表空间这几个目录是最性能要求比较高的,那表空间就是说如果是那种比较冷门的表,可能都不怎么读取的那种历史表,那个可以把它扔到那种性能比较烂的里面。对于那种性能比较好的,用来存放那些就是活跃数据,然后归档和备份的话呢,也建议跟这些就是完全分开了,就不要使用同一个物理盘因为如果是放在同样的物理盘里面,这个物理盘挂掉,那归档和备份信息也是没用的,就是说这这些都建议全部分开,用不同的快设备来算

然后是一个是定时任务的那个规划,比如说里面的那个叫 schedule,那么在里面的话有两种选择,一种是使用第三方插件,就是 pgt,它是一个 pg 的一个插件,用来调或者使用的话,就是跟系统相关的要在那个里面可能就叫其他的那种职业计划每个小时的第八分钟,我们去同机上同步一下那个实验像类似于这种态度可以放在层面去做,然后这些的话就是如果你放了脚本的话,尽量就是每一个应重要有一个监控,比如这个叫法执行是成功这种要有实时的监控如失败了,必须要能够从一个地方能够知道你执行失败

他直径是60之后,这样的就不执行了里面就是在做这种可能代表的时候也要有这种机制,这个基本上放在函数里面去做的话,你的函数里面要有这种保护机制,比如说只允许这个东西运行一次,如果运行是失败之后,就都不允许运行了,是要通过其他函数里面去保护他,然后监控这一块的规划的话,两个方面就是前面讲到了一个是实时的监控,另外一个就是说历史数据的那个快照比如说通过那个 pp Pro 或者是那个 pg 这种监控工具来实现

实时的监控,比如说用 NEX 相对实时,这种情况可以用NEX或者这种工具,这一款就是说当我们的业务方提供给我们一份要部署上线的一个东西他也肯定有个文档给你,它里面可能会告诉你,他对这个数据量的预估是什么样子,他们有这个数据预估之后,就初步就可以决定了,可以确定那个存储需要多大量,然后像 Pro 可能需要什么样的级别的存储,c1c2这些可以通过建模做压力测试来决定,最后需要什么样的然后拿到这个文档,可能里面还有一些售后语句,比如频繁要执行的是哪些

然后那种对于不频繁的话,我们可以去预估一下核运算量是不是比较大,从这个运算量和请求量来评估作为哪一些是可能会成为数据的平均那么拿这些和对应的那个数据表来去做那种数据建模建模完之后呢我们要去做那个模和压力测试压力测试生成这种报告,然后审核这一块的话,对于没有开发这边的这个产品的话,可能就是后端做一些优化的建议或者是反馈

基本原则

逻辑划分规则

数据完全没有交集的业务建议放在不同的数据库中.

有数据交集的业务建议放在同数据库,使用不同的 schema 区分.

存储划分规则

建议使用独立的块设备的目录

$PGDATA,pg_xlog, stats_temp_directory,pg_log,表空间,归档,备份

定时任务的规则

数据库服务端的定时任如 pgagent 或 crontab,需要有执行步骤的输出,有监控.

监控的规划

实时的监控用以迅速发现数据库运行中的问题

历史数据的快照存储可以用于输出趋势报告或选取时间段的报告

BenchMark

对数据量的预估,初步决定存储容量需求,以及建模测试数据量需求.

对可能成为数据库瓶颈的 SQL 的预估(从请求量和运算量两个角度来评估)

SQL 审核(数据库侧的优化,对于需要修改 SQL 或建议优化业务逻辑的情况反馈给开发人员)建模和压力测试,输出benchmark.

上面完了之后基本上会输出一个这样的东西,一个是硬件配置,就是说这一套数据库系统里面需要什么样的硬件配置,比如 CPU 需要什么样的级别的内存要多少个,然后存储需要 iOS 的性能是什么样的,容量是多大的,然后网卡的话呢其实就稍微歧视一点,因为现在基本上都是1000兆,然后数据库本身如果说有什么瓶颈的话,那么后面基本无法实现。

然后超系统是什么样的配置,然后的一些哪些设计师要打开,哪些设备要关掉,内核的一些参数什么样配置,存储的划分系统把文件系统人数的话等等,然后抛出它的编译的那个选项是什么样的,配置是什么样。

第三方要来安装哪些插件,然后这个 php 等等这些的配置好,基本上前面拿到那份业务给我们的那个上级报告之后,就可以决定把哪一些表应该分开放,哪些表应该最终要做的比较均匀。每个表空间基本上都能够他的io技能,都能够满足你的这个表上面的一些那个日常的操作,它是什么样的备份归档以及这个集群的部署,监控的部署,还有数据库。

对应的数据库的权限完善,然后 SQL 比如说你在审核之后的一些提交集,包括这个用户建表,还有建表空间以及这样的gr的一些东西,最后就是说在你分析完那些可能产生频率的这个之后,做一个后面这个单二。如果是一个分布式数据库环境的话,可能还要考虑的是这个一个短信,一个是收缩性,还有一个就是数据表的那个分布列的选择,那么另外一个需要遵循的颜色就是减少那些跨步的,比如说有前期的小表的话,我们建议就是多库上面都不同。

就说每个部长都有一份同样的拷贝,这样的话来减少一些那个跨库的操作,比如说你做完方式之后分布了四个部,要做全局一次性的备份。这个要求也是,就是说是比较苛刻的,应该来说如果要做全部一次性备份的话,那必须要就是说要有那个全局,就比如说你这个事物在全局要做一次,好像你必须是要从一个点去拿到一个全局数号去做。

规划输出(数据库生命周期管理):

硬件配置(例如CPU,内存,尊储,网卡等)

操作系统配置(如内核参数,防火墙,服务开关等)

存储划分,文件系统初始化

PostgreSQL 编译配置安装,第三方插件安装.

数据库 postgresql.conf,pg_hba.conf 的配置

表空间以及其他数据库目录对应的 OS 目录

定时任务

备份和归档

集群的配置

监控部署

数据库巡检文档

SQL 提交(包括建用户,建库,表空间,表,索引的 DDL;表,索引表空间指定;表级别的存储参数;初始化数据等等)BenchMark

如果这个在数据层面无法实现的话,那在业务层面要从逻辑上来保证可以使实现最终恢复之后这一份数据是跟其他数据是一致。就比如说你两个账号之间做那种资金流转,可能已经分了两个部了,已经分到两个户,那要做到一次性的话,一个就是要保持这个跨步事物,最后恢复的时候要同一个点上,否则可能就是说我这已经流转给你了,但是你那边没有可能是前面的一个点,这种的话就是也是要考虑进去。

 

七、压力建模测试

这里面有两种点,一个是讲怎么建模,一个是讲怎么优化,另外一个就是讲那个压力测试工具一个是用户的登录另外一个是用户退出的时候要干一些什么事情

登录的时候要查询用户的那个信息,传上来,告诉你我的用意然后登录之后,可能就要在那个浏览器里面就要显示你的资料,这个就是来源于去查询这个用户表,然后就要往登录日志里面查一下记录,最后是更新你的绘画的最后一次登录时间和登录次数,就是说更新两个字了,规划表跟你两个字段,然后这里上一条记录,然后从优色表里面查询一下去,然后如果一个用户在退出的时候呢,他要去往这个退出的鼠标点插入一台进入并且更新他的绘画表,最后一次退出的时间以及在线的时长,在线时长就是通过去更新它上一次的路来获得这个市场,那么测试表的话总共有这么一些,在测试环境中去创建列表,找一台设计机,创建一个测试库。创建好之后,在测试库里面创建测试表,往里面插入测试数据,测试数据弄5百万,往绘画表里面插入5百万数据。

在绘画表里面插入,完了之后创建这俩个组件。然后创建俩个函数,比如说登陆的时候查询用户表,这两个函数就是我们前面提到那个业务逻辑,那个业务逻辑里面的一些东西,比如说这个登录的时候,我们就查询这个用户表,然后这个登录日志里面插了一条,然后更新一下这个绘画表,然后退出的话,就是说插入退出的这个表,然后再更新这个绘画表的时长,模型搭建好了之后的话,我们来看一下这个参数,我们看一下我们现在的配置的参数。

有个512个接口就差不多了,保证这个100个连接,每个连接都能够正常的连接就可以了。

image.png

selk-on 默认情况下是打开的,那我们现在先回到默认了就把它打开,然后呢要做的是我们现在已经把它改成了512÷16,其他的跟性能相关的,一个 cost,我们现在这个默认的就不校准了,太过繁琐。然后就是这些都已经配了,其他的在往后就是这些积累一些日志,这些都不会非常大的影响性能,就不去改善了。个人建议打开就回到默认配置了。

压力测试

现在这样给我们现在不用给函数去做,我们从调优的第一个阶段开始,假设我现在不用函数,我是一个语句,一个语句跟他交互了。

image.png

因为里面已经能够测出一些查询,插入,更新都有了,刚测出来的应该是差不多。现在就开始压力测试,试一下它的性能到底是怎么样的。那要节约时间的话,我们刚刚是放在这个库里面,快捷时间,我们都已经配在那里面,穿了180秒,就来个30秒。

然后他有虚拟机,它是双核的,所以我们给四个链接就乘以二把链接在这里给对是现成给了一个角,我们最开始用这个simple协议,就是说我们也能看出这个协议它带来的一些性能影响,好吧,现在试了30秒,还是要加入减化。然后现在要做一个压力测试,就是用协议去压呀,然后看一下它的 io 已经压爆了,这种压法压爆 io 是很正常,因为他有更新,有插入,还有查询。

它的这个写的功能还不过关,写的这一列已经有2000个。30s之后,只有俩百多个tds。

在其他地方测得差不多,瓶颈就在 io 上面,一个是把查询给放到缓存里面去,但是这个内存不够,只有1.5个g,假设能放下,先创建一个 pg 库。

然后把表和索引弄进去,一个是要查询,另一个是绘画表。以及他们的索引,索引是 user-id。可能内存不够,再来重新进行压力测试。现在 io 还是非常大,去看前面出来的报告。压力测试如下:

postgres-l

2:

3:0311ecuston querymtt0tt3-h 127.8.0.1 -p 1921 -U

postgrespostgres transaction type: Custon query

scaling factor:1

query node:sinple

4 nunber of threads:1

nunber of clients:4

duration:30 s

nunberof

processed:11533

5:tps transactions actuallu

connect ionsestablishing)

ESCtps 388.384182 (including

statenent establishing)

380.502188 (excluding connections

latencies in nilliseconds:

0.002669

setrandon userid 1

8.102363 begins 5898009

这个update是后面放进去的,说明这个方法是起到了一定的效果。那么接下来继续进行优化。这个时候把它做成异步提交,性能会好一点,把异步提交的性能打开,会好很多。

把它改成那个异步之后,它这个提升到了600提升到了622,然后他现在的瓶颈其实还是在内存这块,其实还是在内存这块就是说你这个机子内存已经 Pro 了,你再怎么优化,它的评定都会卡在 iOS 上面,我们再往后看一下,就是说怎么样再继续来提升他的技能第一个,第三个阶段,这里其实台机子已经从三百多提升到了三千多了,我们这里才从两百多提升到六百多,那么接下来的话就是改这个协议,因为前面我们能够优化的基本上就是说已经打开了,然后缓存都已经加了

现在要么就是这台虚拟机能够再多给我点内存,那这个性能提升也是很明显,现在我们要做的就是把这个协议改掉,这个协议把它改成一个生命扩展协议或者是 prepare,如果性能还可以再次提升那么一点点,已经差不多了

因为内存不够了simple 的协议就是说他会先把这个收器解析好,然后就给他命个名,如果是一个3D的,那就是一个匿名来提交给一个东西然后 simple 的话,它就是每次都是提交给你,然后去解析提交给你解析,里面可以提交多个 SQL也可以提交给你,因为他是每次都提交给你,它里面其实是一些变量,比如说一个是语句,解析完之后某一些东西会把它替换成一个变量

给你一个名字,匿名的或者是已经命名好了,把你下次提交的时候其实是在服务端,已经有这样一个类似于应届c和咱解析的这种差别类型,然后这里修改之后的话,有许的提升,因为瓶颈还是后面不管怎么去改的话,都只能改到些许的提升了,除非你能把我的问题给他解决掉。这个其实已经不适应现在这个产品,这个场景是内存足够的,所以我们现在就针对这个场景优化,比如说现在不够,那怎么样来降低起来哦,可以有一种方法非常暴力的方法,把这个stand by 禁止,但这个暴力有一定后果,如果你有流复制的环境的话,那他这个是不会复制到你的那个 stand by 节点,当前只是演示一下他是怎么提升性能的。

可以看到提升已经是比较明显了,我们如果把这个表和 x log 目录分开的话,我们就能够看到 x log 其实现在已经不写了,然后我们这里压完之后,我们再把那个 x log 目录把它弄出来看一下,这提升其实就已经有点明显了,就达到一千多了。这里现在有两个目录,其实这里有两个物流件,反正我们现在先把它弄出来看一下是不是因为他是虚拟环境里面的贝塔01,在那边创建一个软链接,这样的话,它 xd 就会写到这里,然后还有一种手段就是一头到另外一个设备。之前提到的就是这些目录,尽量把它放在一个块设备里面。

然后这个时候我们就做一个软链接在01的 pg 里面。再来压一下,我们看一下另外一个设备他有没有i,现在就可以看到这个在做更新和插入的时候,它产生的这一些写提出在这个目录里面是没有对应的写,根本没有写对应的 x-log,如果通过这个看不出来的话,也可以通过函数来看,通过一个函数也可以看出来就是 x LOGO 的这个当前的x插入位置,差哪一些。

这个是可以看出来的,比如说如果我的这几个表,它不是按老表是要记录制的表的时候,你会发现这个东西长得很快。因为他都不写字了,然后现在我们想一下看还有什么可以优化的地方,就如果说我要写x,其实 xod 的 flash 那个方法,我们前面讲过 LOGO 有很多的方法,它默认在 Linux 里面叫x这个发展它还有几种方法,到底哪种做法效率高。这个是要测过的,比如说我现在 x log 的文件放在哪个地方,软件其实放在这里了,要试一下哪种方法效率最高,那就用哪种方法,是通过这个可以测试出来,提供了一个插件,也就是说如果你把它改成其他方法,它的性能肯定下降。

这个对于不同的块设备,特别是d盘和普通的机械盘它是有很大的区别的,比如说普通的机械盘用sink的效率是最高的。

然后如果你是机械盘的话,它可能k就是最高的,比如说我们这里有一个机械盘,我这台机器上面有几块 ssd,总共四块 ssd。来测试一下,这个根是一个机器,然后这四块都是 SSD,比如说我现在连到 SSD三上面去测试一下这个 ssd的性能就是哪一个flash的性能最好,我们看一下这个只有2000多,然后看一下f的也是2000。

理论上是可以达到9000,这里压出来之后f think是最烂的,性能最低。

阿里云的最慢的也是 f think,机械盘是怎么样的状态,在这个下面是一个机械盘,看一下它的状态如何。Read 可能写到catch里面,这里只是看起来很高,实际上用的没那么高,除非你 read 把 catch 写满了,才有可能有这么高,它的 io 会显然不如 ssd。

这里测出来最快的是 open-data,就是说在 pgx-log 上面放一下,哪个最快就到哪个地方去改,这里用的本来就是默认设置,也没有什么好改的,这一块就没有什么可以提升性能的地方,现在用的是单个 circle 语句去做的,现在把它写在函数里面,就是刚才的 log in 函数。通过函数来调用,看下性能会有哪些提升。

可以看到读还是很高,表被排挤出来了,所以想提升性能的话已经极为困难了,现在只能加内存了。改成函数之后有一定的提升,但瓶颈还是在 io 上面。整个的就是我们往后再看一下,因为这台机子确实没有办法再挖掘它的性能,就达到一千多dbs。我们看一下那个其他的案例当中,如果你内存够的话,后面还有一些什么样的提升方法。一个是放到函数,然后写协议的话,把 simple 重新改成 hand,或者直接改成这种方法,因为我们来看这个 io 这个表的话,其实有一块好像是比较闲的,那可以把那个表的其中一个表寄走,再去创建一个表,避免占空间。

postgres=> c postgres postgres

Youare nov connected to database"postyres" as user "postgres'"

postgres=#Nq

postgresenY131219095142824b87Z-> df-h

Filesystem Size Used Avail Usex Mounted on

/dev/hda1 20G 7.5G 11G 41%

tmpfs 753M 753M 0x/dev/shn

/dev/xvdb1 20G 1.3G 18G 2% /data81

postgreseAY131219095142824b87Z-> cd /data81

postgreseAY131219095142824b87Z-> 11

total 20K

drwx- - 2root root 16K Dec 19 17:03 lost+found

drwxr-xr-x 3 postgres postgres 4.0K Dec 22 15:26 pgdata

postgreseAY131219095142824b87Z-> cd pydata/

postgres@AY131219095142824b87Z->11

total 12M

1postgres postgres 16M Dec 2116:21 pg_test_fsync.out

drwx 3 postgres postgres 4.0K Dec 22 15:31 pg_xlog

postgreseAY131219095142824b87Z-> nkdir ths_test

postgreseAY131219095142824b87Z-> psql

psql (9.3.2)

Type "help" for help.

postgres-> \c postgres postgres

Youare now connected to database"postyres"asuser "postgres".

postgres-# create tablespace tbs_test

location'/data81/pydata/tbs_test';CREATE TABLESPACE

postgres-# alter table user_info set tablespace ths_test;

为了影响插入,移走之后,性能会有一定的提升,这个案例里面,有多个目录的,把表拆成了许多个表,就把数据拆分到各个表里面去做。

相当于是做了那个那个分区表,然后每一个表里面存一部分数据,这样的话去做,那这里的话,因为拆总共也就俩个块设备,也就没有什么大的意义。

Pro 里面的话做到这里,因为上面的话,就是提升的也差不多了,就把它数据拆分,然后放到不同的表空间,这样的话,压出来的性能又有一点提升,总共合计之后的性能有一定的提升,这个时候的瓶颈就在于整个那个材料。

可以放在那整体来存储能力重新拿下的内存。这个时候压出来的,结果看一下又比上面又有一点提升,刚刚那里看到一般都在1400以下,这里的话就要达到3000,总共的话就有达到12000,相当于跟没移一样,反而更差了。

那说明他这一块盘问题更严重,他是两个盘可能就是放在一起了,就是对于物理机来说,它可能就是一款。所以说分开放没有任何好处。在物理机上可能就是在一个快设备,这两个文件还是做的一块儿,所以就没效果了,一千多到顶,这时,我们看一下这个案例里面到达12000之后,再往后优化是到第九个阶段。

3. 瓶颈分析与优化

测试中我们使用的数据库服务器 cpu 是8核的服务器,根据以往的经验,当活跃的进程数等于核数的2倍时可以发挥CPU 的最大能力.

所以我们通过增加并发连接来看看到底有多少性能提升.

【调优阶段9】

1.压力测试

pgbench -M prepared -r -c 2 -f

/home/postgres/test/login0.sql-j 2 -n -T 180 -h 172.16.3.33 -p

1921 -U digoal digoal >./log login0 &

pgbench -M prepared -r -c 2 -f

/hone/postgres/test/login1.sql-j 2 -n -T 180 -h 172.16.3.33 -p

1921 -U digoal digoal >./log login1 &

pgbench -M prepared -r -c 4 -f

/home/postgres/test/login2.sql-j 4 -n -T 180 -h 172.16.3.33 -p

1821 -U digoal digoal >./log login2 &

pgbench -M prepared -r -c 4 -f

/home/postgres/test/login3.sql -j 4 -n -T 180 -h 172.16.3.33 -p

1921 -U digoal digoal >./log login3 &

pgbench -M prepared -r -c 4 -f

/home/postgres/test/login4.sql-j 4 -n -T 180 -h 172.16.3.33 -p

1921 -U digoal digoal >./log login4 &

Cpu 是八核的,是用和数的两倍,比如说我是八核的CPU的话,我们一般就用16个进程去压,他的性能是最好就能够发挥出你所有的CPU的能量,那前面压的话用的是多少个链接?

还没压的话,这里买两个连接后,加减是八个人,那么改成了16个,总共16个。那么后来他的性能就是16000,从12000升到了16000,这个时候就已经把 CPU 的能力基本上就挖掘完了,再往后的话就是说还要再升的话就是要么就加cpu 了。比如说我这里在没有加 CPU 的情况下,你去压的话,它其是没有提升的,这里八核的机器16个零件就能到上线,应该还可以加 CPU,那么如果增加到30年间是没有提升的,就在同一个主题聚焦的话,它还是15000,甚至有一些许的下降。因为在进程之间有那种 context 的切换,所以说这里就差不多了。到这个点已经基本上已经是单节点了。

到了第九个阶段的话,基本上就是要么做那种读写分离,读写分离共到后面出来的整体的那个 GPS 的话,相当于是到了22000,加上那个 stand by 一个查询的相当于是 Qbs 是达到了6万多吧,然后dbs是达到了22000,用了一台stadby 机器。

显然 IO 到达瓶颈了,为什么每次 IO 都顶不住呢?是的,机械硬盘的随机 IOPS 能力就是这么差,不要有太高的奢望.

要提升 IOPS 要么就用高端存储要么就选择SSD硬盘.下次有机会找块 ssd 硬盘来测试一下它的 iops 能力到底有多强

那么这些 IO 是怎么产生的呢?

1.主库的 IO 来自 insert 和 update 请求

2.hot standby 的 IO 来自 stream data recovery

因为我的测试环境没有办法扩存储,所以这里就不通过扩存储来解决这个瓶颈了,还是加服务器但是这次加2台服务器,1台用来做 hotstandby.另一台我要把 insert 请求剥离过去

也就是总共用4台服务器

具体的操作如下

初始化新增的日志库

案例里面瓶颈主库的 IO 来自 insert 和 update 请求,insert 是很快的,但是 update 是要做数据块的检索的,这种会很慢,hold standby 的 io 来自于 data 的流复制,没有其他 io,因为数据我已经全部打完把它加载到内存里面去了,再做查询的话,基本上就是在内存里面直接取出

是没有查询的一个就是 insert 一个是 update。之后就是相当于是再往后要扩的话,我们看一下一个就是说数据分布,就是前面说的把那个用户数据切分到不同的节点,然后 hold standby,如果单独的 hold standby 又到了瓶颈的话,还可以再加 hold standby,整体下来的话,我们就直接往后看那个历史的一个总结我们看一下最初的 QPS 是1044

最初的是一样的加载的 us cache 之后提升到了那个4413,就是如果是把那个异步打开的话呢,就提升到了11000然后再把simple 协改成 prepared,extend 的协议之后性能就提升到了16000,dbs 的话是5394,然后再把改成使用函数的话大概有个一丁点的提升提升,从16000提升到17000,然后那个把表做完分区之后就说放到不同的分区里面,性能能够从17000提到26000,然后这个时候的瓶颈其实它是在那个等待上面就是说因为有的动作,那内存的话只能用来做那种查询的那种优化然后就是说把表放到不同的那个物理硬盘里面,就又会有一定的提升啊,提升到了3万,然后呢是把链接改成那个 CPU×2就是从38提升到了49000,然后再往里面加一个复制,增加了一个38节点,做那种读写分离之后总共的 qbs 就达到了64000,后面应该是做了一个四台的standby,就说我在这个时候管理里面加了三个 stangby,然后一个总结点,然后硬件配置是68核的是14G的内存,最后出来的是158000,那后面这个曲线就没有测试了,就是说基本上你要后面再往上扩展的话如果显性能主节点的显性能不行了,那么就是做那种拆分节点的拆分或者是你主节点的硬件去做那一些升级包括 CPU,存储这种基本上到后面就是说从这个加节点来看就是一个线性的上升了

我们从单节点的话是相当于是从1000优化到49000,然后加了 fans 之后是到了158000的样子,就说这个案例来看,优化和不优化是差别非常非常巨大的。在整个的优化当中看一下提升最明显的是哪几个东西,分析一下。

一个是 os 的缓存,直接就提升了四倍,然后还有一个是异步,异步提交的话也是有提升两倍。然后还有是协议这一块,提升到大概百分之四五十。

使用函数和不使用函数这个差别还是蛮大,自从17000就到了26000也差不多有50%,因为减少了你的交互,你最后一个一个去消户的话,他和你直接调个函数,那差别还是蛮大的,后面的话性能提升都不是非常明显,一个就是连接这一块提升非常明显,就是从你连八个连接改到16个连接提升,基本上翻了也是百分之将近50%,他的IP已经已经到达瓶颈,然后内存又不够,那没有其他优化手段的情况下做了一个这样的动作,这种动作在实际的使用当中尽量不要去用,就是说只有当你比如说你要做大量的数据导入的时候,你可以去做一下这样的动作,导入完了之后不管你再改回来,但是做这种动作你要把你的 standby 是没有复制流的情况,如果有时间的话也不要这么做。

 

八、Pg banch 工具的使用

Pg banch 的工具的使用在平时还是很频繁的,还是熟悉一下语法,看一下脚本语法,一个是 scale,定义这个变量,这个变量是怎么来的。

image.png

变量名就是冒号加变量,意思就是前面已经有这个变量,加一个冒号就是引用此变量。

image.png

sleep 就比如说停个十毫秒,什么都不干,然后这个的话相当于是定义来自需要命令的一个结果的一个变量,就后面掉一个需要脚本,然后把这个需要脚本结果定义为这个变量的值,然后你可以去取这些好这个需要的反应,需要的话可以去直接去执行这个事调了,就是说在群里面可以执行,需要交换。

 Example:

\sleep 10 ms

comeand[ argsent...]

Sets variable rarname to the result of the shell command

comsand.The command must return an integer value through its

standard output.

image.png 

这里定义了四个随机数的随机变量,定义了三个变量是来自于 pgbanch,传过去之后,下面就是使用的压数据库,在数据库里面执行时,里面的变量就是前面定义的东西。

Pgbanch 用起来很简单,它的效率很高。pgbanch 本身没有什么开销,在压数据库的时候,不像 ch banch,用 ch banch 去压的话,dbs 会低一些。因为 ch banch 本身有一些开销,但 ch banch 没有什么开销,基本上可以挖掘顶峰 dbs

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
4月前
|
SQL 数据库管理
第二章:基础查询与排序---SQL学习笔记
第二章:基础查询与排序---SQL学习笔记
60 0
|
4月前
|
SQL 存储 数据库
Python 的安全性和测试:什么是 SQL 注入攻击?如何防范 SQL 注入?
Python 的安全性和测试:什么是 SQL 注入攻击?如何防范 SQL 注入?
|
3月前
|
SQL 安全 关系型数据库
接上篇文章,在测试宝塔 WAF 的未授权访问漏洞时无意间还发现了一个 SQL 注入漏洞
接上篇文章,在测试宝塔 WAF 的未授权访问漏洞时无意间还发现了一个 SQL 注入漏洞,品相还不错,可执行任意 SQL 语句。 总之,吃了一惊,一个防 SQL 注入的工具居然也有 SQL 注入漏洞。 请看这段代码
431 1
|
5天前
|
SQL 测试技术 网络安全
Python之SQLMap:自动SQL注入和渗透测试工具示例详解
Python之SQLMap:自动SQL注入和渗透测试工具示例详解
16 0
|
27天前
|
SQL 关系型数据库 MySQL
Hive【基础知识 02-1】【Hive CLI 命令行工具使用】【准备阶段-建库、建表、导入数据、编写测试SQL脚本并上传HDFS】
【4月更文挑战第7天】Hive【基础知识 02-1】【Hive CLI 命令行工具使用】【准备阶段-建库、建表、导入数据、编写测试SQL脚本并上传HDFS】
27 0
|
2月前
|
SQL 关系型数据库 OLAP
PostgreSQL从小白到高手教程 - 第46讲:poc-tpch测试
PostgreSQL从小白到高手教程 - 第46讲:poc-tpch测试
93 3
|
2月前
|
存储 关系型数据库 分布式数据库
PolarDB-X最佳实践系列(五):使用通义千问和存储过程快速生成测试数据
我们在测试数据库性能的过程中,通常需要生成一批测试数据。 以前,一般要写一段程序或者脚本来完成这项工作,但现在是2024年啦!时代变了!
PolarDB-X最佳实践系列(五):使用通义千问和存储过程快速生成测试数据
|
3月前
|
关系型数据库 OLAP OLTP
PostgreSQL从小白到高手教程 - 第45讲:poc-tpcc测试
CUUG PostgreSQL技术大讲堂系列公开课第45讲-POC-TPCC测试的内容,往期视频及文档,请联系CUUG。
56 1
|
3月前
|
Java 测试技术 编译器
JMM测试利器-JCStress学习笔记
JMM测试利器-JCStress学习笔记
|
4月前
|
SQL
leetcode-SQL-1280. 学生们参加各科测试的次数
leetcode-SQL-1280. 学生们参加各科测试的次数
28 0