首页 文章 精选 留言 我的

精选列表

搜索[软件构建],共10000篇文章
优秀的个人博客,低调大师

递推的思维构建与技巧实现

递推是一种用若干步可重复运算来解决复杂问题的方法。 1.一维递推 1.1 问题描述 有一个n层的楼梯,每次只可以向上爬1层或者2层,问爬完n层共有多少种不同的方式呢? 1.2 分析 设f(n)表示n层楼总共不同的方式。 假设此时位于第i层,因为每次只能爬1层或2层,所以到第i层只有2种方式。 从第i-1层爬上来。 从第i-2层爬上来。 所以得到递推公式为f(n)=f(n-1)+f(n-2)。前2项之和等于第3项,其实就是斐波那契数列,1,1,2,3,5,8,13,21... 1.3 代码实现 f[0]=1;f[1]=1; for(inti=2;i<n;i++){ f[i]=f[i-1]+f[i-2] } cout<<f[n-1]<<endl; 1.4 空间优化 每一步的递推只与前2步有关,所以只需要记录前2步的方案数,用滚动数组,而不需要开O(n)的空间。手动赋值 intf[3]; f[0]=1; f[1]=1; for(inti=2;i<10;++i){ f[2]=f[1]+f[0]; f[0]=f[1]; f[1]=f[2]; cout<<f[2]<<endl; } 取模滚动 intf[3]; f[0]=1; f[1]=1; for(inti=2;i<10;++i){ f[i%3]=f[(i-1)%3]+f[(i-2)%3]; cout<<f[i%3]<<endl; } 如果只与前一个状态有关,比如f[n]=f[n-1]+1,可以用0,1滚动,这个在动态规划中会比较常用。 intf[2],t=0; f[0]=1; for(inti=2;i<10;++i){ t=1-t; f[t]=f[1-t]+1; cout<<f[t]<<endl; } 递推和动态规划最大的区别:递推的每一步是所有方案数的加和,而动态规划在每一步递推中,需要用来选取一个最优策略。本质其实都是通过重复的小规模子问题推导出大规模的结果。 1.5 时间优化 斐波那契数列递推公式很简单,但数据很大时,效率就比较低,因为递推是O(n)复杂度。 通过矩阵公式变换可将加法变为乘法 如下将递推公式放入矩阵: 假设:则: 可以通过矩阵幂乘快速求出,时间复杂度为,再带入上式即可获得数列值。 具体可以看另一篇递推优化-矩阵幂乘 2.多维递推 2.1 问题描述 从原点出发,每次只能向东,向北,向西走,且不能走已经走过的地方,问走n步共有多少种不同的方式呢? 2.2 分析 假设已经走到第i步,因为不能走已经走过的地方,那这一步能走的方式只会与上一步有关。因为每次走一步,要保证不走回头路,就保证不走上一步走过的地方就行了。 每次有3个选择,即向东,向北,向西。 第i-1步向东走,那么第步只能向北、向东。 第i-1步向西走,那么第步只能向北、向西。 第i-1步向北走,那么第步可以向北、向东,向西。 一维的f[n]只能记录一个总数,而不能记录状态,所以要再多一维记录上一步走的状态。 设f[n][0], f[n][1], f[n][2]分别表示:第步向东、向西、向北走总共不同的方式。 则有如下递推关系: f[n][0] = f[n - 1][0] + f[n - 1][2]; f[n][1] = f[n - 1][1] + f[n - 1][2]; f[n][2] = f[n - 1][0] + f[n - 1][1] + f[n - 1][2]; 2.3 代码实现 intf[100][3]={0}; f[0][0]=1; f[0][1]=1; f[0][2]=1; for(inti=1;i<n;++i){ f[i][0]=f[i-1][0]+f[i-1][2]; f[i][1]=f[i-1][1]+f[i-1][2]; f[i][2]=f[i-1][0]+f[i-1][1]+f[i-1][2]; } cout<<f[n-1][0]+f[n-1][1]+f[n-1][2]<<endl; 2.4 进一步优化 设第n步的总方案数为s[n], s[n]=f[n][0]+f[n][1]+f[n][2]。 s[n]=2f[n-1][0]+2f[n-1][1]+3f[n-1][2]。 s[n]=2s[n-1]+f[n-1][2]。 而f[n-1][2]=f[n-2][0]+f[n-2][1]+f[n-2][2]=s[n-2]。 得s[n]=2s[n-1]+s[n-2]。 所以对公式变形,也可以通过一维的方式完成递推,但这个关系无法直接通过建模构造出来。 3.图递推 3.1 问题描述 在一个的二维地图中,一个人从左上角走到右下角,每次只能向右或者向下走,问到终点共有多少种不同的方式呢? 3.2 分析 假设已经位于某个位置,因为只能向右或者向下走,那上一步只能从上或者从左走过来。 设f[i][j]表示走到坐标总共的方案数。 则f[i][j]=f[i-1][j]+f[i][j-]。 3.3 代码实现 intf[10][10]={0}; f[0][0]=1; for(inti=0;i<n;++i){ for(intj=0;j<m;++j){ if(i-1>=0){ f[i][j]+=f[i-1][j]; } if(j-1>=0){ f[i][j]+=f[i][j-1]; } } } 3.4 进一步思考 要到达终点,一定要向下走n-1步,向右走m-1步。 把每一步组合在一起来看,其实问题就等价于在n+m-2步中选择n-1步向下走,或者选择m-1步向右走,通过排列组合公式就可以直接得到结果。 4.状态压缩递推 4.1 问题描述 在一个的棋盘中放置棋子,有一些地方不能放置。要求放置棋子时任意2个棋子不能在同1行或同1列,问放置k个棋子有多少种不同的方式呢? 4.2 分析 对于每1个位置,只会有2种情况,就是放或不放。在数据规模不大的情况下可以用DFS(深度优先搜索)枚举所有的情况就可以了。 那有没有更好的方法呢? 这个最终是要求方案总数,而不需要考虑每一步是否需要择优,所以是符合递推模型,接下来就是怎么找出递推关系。 先分析一些隐含的规律,把问题理得更清晰: 每1行或者每1列都只能放置1个棋子,所以按每一行来枚举放置方法。 在尝试第i行时,每一个位置(i,j)能不能放置,不只是跟上一行有关,而是跟之前的所有行都有关。这就说明需要记录之前放置的方法,也就是状态。 那怎么记录之前放置的方案状态呢,这就要用到状态压缩。状态压缩:本质就是用二进制记录对应位置的2种状态,0表示不放,1表示放。 对于n个位置,就可以用个十进制数来表示所有放置的方案。 继续回到上面的问题,在尝试第i行时,能否放置跟之前的i-1行都有关,意味着需要记录之前所有行放置的状态。 但看下面2种情况,图1和图2对于在尝试放置第3行时,其实是等价的,前2列都是不能放置。也就是说这2种方案数是可以直接合并的,因为每1列也只能放一个,所以放置的方案状态也可以直接合并成一行。 用f[i][j]表示前i行,放置方案为j总共的方案数。 第0行的过程如下: 第1行的过程如下: 如此递推求出n行,种放置方案的总数,。因为只能放置k个棋子,所以在种放置方案中找出刚好是k个棋子的方案,也就是对应的状态j转化为二进制时,有k个1。 4.3 二进制包含1的个数 目标数n,通过n&(n-1)运算,包含多少个1就刚好进行多少次该运算,可以快速求出1的个数。 4.4 代码实现 计算数n中包含1的个数 intcountOne(intn){ inttotal=0; while(n>0){ total++; n&=n-1; } returntotal; } 变量定义及初始化 inti,n,k,line[8],f[2][256],num[256]; for(i=0;i<256;++i)num[i]=countOne(i); memset(f,0,2*256*4); f[0][0]=1; intj,c,now=0; //棋盘读入 for(i=0;i<n;++i){ intt=0; for(intj=0;j<n;++j){ t<<=1; cin>>ch; if(ch=='.')t+=1; } line[i]=t; } 核心递推 for(i=0;i<n;++i){ now=1-now; for(j=0;j<256;++j) if(num[j]<=k){ //第i行不放棋子 f[now][j]+=f[1-now][j]; //第i行放棋子 for(c=0;c<n;++c){ if((j&1<<c)==0&&(line[i]&1<<c)==0){ f[now][j|1<<c]+=f[1-now][j]; } } } } //枚举所有包含k个棋子的方案数 intans=0; for(i=0;i<256;++i){ if(num[i]==k){ ans+=f[now][i]; } } cout<<ans<<endl; 5.总结 递推最重要的思想,就是通过每一小步,找出与下一步之间的关系。关键在于思考问题的本质,对问题进行建模。常用f[i][j][k]等类似数组来记录,多一维就可以多记录一维状态信息,要思考上一步真正有多少个因素会影响当前步,那一般这些就是一定要记录的信息。 关注我,涨知识,微信公众号:几何思维 往期精彩回顾 蚂蚁走迷宫 老鼠与毒药 通过6人介绍可以认识世界上任何一个人?

