PostgreSQL监控实战 基于Pigsty解决实际监控问题 ——冯若航

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: PostgreSQL监控实战基于Pigsty解决实际监控问题——冯若航

内容简要:

一、为什么需要监控系统

二、用监控系统解决问题

三、监控系统的部署

 

 

一、为什么需要监控系统

离开监控系统管理数据库就像蒙眼开车,我们通过利用监控系统实现对数据库状态的观察与管理,下面通过两个实验举例说明。

(一)实验1:利用监控系统观测查询负载

1)使用正常连接数负载,观察系统状态

这里我们做一个实验,已有一主两从的数据库集群PG-test,为集群添加50的读写QPS1000的只读QPS,利用监控系统的信息,印证我们主动施加的负载。这个负载是用PG自带的压测工具PG Bench生成的。

命令一:

while true; do pgbench -nv -P1 -c4 --select-only --rate=1000 -T10 postgres://test:test@pg-test:5434/test; done

命令二:

while true; do pgbench -nv -P1 -c4 --select-only --rate=1000 -T10 postgres://test:test@pg-test:5434/test; done

第一行命令我们用PG Bench给从库select-only加上了1000TPS,第二条命令我们给主库加上了50TPS,从库使用4条连接,主库使用2条连接。

那么我们期待的结果总共加了1050TPS,主库50,两个从库每人各500,从库总共1000

image.png

如上图所示,我们可以看到整个集群的GPS数据,主库上的TPS差不多是50左右,从库上的TPS差不多是1000,符合我们的预期。

 

2)使用十倍的连接数施加同样负载,观察系统状态

接下来我们稍微改动一下,施加同样的负载,但使用十倍的连接数量,原来我们使用了2条读写连接,4条只读连接,现在翻十倍变为20条和40条,观察连接池在这一过程中起到的作用。

命令一:

while true; do pgbench -nv -P1 -c40 --select-only --rate=1000 -T10 postgres://test:test@pg-test:5434/test; done

命令二:

while true; do pgbench -nv -P1 -c20 --rate=50 -T10 postgres://test:test@pg-test:5433/test; done

image.png

我们来看一下监控系统,PG Cluster Session是专门绘画关于集群相关的指标,其中的Active Clients by Instance是按照实例划分的连接数。如上图所示,通过最近5分钟的情况可以看到,之前使用的是6条连接,222从,现在使用60条,就变成20 2020。如果说TPS指标它是有一定抖动误差的话,那么连接数这样的指标可以算是相当精确了。

 

3)使用尽可能大的负载,观察系统在过载下的表现

我们采用没有 TPS限制的PG Bench,用最大负载把集群尽可能打满,观察系统在过载情况下的表现。

命令一:while true; do pgbench -nv -P1 -c20 -T10 postgres://test:test@pg-test:5433/test; done

命令二:while true; do pgbench -nv -P1 -c40 --select-only -T10 postgres://test:test@pg-test:5434/test; done

image.png如上图所示,我们回到主页可以看到,监控面板目前的负载水平已经超过100%,主库负载严重超标,两个从库也基本进入过载状态,整个系统已经爆表。当我们将负载定量重新调低后,整个系统的负载水平会逐渐回到温和状态。

 

以上实验反映了监控系统的基本功能,它能够如实地反映用户给集群施加的负载以及集群本身内部的状态。

 

(二)实验二:重启主库,观察集群领导权交接

我们通常所说的高可用,指的是当一个系统的主库宕机时,应该有一个从库自动被提升出来接管系统。如果没有监控系统的话,这个操作对我们而言是一个很抽象的事情,下面我们借助监控系统来观察一下这个操作过程。

比如我们登录到第一台主库所在的机器上,然后执行ssh –t node-1 sudo reboot,可以看到负载都开始报错。但在短短数秒内,无论是读流量还是写流量,它都自行恢复正常运行。

image.png

如上图所示,我们可以看到监控系统中原本的主库pg-test1已经被踢掉了, pg-test2被提升成新的主库了,开始承接写流量。当pg-test1重启完成之后,它是一台死掉的Primary,会尝试将自己降格为一台新的从库,重新挂在pg-test2的位置上。

