一、排查IO相关的命令

iostat

-安装:

yum install sysstat

-使用:

iostat -x 1 2	#每一秒输出,输出2次(可以查看出io读写的分区)

-参数说明:

Device:设备名称
tps:每秒的IO读、写请求数量,多个逻辑请求可以组合成对设备的单个I/O请求。
Blk_read/s (kB_read/s, MB_read/s):从设备读取的数据量,以每秒若干块(千字节、兆字节)表示。块相当于扇区,因此块大小为512字节。
Blk_wrtn/s (kB_wrtn/s, MB_wrtn/s):写入设备的数据量,以每秒若干块(千字节、兆字节)表示。块相当于扇区,因此块大小为512字节。
Blk_read (kB_read, MB_read):读取块的总数(千字节、兆字节)。
Blk_wrtn (kB_wrtn, MB_wrtn):写入块的总数(千字节,兆字节)。

rrqm/s:每秒合并到设备的读请求数。即delta(rmerge)/s 
wrqm/s:每秒合并到设备的写入请求数。即delta(wmerge)/s 
r/s:每秒完成的读I/O设备次数。即delta(rio)/s 
w/s:每秒完成的写I/0设备次数。即delta(wio)/s 
rsec/s (rkB/s, rMB/s):每秒读取设备的扇区数(千字节、兆字节)。每扇区大小为512字节
wsec/s (wkB/s, wMB/s):每秒写入设备的扇区数(千字节、兆字节)。每扇区大小为512字节

avgrq-sz:平均每次设备I/O操作的数据量(扇区为单位)。即delta(rsec+wsec)/delta(rio+wio) 
avgqu-sz:平均每次发送给设备的I/O队列长度。
await:平均每次IO请求等待时间。(包括等待队列时间和处理时间,毫秒为单位)
r_await:平均每次IO读请求等待时间。(包括等待队列时间和处理时间,毫秒为单位)
w_await:平均每次IO写请求等待时间。(包括等待队列时间和处理时间,毫秒为单位)
svctm:平均每次设备I/O操作的处理时间(毫秒)。警告!不要再相信这个字段值,这个字段将在将来的sysstat版本中删除。 
%util:一秒中有百分之多少的时间用于I/O操作,或者说一秒中有多少时间I/O队列是非空的。当该值接近100%时,设备饱和发生。

pidstat

-安装:

yum install sysstat

-使用:

pidstat -d 1	#-d,显示各进程io使用情况;每一秒输出一次(可以查看io高的进程)

-参数说明

PID:进程id
kB_rd/s:每秒从磁盘读取的KB
kB_wr/s:每秒写入磁盘KB
kB_ccwr/s:任务取消的写入磁盘的KB。当任务截断脏的pagecache的时候会发生。
COMMAND:task的命令名

iotop

类似于top的实时监控模式

iotop -oP
#可以看到io的进程,并且只显示有I/O行为的进程

dmesg

介绍

dmesg是内核级别记录io的日志信息;通过dmesg信息可以看到IO正在写那些文件,有进程号,inode号,文件名和磁盘设备名;

使用方法

在排查服务器IO繁忙的原因时,需要检查哪个进程在频繁IO。在Linux内核提供了block_dump参数来把block读写(WRITE/READ)情况dump到日志中,这样就可以使用dmesg命令来查看

dmesg		#输出dmesg的日志
如:
[10489963.254731] kworker/u65:0(119773): WRITE block 3017556368 on sdm (136 sectors)
[10489963.254763] kworker/u65:0(119773): WRITE block 3017556360 on sdm (8 sectors)
[10489963.367301] prometheus(142509): dirtied inode 177997980 (00000050) on sdm
[10489963.367312] prometheus(142509): dirtied inode 177997980 (00000050) on sdm

注意:其中日志中WRITE block 0,WRITE block 16, WRITE block 104中的数字表示写到了哪个block 而 不是 写了多少blocks。

分析WRITE block,后面的数字并不是真正的块号,而是内核IO层获取的扇区号,除以8即为块号,然后根据debugfs工具的icheck和ncheck选项,就可以获取该文件系统块属于哪个具体文件

如果一直dmesg的话,日志量是非常巨大的,所以该功能默认是关闭的,在dmesg之前一般需要先开启,收集一段时间的日志后再用dmesg统计的,且统计完之后也要关闭;

echo 1 > /proc/sys/vm/block_dump	#开启dmesg
echo 0 > /proc/sys/vm/block_dump	#关闭dmesg(默认)

或者

sysctl -w "vm.block_dump=1"		#开启dmesg
sysctl -w "vm.block_dump=0"		#关闭dmesg(默认)

开启dmesg之后,稍作等待,即可使用命令过滤出高io的进程:
采用如下命令统计当前占用IO最高的10个进程:

dmesg |awk -F: '{print $1}'|sort|uniq -c|sort -rn|head -n 10

其他命令

dmesg -c    #输出日志,并清空。(因为之前的日志可能会影响后续io的排查,可以先清空)

参考链接1
参考链接2

二、排查cpu相关的命令

分析cpu主要就是分析哪些进程占用

ps

-进程排序

ps aux --sort=-pcpu	#占用cpu进程的降序(+ 是升序)

-进程树

ps -ef --forest		#显示进程树,可以清楚看到进程的属主

-显示线程

ps -efL		#显示全部的进程、线程;负载高有时也是因为线程多造成的;

-ps命令状态位

