本网站相关文章:

HDD, SSD

Hard Disk Drive

HDD(维基): 电脑上使用坚硬的旋转片为基础的非挥发性存储设备, 它在平整的磁性表面存储和检索数字数据, 信息通过离磁性表面很近的磁头控制电磁流来改变极性方式写到磁盘上, 信息可以通过相反的方式读取.

HDD 中数据的操作, 95%的消耗在机器运动上, 一次数据操作表示一次 IO 动作, 其操作过程为:

  • 寻道时间延迟, 3-15ms
  • 旋转延迟, 即盘片旋转将磁头转移到磁头下方的时间延迟, 例如 7200rpm(7200 roll per minute)的磁盘, 平均延迟 4.17ms
  • 内部接口传送时间延迟, 磁盘盘片到内部磁盘缓冲
  • 外部接口传输时间延迟, 磁盘缓冲到接口

影响一个已有的固定的 HDD 磁盘的时间一般是寻道时间, 其他三项都是固定值

Solid State Disk

SSD: 一种主要以闪存作为永久性存储器的电脑存储设备.

优点: 固态硬盘具有低功耗, 无噪音, 抗震动, 低热量的特点.数据能更加安全地得到保存, 延长靠电池供电的设备的连续运转时间. 不需要旋转, 不同位置的读取速度一样, 不需要进行磁盘整理等操作.
缺点: 成本, 写入次数, 读取干扰, 损坏时的不可挽救性及掉, 但是在其优点面前缺点可以用 money 避免

[非]易失性内存

  • 易失性内存: 用于临时性存储, 需要靠外界电力维持其记忆, 访问速度极快(类似内存), 在断电时一般有足够的时间进行数据转移和备份.
  • 非易失性内存: 数据访问速度介于易失性内存和传统硬盘之间, 不需要外界电力来维持其记忆.因此更适于作为传统硬盘的替代品.

IO 性能

  1. QPS: Queries Per Second, 每秒查询量, 在不同场景其包含的含义不一样(数据库中, 请求中, IO 中均存在该标准), 但大体上表示每秒可以做的单元工作量.
  2. IOQPS: 每秒可以完成的 IO 服务次数, 作为磁盘性能的度量指标, 每一次 IO 服务器的主要耗时就在寻道时间上, 如果是大量随机的 IO 操作, 那就扯淡了
  3. IO 吞吐/带宽: 在指定的时间, 指定的内存下, 完成 IO 读写数据字节数, 其中带宽和 IOQPS 关系如下:
  • 增加每次读写数据量, 则 IO 吞吐增加, 同时 IOQPS 就会下降
  • 按照需求场景, 大文件需要大吞吐, 小文件和随机读写也许则需要追求 IOQPS
  • 根据实际场景, 设置响应的 blocksize 大小, 从而达到 IOQPS 和 IO 吞吐的均衡
  1. IO 提升方法
  • IO 合并: 将多个 IO 请求合并
  • IO 拆封: 采用 raid 等磁盘阵列, 将普通 IO 请求并发的分发到多个物理磁盘, 提高 IO 吞吐
  • IO 大 cache: 预存 Cache, staout
  • IO 大预读 Buffer: 预读多余的数据到内存中, 你想用 4KB, 我把后面的 512KB 都读出来, 我猜我猜!
  1. IOwait: 内核态 CPU 用于等待 IO 完成的 CPU 耗时, 在 iostat, iotop 中查看

内存相关

  1. 寄存器: Register 是 CPU 一部分, 离 CPU 最近, 访问数据最快的存储介质, 用来做一些最基本的指令和地址看查询.SRAM 又称为静态 RAM, 用于 CPU 内部寄存器以及 CPU 缓存.

  2. 高速缓存(L1 SRAM, L2 SRAM, L3 SRAM): Cache 是速度仅次于 CPU 内置寄存器的存储器, 其是为了弥合 CPU 和 MEMORY 的速度差距, 根据空间局部性原理, 提升数据的访问效率. CPU 中有好几个等级的缓存.

  • L1 SRAM: 单 CPU 独有, 存储指令和数据, 其中指令和数据是分开存储的, 访问速度3 Cycles
  • L2 SRAM: 单 CPU 独有, 存储指令和数据, 不会区分开来, 访问速度11 cycles
  • L3 SRAM: 多 CPU 共享缓存, 访问速度25 cycles
  • TLB: 缓存 MMU(分页内存管理单元)使用的页表.

上面的访问速度都是引用其他网站数据, 并非非常准确, 但是可以大概的理解各个缓存的访问效率, 另外内存的访问效率100 cycles.

IO 监控

iotop

iotop 获取 IO 压力大的进程, IO 实时监控, 展示系统中每一个进程线程的信息, 输出 PID/USER/IO/进程相关信息. 通过 iotop 来获取当前使用 IO 大开销的进程(老板, 外卖): iotop, 根据进程信息, 查询/proc/<pid>/io中的信息来查看:

1
2
3
4
5
6
7
rchar               读出的总字节数
wchar 写入的总字节数
syscr read系统调用的次数
syscw write系统调用的次数
read_bytes 实际从磁盘中读取的字节数
write_bytes 实际写入到磁盘的字节数
cancelled_write_bytes 由于截断pagecache导致该发生但是没有发生而冗余的字节数

命令的动态输出:

1
2
3
4
Total DISK READ:         0.00 B/s | Total DISK WRITE:         0.00 B/s
Current DISK READ: 0.00 B/s | Current DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
30 be/4 root 0.00 B/s 0.00 B/s ?unavailable? [cpuhp/3]

iostat