image.png

同时我们可以看到,整个集群的领导权Leadership图表已经发生转移,比如说原来集群的新领导是pg-test1,现在变成pg-test2

 

通过以上两个实验可以看出,监控系统对于反应系统状态来说,是一个非常实用的工具。

 

 

二、用监控系统解决一些实际问题

(一)用监控系统解决问题

1.黄金监控指标

image.png

Pigsty提供了约1200个指标,但最重要的就是这10个,这也是PG Cluster首屏上呈现出的关键指标。

数据库负值和饱和度是最重要的指标。按照Google SRE的监控最佳实践,这些指标可以分为4大类,饱和度、延迟、流量和错误,都具有很重要的参考价值。

 

2.PG Load  衡量数据库的负载程度

PG的负载是不是也可以采用类似于 CPU 利用率和机器负载的方式来定义?当然可以,而且这是一个极棒的主意。让我们先来考虑单进程情况下的PG负载,假设我们需要这样一个指标,当该PG进程完全空闲时负载因子为0,当该进程处于满载状态时负载为1(100%)。类比 CPU利用率的定义,我们可以使用单个PG进程处于活跃状态的时长占比来表示单个PG后端进程的利用率。

image.png

如上图所示,在一秒的统计周期内,PG处于活跃(执行查询或者执行事务)状态的时长为 0.6 秒,那么这一秒内的PG负载就是 60%。如果这个唯一的PG进程在整个统计周期中都处于忙碌状态,而且还有 0.4 秒的任务在排队,如那么就可以认为PG的负载为 140%。

image.png

对于并行场景,计算方法与多核CPU的利用率类似,首先把所有 PG进程在统计周期(1S)内处于活跃状态的时长累加,然后除以可用的PG进程/连接数,或者说可用并行数,即可得到PG本身的利用率指标,如上图所示。两个PG后端进程分别有 20Oms + 400ms 80Oms 的活跃时长,那么整体的负载水平为:

(0.2S+0.4S+0.8S)/1S/2=70 %

 

总结一下,某一段时间PG的负载可以定义为:

pg_load=pg_active_seconds/time_eroid /parallel

l  pg_active_seconds 是该时间段内所有 PG 进程处于活跃状态的时长之和。

l  time_peroid 是负载计算的统计周期,通常为1分钟, 5分钟, 15分钟,以及实时(小于10 秒)。

l  Para11el PostgreSQL 的可用并行数,后面会详细解释.

因为前两项之商实际上就是一段时间内的每秒活跃时长总数,因此这个公式进一步可以简化为活跃时长对时间的导数除以可用并行数,即:

rate(pg_active_seconds [time_peroid ])/parallel

time_peroid 通常是固定的常量(1,5, 15分钟),所以问题就是如何获取 PG进程活跃总时长pg_active_seconds这个指标,以及如何评估计算数据库可用并行数 max_ para11el了。

 

3.黄金指标: 数据库饱和度

数据库负载 pg load= pg conn busy time / avail CPU time

数据库饱和度saturation = max(cpu_ usage, pg_load)

饱和度用于反映数据库整体资源利用率理论上应当取所有饱和度指标的最大值(PGCPU,内存,网络,磁盘……)

PG Saturation = max(PG Load, CPU Usage, xxxUsage…)

实际应用中,饱和度指标取 PG Load CPU Usage的最大值作为饱和度,当数据库使用非独占式部署,其他应用占用CPU资源时,PG Saturation比单纯的PG Load更能反映数据库整体负载水位。

- record: pg:ins:saturation0 expr: pg:ins:load0 > node:ins:cpu_usage or node:ins:cpu_usage

- record: pg:ins:saturation1 expr: pg:ins:load1 > node:ins:cpu_usage or node:ins:cpu_usage

- record: pg:ins:saturation5 expr: pg:ins:load5 > node:ins:cpu_usage or node:ins:cpu_usage

- record: pg:ins:saturation15 expr: pg:ins:load15 > node:ins:cpu_usage or node:ins:cpu_usage