#ps aux :
STAT状态位常见的状态字符
	D 无法中断的休眠状态(通常 IO 的进程);
	R 正在运行可中在队列中可过行的;
	S 处于休眠状态;
	T 停止或被追踪;
	W 进入内存交换  (从内核2.6开始无效);
	X 死掉的进程   (基本很少見);
	Z 僵尸进程;
	< 优先级高的进程
	N 优先级较低的进程
	L 有些页被锁进内存;
	s 进程的领导者(在它之下有子进程);
	l 多进程的(使用 CLONE_THREAD, 类似 NPTL pthreads);
	+ 位于后台的进程组

top

进入监控模式后 P 对按照cpu占用排序;
image.png

三、排查mem相关的命令

ps

-内存排序

ps aux --sort=-pmem	#占用内存进程的降序(+ 是升序)
ps -HT $pid	#通过进程号,可以看到该进程的线程

top

进入监控模式后 M 对按照内存占用排序;
image.png

free

-使用

free -h		#查看总体进程的占用(-m,-h 显示的单位不同)

image.png

-参数说明

total:总计物理内存的大小。
used:已使用多大。
free:剩余可用内存(从系统层面看)
Shared:多个进程共享的内存总额。
Buffers/cached:磁盘缓存的大小。
available:剩余可用内存(从应用层面看,因为缓存中的部分内存也是可以被应用程序直接使用的)

四、其他命令

vmstat

使用方法:
vmstat 1 10
#每1秒输出一次,输出10次;

示例:

[root@huawei src]# vmstat 1 10
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0   4912 211068 230804 2163612    0    0     0    10    1    1  0  0 100  0  0
 0  0   4912 212636 230804 2163612    0    0     0    52  362  649  1  1 99  0  0
 0  0   4912 214616 230804 2163612    0    0     0    56  337  612  0  0 100  1  0
 0  0   4912 213248 230804 2163616    0    0     0     0  412  678  1  1 99  0  0
 0  0   4912 213224 230804 2163620    0    0     0     4  301  566  0  1 100  0  0
 0  0   4912 214400 230804 2163620    0    0     0     0  335  606  1  0 100  0  0
 0  0   4912 214512 230804 2163624    0    0     0     0  292  571  0  0 100  0  0
 0  0   4912 214512 230804 2163624    0    0     0     0  285  553  0  0 100  0  0
 0  0   4912 214512 230804 2163624    0    0     0    80  315  586  1  0 100  0  0
 0  0   4912 214512 230804 2163624    0    0     0     0  267  532  0  1 100  0  0

-参数说明

r 表示运行队列(就是说多少个进程真的分配到CPU),我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系,一般负载超过了3就比较高,超过了5就高,超过了10就不正常了,服务器的状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。

b 表示阻塞的进程,进程阻塞。

swpd 虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。

free   空闲的物理内存的大小。

buff   用来存储系统目录里面有什么内容,权限等的缓存。

cache	直接用来记忆我们打开的文件,给文件做缓冲(把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高 程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用)

si  每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。

so  每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上。

bi  块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte(但曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速度差不多140M每秒)

bo  块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整。

in 每秒CPU的中断次数,包括时间中断

cs 每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。

us 用户CPU时间,曾在一个做加密解密很频繁的服务器上,可以看到us接近100,r运行队列达到80(机器在做压力测试,性能表现不佳)。

sy 系统CPU时间,如果太高,表示系统调用时间长,例如是IO操作频繁。

id  空闲CPU时间,一般来说,id + us + sy = 100,一般我认为id是空闲CPU使用率,us是用户CPU使用率,sy是系统CPU使用率。

wt 等待IO CPU时间。

image.png

五、如何减少CPU消耗?

1、减少等待

减少IO量

SQL/index,使用合适的索引减少扫描的行数(需平衡索引的正收益和维护开销,空间换时间)

提升IO处理能力

加cache/加磁盘/SSD

2、减少计算

减少逻辑运算量

避免使用函数,将运算转移至易扩展的应用服务器中
如substr等字符运算,dateadd/datesub等日期运算,abs等数学函数

减少排序

利用索引取得有序数据或避免不必要排序,如union all代替 union,order by 索引字段等

禁止类型转换

使用合适类型并保证传入参数类型与数据库字段类型绝对一致,如数字用tiny/int/bigint等,必需转换的在传入数据库之前在应用中转好。

简单类型

尽量避免复杂类型,降低由于复杂类型带来的附加运算。更小的数据类型占用更少的磁盘、内存、cpu缓存和cpu周期。

3、减少逻辑IO量

index

优化索引,减少不必要的表扫描。如增加索引,调整组合索引字段顺序,去除选择性很差的索引字段等等

table

合理拆分,适度冗余。如将很少使用的大字段拆分到独立表,非常频繁的小字段冗余到“引用表”

SQL

调整SQL写法,充分利用现有索引,避免不必要的扫描,排序及其他操作
如减少复杂join,减少order by,尽量union all,避免子查询等

数据类型

够用就好,减少不必要使用大字段,如tinyint够用就别总是int,int够用也别老bigint,date够用也别总是timestamp

4、减少query请求量(非数据库本身)

适当缓存

降低缓存数据粒度,对静态并被频繁请求的数据进行适当的缓存.如用户信息,商品信息等

优化实现

尽量去除不必要的重复请求.如禁止同一页面多次重复请求相同数据的问题,通过跨页面参数传递减少访问等

合理需求

评估需求产出比,对产出比极端底下的需求合理去除

5、升级cpu

若经过减少计算和减少等待后还不能满足需求,cpu利用率还高T_T

是时候拿出最后的杀手锏了,升级cpu,是选择更快的cpu还是更多的cpu了?

低延迟(快速响应)需要更快的cpu(每个查询只能使用一个cpu);
高吞吐同时运行很多查询语句,能从多个cpu处理查询中收益.

打赏
支付宝 微信
上一篇 下一篇