优秀的个人博客,低调大师

构建高大上的黑盒监控平台

概述 在监控体系里面,通常我们把监控分为:白盒监控和黑盒监控: 黑盒监控:主要关注的现象,一般都是正在发生的东西,例如出现一个告警,业务接口不正常,那么这种监控就是站在用户的角度能看到的监控,重点在于能对正在发生的故障进行告警。 白盒监控:主要关注的是原因,也就是系统内部暴露的一些指标,例如redis的info中显示redis slave down,这个就是redis info显示的一个内部的指标,重点在于原因,可能是在黑盒监控中看到redis down,而查看内部信息的时候,显示redis port is refused connection。 白盒监控:有很多种,有中间件,有存储,有web服务器例如redis可以使用info暴露内部的指标信息;例如mysql可以使用show variables暴露内部指标信息;例如nginx可以使用nginx_status来暴露内部信息,系统业务指标可以通过埋点或者命令进行采集。 Blackbox Exporter 在前面的知识中,我们介绍Prometheus下如何进行白盒监控:我们监控主机的资源用量、容器的运行状态、数据库中间件的运行数据,通过采集相关指标来预测我们的服务健康状态。在黑盒监控方面。Blackbox Exporter是Prometheus社区提供的官方黑盒监控解决方案,其允许用户通过:HTTP、HTTPS、DNS、TCP以及ICMP的方式对网络进行探测。 Blackbox_exporter 应用场景 HTTP 测试定义 Request Header 信息判断 Http status / Http Respones Header / Http Body 内容 TCP 测试业务组件端口状态监听应用层协议定义与监听 ICMP 测试主机探活机制 POST 测试接口联通性 SSL 证书过期时间 结合grafana 生成的相关模板: 1、首先看下我们这边的相关图表,门户多项指标与ssl监控: 2、线路监控: 3、接口状态监控: Blackbox Exporter 部署: 1、安装Exporter: [root@cinder1 src]# wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.16.0/blackbox_exporter-0.16.0.linux-amd64.tar.gz [root@cinder1 src]#tar -zxvf blackbox_exporter-0.16.0.linux-amd64.tar.gz -C /usr/local [root@cinder1 src]#mv /usr/local/blackbox_exporter-0.16.0.linux-amd64 /usr/local/blackbox_exporter 2、添加到启动项: [root@cinder1 src]# cat /etc/systemd/system/blackbox_exporter.service [Unit] Description=blackbox_exporter After=network.target [Service] WorkingDirectory=/usr/local/blackbox ExecStart=/usr/local/blackbox/blackbox_exporter \ --config.file=/usr/local/blackbox/blackbox.yml [Install] WantedBy=multi-user.target 3、检测是否正常启动: [root@cinder1 src]# ss -tunlp|grep 9115 tcp LISTEN 0 128 :::9115 :::* users:(("blackbox_export",pid=2517722,fd=3)) icmp监控 通过icmp 这个指标的采集,我们可以确认到对方的线路是否有问题。这个也是监控里面比较重要的一个环节。我们要了解全国各地到我们机房的线路有哪条有问题我们总结了两种方案:1、全国各地各节点ping 和访问数据采集。这种类似听云运营商有提供这类服务,但是要花钱。2、我现在用的方法就是:找各地测试ping 的节点,我们从机房主动ping 看是否到哪个线路有故障,下面我们开始。 一、prometheus 添加相关监控,Blackbox 使用默认配置启动即可: - job_name: "icmp_ping" metrics_path: /probe params: module: [icmp] # 使用icmp模块 file_sd_configs: - refresh_interval: 10s files: - "/home/prometheus/conf/ping_status*.yml" #具体的配置文件 relabel_configs: - source_labels: [__address__] regex: (.*)(:80)? target_label: __param_target replacement: ${1} - source_labels: [__param_target] target_label: instance - source_labels: [__param_target] regex: (.*) target_label: ping replacement: ${1} - source_labels: [] regex: .* target_label: __address__ replacement: 192.168.1.14:9115 二、相关ping节点配置: [root@cinder1 conf]# cat ping_status.yml - targets: ['220.181.38.150','14.215.177.39','180.101.49.12','14.215.177.39','180.101.49.11','14.215.177.38','14.215.177.38'] labels: group: '一线城市-电信网络监控' - targets: ['112.80.248.75','163.177.151.109','61.135.169.125','163.177.151.110','180.101.49.11','61.135.169.121','180.101.49.11'] labels: group: '一线城市-联通网络监控' - targets: ['183.232.231.172','36.152.44.95','182.61.200.6','36.152.44.96','220.181.38.149'] labels: group: '一线城市-移动网络监控' #这些数据是从全国各地ping 网站进行采集,大家可以从那些网站获取 三、添加grafana 这个grafana是自己定义的,看到网上没有就自己定义了一个。大家可以从github上下载,再看看效果: http 相关指标监控: 一、prometheus 配置http_get访问: - job_name: "blackbox" metrics_path: /probe params: module: [http_2xx] #使用http模块 file_sd_configs: - refresh_interval: 1m files: - "/home/prometheus/conf/blackbox*.yml" relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.14:9115 二、相关配置文件,类似举例如下: [root@cinder1 conf]# cat /home/prometheus/conf/blackbox-dis.yml - targets: - https://www.zhibo8.cc - https://www.baidu.com #配置相关URL 三、添加grafana模板: 可以选择模板的9965模板,这个模板我们也看到前面的,提供了相关的ssl 过期检测。 接口get请求检测 一、prometheus 配置,其实跟我们之前的配置一样,我们直接看配置文件: - job_name: "check_get" metrics_path: /probe params: module: [http_2xx] # Look for a HTTP 200 response. file_sd_configs: - refresh_interval: 1m files: - "/home/prometheus/conf/service_get.yml" relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.14:9115 二、相关接口配置参考: [root@cinder1 conf]# cat service_get.yml - targets: - http://10.10.1.123:10000/pmkb/atc_tcbi - http://10.10.1.123:10000/pmkb/get_ship_lock_count - http://10.10.1.123:10000/pmkb/get_terminal_count_by_city - http://10.10.1.123:10000/pmkb/get_terminal_monitor?industry=1 - http://10.10.1.123:10000/pmkb/get_terminal_comparison?industry=1 - http://10.10.1.123:10000/pmkb/get_terminal_city_count_industry?industry=1 - http://10.10.1.123:10000/pmkb/industry_stat?industry=1 - http://10.10.1.123:10000/pmkb/get_company_car_count?industry=1 - http://10.10.1.123:10000/pmkb/get_terminal_month_countbyi?industry=1 labels: group: 'service' 三、grafana 和前面一样自己订制的,可以从github上下载。 接口post 请求状态检测: 一、这里首先我们要改一下post 相关接口的blackbox.yml配置,我们自己定义一个模块: [root@cinder1 blackbox]# cat blackbox.yml modules: http_2xx: prober: http http_post_2xx: #这个模块名称可以自己定义 prober: http http: method: POST headers: Content-Type: application/json #添加头部 body: '{"username":"admin","password":"123456"}' #发送的相关数据,这里我们以登录接口为例 二、添加到prometheus: - job_name: "check_service" metrics_path: /probe params: module: [http_post_2xx] # 这里要对应配置文件里,定义的模块 file_sd_configs: - refresh_interval: 1m files: - "/home/prometheus/conf/service_post.yml" relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.14:9115 三、相关配置: [root@cinder1 conf]# cat service_post.yml - targets: - http://10.2.4.103:5000/devops/api/v1.0/login labels: group: 'service' 四、添加grafana相关配置,这个也是自己定义的,可以从github上下载。 tcp端口状态检测: 个人理解的是这个跟telnet差不多都是检测端口是否在线 一、prometheus 配置: - job_name: 'port_status' metrics_path: /probe params: module: [tcp_connect] #使用tcp模块 static_configs: - targets: ['10.10.1.35:8068','10.10.1.35:8069'] #对应主机接口 labels: instance: 'port_status' group: 'tcp' relabel_configs: - source_labels: [__address__] target_label: __param_target - target_label: __address__ replacement: 192.168.1.14:9115 二、图表: 图表可以集成到前面的grafana 9965模板: 告警规则定义: 一、业务正常性:icmp、tcp、http、post 监测是否正常可以观察probe_success 这一指标probe_success == 0 ##联通性异常probe_success == 1 ##联通性正常告警也是判断这个指标是否等于0,如等于0 则触发异常报警 二、通过http模块我们可以获取证书的过期时间,可以根据过期时间添加相关告警 probe_ssl_earliest_cert_expiry :可以查询证书到期时间。 #经过单位转换我们可以得到一下,按天来计算:(probe_ssl_earliest_cert_expiry - time())/86400 三、所以我们结合上面的配置可以定制如下告警规则 [root@cinder1 rules]# cat blackbox.yml groups: - name: blackbox_network_stats rules: - alert: blackbox_network_stats expr: probe_success == 0 for: 1m labels: severity: critical annotations: summary: "接口/主机/端口 {{ $labels.instance }} 无法联通" description: "请尽快检测" ##ssl检测 [root@cinder1 rules]# cat ssl.yml groups: - name: check_ssl_status rules: - alert: "ssl证书过期警告" expr: (probe_ssl_earliest_cert_expiry - time())/86400 <30 for: 1h labels: severity: warn annotations: description: '域名{{$labels.instance}}的证书还有{{ printf "%.1f" $value }}天就过期了,请尽快更新证书' summary: "ssl证书过期警告" 四、重启完成之后我们可以登录web界面查看下: 五、我们发现有个接口已经存在问题,这个时候我们也收到了一条相应的微信告警: 总结: 黑盒监控相较于白盒监控最大的不同在于黑盒监控是以故障为导向当故障发生时,黑盒监控能快速发现故障,所以我们监控时候以粒度比较细的,如端口、接口、线路等进行监控。通过Prometheus Blackbox Exporter可以快速实现和定制我们很多相关策略,大家可以按照上述流程测试一下。