image.png

(二)慢查询定位优化

1.什么是慢查询?

慢查询是数据库的大敌,这里我们使用PG Bench 用例模拟一个慢查询。

ALTER TABLE pgbench_accounts DROP CONSTRAINT pgbench_accounts_pkey ;

该命令会移除pgbench_accounts 表上的主键,导致相关查询变慢,系统瞬间雪崩过载。

image.png

2.定位慢查询

定位集群RT异常,定位到具体的实例和查询。首先,使用PG Cluster面板定位慢查询所在的具体实例,这里以pg-test2为例,然后使用PG Query面板定位具体的慢查询:编号为 -6041100154778468427

该查询表现出:响应时间显著上升:17us升至 280ms QPS显著下降:从500下降到7,花费在该查询上的时间占比显著增加,可以确定就是这个查询变慢了。

image.png

3.发现异常

接下来,利用PG Stat Statements面板,根据查询ID定位慢查询的具体语句。查询以aid作为过滤条件查询pgbench_accounts 表查询变慢,大概率是这张表上的索引出了问题。

分析查询后提出猜想:该查询变慢是pgbench_accounts表上aid列缺少索引,下一步,查阅PG Table Detail面板,检查pgbench_accounts 表上的访问。定位潜在问题,找出顺序扫表,建立所需索引。

image.png

image.png

image.png

4.性能优化

我们尝试在pgbench_accounts表上为aid列添加索引,看看能否解决这个问题。

CREATE UNIQUE INDEX ON pgbench_accounts (aid);

可以看到,查询的响应时间与QPS已经恢复正常,整个集群的负载水平也恢复正常,报警也平息下来。精准衡量优化效果,直观展示工作成绩,真正做到数据驱动。

image.png

(三)定位系统故障

人工时时盯着指标,是一个非常辛苦的活,更好的选择是由机器来盯着这些指标,您设定好规则,机器发现这些指标超出异常范围的时候,自动给你触发发送报警,Pigsty里面提供了一系列的报警规则,同时报警事件也可以在监控系统的面板里面看到,通过这种条状甘特图的方式,我们可以看到哪一个时间段触发了报警事件,从而有的放矢的去排查。报警系统提供了很多计算好的衍生指标,所以不用再写特别复杂的表达式,可以直接用。

image.png

image.png

image.png

(四)系统水位评估

1.水位评估: 饱和度的历史分位点

除了直观的衡量实时的数据库负载水平,还可以用来计算数据库的水位,水位就是一个长期的资源使用量指标,通常来说,如果我们的某一个数据库集群长时间处于高负载状态,我们就是说它水位比较高,我们可能就要给它扩容。如果它长时间处于低水位状态,处于闲置,那么我们就要给他缩容。

 

扩容和缩容的依据就是所谓的水位,水位就是过去某一个时间段饱和度的百分位点。比如说现在采用的就是过去一天里面水位的99分位点,对于那种有周期性的负载来说,一天是一个比较好的这种衡量指标,如果您的业务周期性是一周或者一月,可以使用过去一周或者一月的饱和度数据,来计算它的99分位点或者99.99分位点,来评估集群的水位。比如这里某一套集群,它的水位是30%,那么就是意味着系统在过去一天的99%的时间里面,它的资源使用率都在30%以内,我们就认为它的水位是30%。像这样的指标对于评估长时间段系统的资源利用率很有用。评估资源利用率,就可以评估成本,及时的进行优化,这是一个典型应用。

 

 

三、How 如何部署一套监控系统?

(一)开源软件

参考文档:http://pigsty.cc

image.png

(二)公开文档与演示

l  上手

基于Vagrant,快速在本机拉起演示系统。

这篇文档将介绍如何在您手头的笔记本或PC机上,基于VagrantVirtualbox,拉起Pigsty演示沙箱。

本教程着眼于在本地单机创建Pigsty演示环境,如果您已经有可以用于部署的机器实例,可以参考部署教程

 

l  太长;不看