iostat(io statistics), 系统 IO 压力分析工具, 对系统的磁盘操作活动进行监视, 汇报磁盘活动统计情况, 不对指定进程进行深入分析, 该命令类似 netstat.

  1. 命令参数:
1
2
3
4
5
-c      显示cpu使用情况
-d 显示磁盘使用情况
-k 以kb显示
-m 以mb显示
-x 详细显示每一个设备的详细io信息

ubuntu 系统下的命令输出如下:

1
2
3
4
5
6
7
Linux 5.15.0-52-generic (bifeng) 	2022年11月28日 	_x86_64_	(8 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle
2.25 0.01 0.40 0.04 0.00 97.29

Device tps kB_read/s kB_wrtn/s kB_dscd/s kB_read kB_wrtn kB_dscd
nvme0n1 8.62 96.11 79.22 0.00 1811148 1492913 0

其中 device 表示挂载的磁盘设备, 从df -h命令可以看出

1
2
3
4
5
➜  ~ df -h
文件系统 容量 已用 可用 已用% 挂载点
udev 7.7G 0 7.7G 0% /dev
tmpfs 1.6G 3.1M 1.6G 1% /run
/dev/nvme0n1p2 468G 114G 331G 26% /
  1. 命令的输出分析
    cpu:
  • iowait:等待输入输出完成的时间占用百分比
  • idle:空闲时间占比
  • steal:虚拟 cpu 的无意识等待时间百分比
  • user:
  • system

disk 属性:

  • tps: 每秒传输次数, 设备每秒的数据传输次数(一次传输就是一次 io 服务)
  • blk_read/blk_wrtn/s: 读吞吐量, 每秒的对写 blcok(扇区)次数
  • blk_read/blk_wrtn: 累计的对写 block 次数

dd

dd, 磁盘顺序读写性能测试命令, 转换和复制文件, 其用指定大小的块拷贝一个文件, 并在拷贝的同时进行转换. 磁盘 IO 存在两种方式:

  • BufferIO: 设备->内核->用户
  • DirectIO: 设备->用户

在讲解 dd 命令之前先介绍下平常磁盘单位代表的实际容量:

1
2
3
4
5
6
7
c = 1
w = 2
b = 512
kb = 1000
K = 1024
MB = 1000 * 1000
M = 1024 * 1024

参数说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Usage:dd [option] 或者 dd option
Option:
if 输入文件或者设备名称, 默认为stdin
iflag 指定读取的方式, 按照逗号分隔列表, 将FLAGS说明
ibs 每次读取的字节数(input byte), 默认为512

of 输出文件或者设备名称
oflag 指定写入方式
obs 每次写入的字节数

bs 设置R/W缓存区的字节数(即同时设置ibs/obs)
obs 每次conv转换的字节数

count 拷贝的块大小(并非块数量?)
seek 在输出开始时跳过block块值
skip 在输入开始时跳过ibs大小的块值

CONV:
ascii 转换EBCDIS到ASCII
block 将每一行转为长度为cbs的记录, 不足用空格填充

FLAGS分类, 见上面的iflag, oflag等:
direct 直接IO方式
dsync 同步R/W IO
sync 元数据同步R/W
nonblock 非阻塞IO

其中BLOCKSBYTES后面单位计算见上面的单位介绍. 另外, 不同的系统(macos, ubuntu)单位的大小写不一样, 为了兼容多操作系统, 最好在将单位设置为最小单位, 比如 1M 变为1024 * 1024.

  1. 读写测试(DirectIO)

写测试—iops:

1
2
3
4
5
6
7
# a. 创建一个大小为10 * 8k的空文件a.dat
dd if=/dev/zero of=./a.dat bs=8k count=10 oflag=direct
ls -l a.dat

# b. 直接一次写入大数据, 大小为1G
dd if=/dev/zero of=./a.dat bs=1G count=1 oflag=dsync
ls -l a.dat

读测试—iops:

1
2
3
4
5
# a. 首先设置缓存无效(不要在正式环境中尝试)
flush
echo 3 | sudo tee /proc/sys/vm/drop_caches
# b. 测试
dd if=./a.dat of=/dev/null bs=8k count=1M iflag=direct

写测试—IO 吞吐:

1
dd if=/dev/zero of=./a.dat bs=1M count=8k oflag=direct

读测试—IO 吞吐:

1
dd if=./a.dat of=/dev/null bs=1M count=8k iflag=direct

测试结果: 对于小块数据的读写, HDD 性能略低于 SSD, 对于大块数据的读写, SSD 性能达到 HDD 的 20 倍以上, 当然, HDD 可以通过 BufferIO 来提升性能

  1. 服务器延迟
1
2
3

# 多次写入, 每次512字节, 获取RAID服务器的延迟时间
dd if=/dev/zero of=./a.data bs=512 count=1000 oflag=dsync
  1. 截取复制文件
1
2
3
4
5
6
7
8
9
10
11
12
# a. 跳过文件前 1MB, 读取后续内容到文件末尾
dd if=/dir/infile.log of=/dir/oufile.log skip=1m ibs=1m obs=1m

# b. 对于 10MB 的文件, 保留 1MB, 覆盖后续的 8MB 到目标文件中(覆盖目标文件)
dd if=/dir/infile.log of=/dir/oufile.log skip=1m seek=1m count=8m ibs=1m obs=1m
# count可以k为单位
dd if=/dir/infile.log of=/dir/oufile.log skip=1m seek=1m count=9216k ibs=1m obs=1m

# c. 截取日志文件中执行大小
dd if=/dir/infile.log of=/dir/oufile.log skip=2m ibs=1m obs=1m
# 拼接
cat /dir/oufile.log >> /dir/dest.log

参考