优秀的个人博客,低调大师

构建高大上的MySQL监控平台

概述 对于MySQL的监控平台,相信大家实现起来有很多了:基于天兔的监控,还有基于zabbix相关的二次开发。相信很多同行都应该已经开始玩起来了。我这边的选型是prometheus + granafa的实现方式。简而言之就是我现在的生产环境使用的是prometheus,还有就是granafa满足的我的日常工作需要。在入门的简介和安装,大家可以参考这里:https://blog.51cto.com/cloumn/detail/77 1、首先看下我们的监控效果、mysql主从 2、mysql状态: 3、缓冲池状态: exporter 相关部署 1、安装exporter [root@controller2 opt]# https://github.com/prometheus/mysqld_exporter/releases/download/v0.10.0/mysqld_exporter-0.10.0.linux-amd64.tar.gz [root@controller2 opt]# tar -xf mysqld_exporter-0.10.0.linux-amd64.tar.gz 2、添加mysql 账户: GRANT SELECT, PROCESS, SUPER, REPLICATION CLIENT, RELOAD ON *.* TO 'exporter'@'%' IDENTIFIED BY 'localhost'; flush privileges; 3、编辑配置文件: [root@controller2 mysqld_exporter-0.10.0.linux-amd64]# cat /opt/mysqld_exporter-0.10.0.linux-amd64/.my.cnf [client] user=exporter password=123456 4、设置配置文件: [root@controller2 mysqld_exporter-0.10.0.linux-amd64]# cat /etc/systemd/system/mysql_exporter.service [Unit] Description=mysql Monitoring System Documentation=mysql Monitoring System [Service] ExecStart=/opt/mysqld_exporter-0.10.0.linux-amd64/mysqld_exporter \ -collect.info_schema.processlist \ -collect.info_schema.innodb_tablespaces \ -collect.info_schema.innodb_metrics \ -collect.perf_schema.tableiowaits \ -collect.perf_schema.indexiowaits \ -collect.perf_schema.tablelocks \ -collect.engine_innodb_status \ -collect.perf_schema.file_events \ -collect.info_schema.processlist \ -collect.binlog_size \ -collect.info_schema.clientstats \ -collect.perf_schema.eventswaits \ -config.my-cnf=/opt/mysqld_exporter-0.10.0.linux-amd64/.my.cnf [Install] WantedBy=multi-user.target 5、添加配置到prometheus server - job_name: 'mysql' static_configs: - targets: ['192.168.1.11:9104','192.168.1.12:9104'] 6、测试看有没有返回数值: http://192.168.1.12:9104/metrics 正常我们通过mysql_up可以查询倒mysql监控是否已经生效,是否起起来 #HELP mysql_up Whether the MySQL server is up. #TYPE mysql_up gauge mysql_up 1 监控相关指标 在做任何一个东西监控的时候,我们要时刻明白我们要监控的是什么,指标是啥才能更好的去监控我们的服务,在mysql里面我们通常可以通过一下指标去衡量mysql的运行情况:mysql主从运行情况、查询吞吐量、慢查询情况、连接数情况、缓冲池使用情况以及查询执行性能等。 主从复制运行指标: 1、主从复制线程监控: 大部分情况下,很多企业使用的都是主从复制的环境,监控两个线程是非常重要的,在mysql里面我们通常是通过命令: MariaDB [(none)]> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.16.1.1 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000045 Read_Master_Log_Pos: 72904854 Relay_Log_File: mariadb-relay-bin.000127 Relay_Log_Pos: 72905142 Relay_Master_Log_File: mysql-bin.000045 Slave_IO_Running: Yes Slave_SQL_Running: Yes #Slave_IO_Running、Slave_SQL_Running两个线程正常那么说明我们的复制集群是健康状态的。 MySQLD Exporter中返回的样本数据中通过mysql_slave_status_slave_sql_running来获取主从集群的健康状况。 # HELP mysql_slave_status_slave_sql_running Generic metric from SHOW SLAVE STATUS. # TYPE mysql_slave_status_slave_sql_running untyped mysql_slave_status_slave_sql_running{channel_name="",connection_name="",master_host="172.16.1.1",master_uuid=""} 1 2、主从复制落后时间: 在使用show slave status 里面还有一个关键的参数Seconds_Behind_Master。Seconds_Behind_Master表示slave上SQL thread与IO thread之间的延迟,我们都知道在MySQL的复制环境中,slave先从master上将binlog拉取到本地(通过IO thread),然后通过SQL thread将binlog重放,而Seconds_Behind_Master表示本地relaylog中未被执行完的那部分的差值。所以如果slave拉取到本地的relaylog(实际上就是binlog,只是在slave上习惯称呼relaylog而已)都执行完,此时通过show slave status看到的会是0 Seconds_Behind_Master: 0 MySQLD Exporter中返回的样本数据中通过mysql_slave_status_seconds_behind_master 来获取相关状态。 # HELP mysql_slave_status_seconds_behind_master Generic metric from SHOW SLAVE STATUS. # TYPE mysql_slave_status_seconds_behind_master untyped mysql_slave_status_seconds_behind_master{channel_name="",connection_name="",master_host="172.16.1.1",master_uuid=""} 0 查询吞吐量: 说到吞吐量,那么我们如何从那方面来衡量呢?通常来说我们可以根据mysql 的插入、查询、删除、更新等操作来 为了获取吞吐量,MySQL 有一个名为Questions的内部计数器(根据 MySQL 用语,这是一个服务器状态变量),客户端每发送一个查询语句,其值就会加一。由Questions指标带来的以客户端为中心的视角常常比相关的Queries计数器更容易解释。作为存储程序的一部分,后者也会计算已执行语句的数量,以及诸如PREPARE和DEALLOCATE PREPARE指令运行的次数,作为服务器端预处理语句的一部分。可以通过命令来查询: MariaDB [(none)]> SHOW GLOBAL STATUS LIKE "Questions"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Questions | 15071 | +---------------+-------+ MySQLD Exporter中返回的样本数据中通过mysql_global_status_questions反映当前Questions计数器的大小: # HELP mysql_global_status_questions Generic metric from SHOW GLOBAL STATUS. # TYPE mysql_global_status_questions untyped mysql_global_status_questions 13253 当然由于prometheus 具有非常丰富的查询语言,我们可以通过这个累加的计数器来查询某一短时间内的查询增长率情况,可以做相关的阈值告警处理、例如一下查询2分钟时间内的查询情况: rate(mysql_global_status_questions[2m]) 当然上面是总量,我们可以分别从监控读、写指令的分解情况,从而更好地理解数据库的工作负载、找到可能的瓶颈。通常,通常,读取查询会由Com_select指标抓取,而写入查询则可能增加三个状态变量中某一个的值,这取决于具体的指令: Writes=Com_insert+Com_update+Com_delete 下面我们通过命令获取插入的情况: MariaDB [(none)]> SHOW GLOBAL STATUS LIKE "Com_insert"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Com_insert | 10578 | +---------------+-------+ 从MySQLD Exporter的/metrics返回的监控样本中,可以通过global_status_commands_total获取当前实例各类指令执行的次数: # HELP mysql_global_status_commands_total Total number of executed MySQL commands. # TYPE mysql_global_status_commands_total counter mysql_global_status_commands_total{command="create_trigger"} 0 mysql_global_status_commands_total{command="create_udf"} 0 mysql_global_status_commands_total{command="create_user"} 1 mysql_global_status_commands_total{command="create_view"} 0 mysql_global_status_commands_total{command="dealloc_sql"} 0 mysql_global_status_commands_total{command="delete"} 3369 mysql_global_status_commands_total{command="delete_multi"} 0 慢查询性能 查询性能方面,慢查询也是查询告警的一个重要的指标。MySQL还提供了一个Slow_queries的计数器,当查询的执行时间超过long_query_time的值后,计数器就会+1,其默认值为10秒,可以通过以下指令在MySQL中查询当前long_query_time的设置: MariaDB [(none)]> SHOW VARIABLES LIKE 'long_query_time'; +-----------------+-----------+ | Variable_name | Value | +-----------------+-----------+ | long_query_time | 10.000000 | +-----------------+-----------+ 1 row in set (0.00 sec) #当然我们也可以修改时间 MariaDB [(none)]> SET GLOBAL long_query_time = 5; Query OK, 0 rows affected (0.00 sec) 然后我们而已通过sql语言查询MySQL实例中Slow_queries的数量: MariaDB [(none)]> SHOW GLOBAL STATUS LIKE "Slow_queries"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Slow_queries | 0 | +---------------+-------+ 1 row in set (0.00 sec) MySQLD Exporter返回的样本数据中,通过mysql_global_status_slow_queries指标展示当前的Slow_queries的值: # HELP mysql_global_status_slow_queries Generic metric from SHOW GLOBAL STATUS. # TYPE mysql_global_status_slow_queries untyped mysql_global_status_slow_queries 0 同样的,更具根据Prometheus 慢查询语句我们也可以查询倒他某段时间内的增长率: rate(mysql_global_status_slow_queries[5m]) 连接数监控 监控客户端连接情况相当重要,因为一旦可用连接耗尽,新的客户端连接就会遭到拒绝。MySQL 默认的连接数限制为 151。 MariaDB [(none)]> SHOW VARIABLES LIKE 'max_connections'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 151 | +-----------------+-------+ 当然我们可以修改配置文件的形式来增加这个数值。与之对应的就是当前连接数量,当我们当前连接出来超过系统设置的最大值之后常会出现我们看到的Too many connections(连接数过多),下面我查找一下当前连接数: MariaDB [(none)]> SHOW GLOBAL STATUS LIKE "Threads_connected"; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | Threads_connected | 41 | +-------------------+------- 当然mysql 还提供Threads_running这个指标,帮助你分隔在任意时间正在积极处理查询的线程与那些虽然可用但是闲置的连接。 MariaDB [(none)]> SHOW GLOBAL STATUS LIKE "Threads_running"; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | Threads_running | 10 | +-----------------+-------+ 如果服务器真的达到max_connections限制,它就会开始拒绝新的连接。在这种情况下,Connection_errors_max_connections指标就会开始增加,同时,追踪所有失败连接尝试的Aborted_connects指标也会开始增加。 MySQLD Exporter返回的样本数据中: # HELP mysql_global_variables_max_connections Generic gauge metric from SHOW GLOBAL VARIABLES. # TYPE mysql_global_variables_max_connections gauge mysql_global_variables_max_connections 151 #表示最大连接数 # HELP mysql_global_status_threads_connected Generic metric from SHOW GLOBAL STATUS. # TYPE mysql_global_status_threads_connected untyped mysql_global_status_threads_connected 41 #表示当前的连接数 # HELP mysql_global_status_threads_running Generic metric from SHOW GLOBAL STATUS. # TYPE mysql_global_status_threads_running untyped mysql_global_status_threads_running 1 #表示当前活跃的连接数 # HELP mysql_global_status_aborted_connects Generic metric from SHOW GLOBAL STATUS. # TYPE mysql_global_status_aborted_connects untyped mysql_global_status_aborted_connects 31 #累计所有的连接数 # HELP mysql_global_status_connection_errors_total Total number of MySQL connection errors. # TYPE mysql_global_status_connection_errors_total counter mysql_global_status_connection_errors_total{error="internal"} 0 #服务器内部引起的错误、如内存硬盘等 mysql_global_status_connection_errors_total{error="max_connections"} 0 #超出连接处引起的错误 当然根据prom表达式,我们可以查询当前剩余可用的连接数: mysql_global_variables_max_connections - mysql_global_status_threads_connected 查询mysq拒绝连接数 mysql_global_status_aborted_connects 缓冲池情况: MySQL 默认的存储引擎 InnoDB 使用了一片称为缓冲池的内存区域,用于缓存数据表与索引的数据。缓冲池指标属于资源指标,而非工作指标,前者更多地用于调查(而非检测)性能问题。如果数据库性能开始下滑,而磁盘 I/O 在不断攀升,扩大缓冲池往往能带来性能回升。默认设置下,缓冲池的大小通常相对较小,为 128MiB。不过,MySQL 建议可将其扩大至专用数据库服务器物理内存的 80% 大小。我们可以查看一下: MariaDB [(none)]> show global variables like 'innodb_buffer_pool_size'; +-------------------------+-----------+ | Variable_name | Value | +-------------------------+-----------+ | innodb_buffer_pool_size | 134217728 | +-------------------------+-----------+ MySQLD Exporter返回的样本数据中,使用mysql_global_variables_innodb_buffer_pool_size来表示。 # HELP mysql_global_variables_innodb_buffer_pool_size Generic gauge metric from SHOW GLOBAL VARIABLES. # TYPE mysql_global_variables_innodb_buffer_pool_size gauge mysql_global_variables_innodb_buffer_pool_size 1.34217728e+08 Innodb_buffer_pool_read_requests记录了正常从缓冲池读取数据的请求数量。可以通过以下指令查看 MariaDB [(none)]> SHOW GLOBAL STATUS LIKE "Innodb_buffer_pool_read_requests"; +----------------------------------+-------------+ | Variable_name | Value | +----------------------------------+-------------+ | Innodb_buffer_pool_read_requests | 38465 | +----------------------------------+-------------+ MySQLD Exporter返回的样本数据中,使用mysql_global_status_innodb_buffer_pool_read_requests来表示。 # HELP mysql_global_status_innodb_buffer_pool_read_requests Generic metric from SHOW GLOBAL STATUS. # TYPE mysql_global_status_innodb_buffer_pool_read_requests untyped mysql_global_status_innodb_buffer_pool_read_requests 2.7711547168e+10 当缓冲池无法满足时,MySQL只能从磁盘中读取数据。Innodb_buffer_pool_reads即记录了从磁盘读取数据的请求数量。通常来说从内存中读取数据的速度要比从磁盘中读取快很多,因此,如果Innodb_buffer_pool_reads的值开始增加,可能意味着数据库的性能有问题。 可以通过以下只能查看Innodb_buffer_pool_reads的数量 MariaDB [(none)]> SHOW GLOBAL STATUS LIKE "Innodb_buffer_pool_reads"; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | Innodb_buffer_pool_reads | 138 | +--------------------------+-------+ 1 row in set (0.00 sec) MySQLD Exporter返回的样本数据中,使用mysql_global_status_innodb_buffer_pool_read_requests来表示。 # HELP mysql_global_status_innodb_buffer_pool_reads Generic metric from SHOW GLOBAL STATUS. # TYPE mysql_global_status_innodb_buffer_pool_reads untyped mysql_global_status_innodb_buffer_pool_reads 138 通过以上监控指标,以及实际监控的场景,我们可以利用PromQL快速建立多个监控项。可以查看两分钟内读取磁盘的增长率的增长率: rate(mysql_global_status_innodb_buffer_pool_reads[2m]) 官方模板ID 上面是我们简单列举的一些指标,下面我们使用granafa给 MySQLD_Exporter添加监控图表: 主从主群监控(模板7371): 相关mysql 状态监控7362: 缓冲池状态7365: 简单的告警规则 除了相关模板之外,没有告警规则那么我们的监控就是不完美的,下面列一下我们的监控告警规则 groups: - name: MySQL-rules rules: - alert: MySQL Status expr: up == 0 for: 5s labels: severity: warning annotations: summary: "{{$labels.instance}}: MySQL has stop !!!" description: "检测MySQL数据库运行状态" - alert: MySQL Slave IO Thread Status expr: mysql_slave_status_slave_io_running == 0 for: 5s labels: severity: warning annotations: summary: "{{$labels.instance}}: MySQL Slave IO Thread has stop !!!" description: "检测MySQL主从IO线程运行状态" - alert: MySQL Slave SQL Thread Status expr: mysql_slave_status_slave_sql_running == 0 for: 5s labels: severity: warning annotations: summary: "{{$labels.instance}}: MySQL Slave SQL Thread has stop !!!" description: "检测MySQL主从SQL线程运行状态" - alert: MySQL Slave Delay Status expr: mysql_slave_status_sql_delay == 30 for: 5s labels: severity: warning annotations: summary: "{{$labels.instance}}: MySQL Slave Delay has more than 30s !!!" description: "检测MySQL主从延时状态" - alert: Mysql_Too_Many_Connections expr: rate(mysql_global_status_threads_connected[5m]) > 200 for: 2m labels: severity: warning annotations: summary: "{{$labels.instance}}: 连接数过多" description: "{{$labels.instance}}: 连接数过多,请处理 ,(current value is: {{ $value }})" - alert: Mysql_Too_Many_slow_queries expr: rate(mysql_global_status_slow_queries[5m]) > 3 for: 2m labels: severity: warning annotations: summary: "{{$labels.instance}}: 慢查询有点多,请检查处理" description: "{{$labels.instance}}: Mysql slow_queries is more than 3 per second ,(current value is: {{ $value }})" 2、添加规则到prometheus: rule_files: - "rules/*.yml" 3、打开web ui我们可以看到规则生效了: 总结 到处监控mysql的相关状态已经完成,大家可以根据mysql更多的监控指标去完善自己的监控,当然这一套就是我用在线上环境的,可以参考参考。

优秀的个人博客,低调大师

Redis专题(1):构建知识图谱

场景:Redis面试 (图片来源于网络) 面试官: 我看到你的简历上说你熟练使用Redis,那么你讲一下Redis是干嘛用的? 小明: (心中窃喜,Redis不就是缓存吗?)Redis主要用作缓存,通过内存高效地存储非持久化数据。 面试官: Redis可以用作持久化的存储吗? 小明 :嗯...应该可以吧... 面试官: 那Redis怎么进行持久化操作呢? 小明:嗯...不是太清楚。 面试官: Redis的内存淘汰机制有哪些? 小明:嗯...没了解过 面试官:我们还可以用Redis做哪些事情?分别利用了Redis的哪个指令? 小明:我只知道Redis还可以做分布式锁、消息队列... 面试官:好了,我们进入下一个话题... 思考:很明显,小明同学在面试过程中关于Redis的表现和回答肯定是比较失败的。Redis是我们工作中每天都会使用到的东西,为什么一到面试却

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册