如果用户的本地计算机上已经安装有VagrantVirtualboxAnsible,那么只需要克隆并进入本项目后,依次执行以下命令即可:

image.png

正常情况下执行结果详见参考-标准流程

 

(三)快速上手

快速开始

git clone https://github.com/Vonng/pigsty

cd /tmp

make up

make ssh

sudo make

dns make init

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
2月前
|
存储 SQL 关系型数据库
MySQL - 深入理解锁机制和实战场景
MySQL - 深入理解锁机制和实战场景
|
2月前
|
存储 JSON 关系型数据库
《Postgresql实战》笔记(二)
《Postgresql实战》笔记(二)
34 0
|
3月前
|
关系型数据库 MySQL
电子好书发您分享《MySQL MGR 8.0高可用实战》
电子好书发您分享《MySQL MGR 8.0高可用实战》 电子好书发您分享《MySQL MGR 8.0高可用实战》
90 1
|
3月前
|
关系型数据库 MySQL 数据库
深入MySQL数据库进阶实战:性能优化、高可用性与安全性
深入MySQL数据库进阶实战:性能优化、高可用性与安全性
136 0
|
26天前
|
SQL 关系型数据库 MySQL
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
96 0
|
3月前
|
SQL 关系型数据库 MySQL
MySQL数据库基础与实战应用
MySQL数据库基础与实战应用
49 0
|
2天前
|
关系型数据库 MySQL 中间件
【MySQL实战笔记】07 | 行锁功过:怎么减少行锁对性能的影响?-02 死锁和死锁检测
【4月更文挑战第19天】在高并发环境下,死锁发生在多个线程间循环等待资源时,导致无限期等待。MySQL中,死锁可通过`innodb_lock_wait_timeout`参数设置超时或`innodb_deadlock_detect`开启死锁检测来解决。默认的50s超时可能不适用于在线服务,而频繁检测会消耗大量CPU。应对热点行更新引发的性能问题,可以暂时关闭死锁检测(风险是产生大量超时),控制并发度,或通过分散记录减少锁冲突,例如将数据分拆到多行以降低死锁概率。
18 1
|
5天前
|
SQL 关系型数据库 MySQL
Python与MySQL数据库交互:面试实战
【4月更文挑战第16天】本文介绍了Python与MySQL交互的面试重点,包括使用`mysql-connector-python`或`pymysql`连接数据库、执行SQL查询、异常处理、防止SQL注入、事务管理和ORM框架。易错点包括忘记关闭连接、忽视异常处理、硬编码SQL、忽略事务及过度依赖低效查询。通过理解这些问题和提供策略,可提升面试表现。
25 6
|
12天前
|
存储 关系型数据库 MySQL
【MySQL实战笔记】 04 | 深入浅出索引(上)-02
【4月更文挑战第9天】InnoDB数据库使用B+树作为索引模型,其中主键索引的叶子节点存储完整行数据,非主键索引则存储主键值。主键查询只需搜索一棵树,而非主键查询需两次搜索,因此推荐使用主键查询以提高效率。在插入新值时,B+树需要维护有序性,可能导致数据页分裂影响性能。自增主键在插入时可避免数据挪动和页分裂,且占用存储空间小,通常更为理想。然而,如果场景仅需唯一索引,可直接设为主键以减少查询步骤。
15 1
【MySQL实战笔记】 04 | 深入浅出索引(上)-02
|
14天前
|
存储 SQL 关系型数据库
【MySQL实战笔记】03.事务隔离:为什么你改了我还看不见?-02
【4月更文挑战第7天】数据库通过视图实现事务隔离,不同隔离级别如读未提交、读已提交、可重复读和串行化采用不同策略。以可重复读为例,MySQL使用多版本并发控制(MVCC),每个事务有其独立的视图。回滚日志在无更早视图时被删除。长事务可能导致大量存储占用,应避免。事务启动可显式用`begin`或设置`autocommit=0`,但后者可能意外开启长事务。建议使用`autocommit=1`并显式管理事务,若需减少交互,可使用`commit work and chain`。
30 5

相关产品

  • 云原生数据库 PolarDB