?page cache
Linux 操作系统默认情况下写都是有写缓存的, 可以使用 direct IO 方式绕过操作系统的写缓存. 当你写一串数据时, 系统会开辟一块内存区域缓存这些数据, 这块区域就是我们常说的 page cache(操作系统的页缓存). 查看系统内存常用的命令有: vmstat,free,top 等.
可以使用 cat /proc/meminfo 查看详细的内存使用情况
?
其中的 Cached 为 140M 左右(page cache). 注意其中有一个 Dirty: 24KB, 表示当前有 24KB 的数据缓存在 page cache, 这些数据等待后台线程刷入磁盘. 随着写入数据增加, 这个值也会增加.
?
writeback
有了 page cache 就有了 writeback 写方式. 一个写 IO 会先写入 page cache, 然后等待后台 pdflush 把 page cache 中脏数据刷入磁盘. 如果在刷入磁盘之前系统断电, 则 page cache 的数据丢失. 所以对一些可靠性要求高的场景都会把这个写缓存禁掉. writeback 写方式是 Linux 操作系统提供的一种非常通用写模式. writeback 提供了较好的吞吐量, 有了缓存也缩短了 IO 响应时间. 但它也有缺点:(1)断电可能丢数据 (数据安全性)(2) 对于像数据库这样自缓存的系统来说, 多了一层 IO 缓存开销. 因为数据库已经在应用层做了一层缓存. 所以对于这样的应用可以用 direct io 方式, 减少用户空间和 page cache 之间数据复制开销.(3)如果 page cache 过大, 那么就会缓存太多的数据, 当需要统一刷入磁盘的时候就会出现一个 IO 峰值和瓶颈, 在这其间对用户的 IO 访问出现明显影响. 如果想削平这个峰值可以把 page cache 容量设置小一点, 让 pdflush 一段时间内较为平均的刷新 dirty 数据.
?
pdflush
pdflush 是 Linux 系统后台运行的一个线程, 这个进程负责把 page cahce 中的 dirty 状态的数据定期的输入磁盘. 一个系统中会运行很多这个 pdflush.cat /proc/sys/vm/nr_pdflush_threads 查看当前系统运行 pdflush 数量. 当一段时间 (一般是 1s) 没有任何的 pdflush 处于工作状态, 系统会 remove 一个 pdflush 线程. pdflush 最大和最小的数量是有配置的, 但这些配置一般很少修改.
?
几个重要的 IO 写相关参数
4.1 dirty_writeback_centisecs
cat /proc/sys/vm/dirty_writeback_centisecs 查看这个值, 默认一般是 500(单位是 1/100 秒). 这个参数表示 5s 的时间 pdflush 就会被唤起去刷新脏数据. 没有官方文档说明减少这个值就会有更多的 pdflush 参与刷数据. 比如 2.6 或者更早的内核, Linux 中 mm/page-writeback.c 的源码中有这样一段描述 "如果 pdflush 刷新脏数据的时间超过了这个配置时间, 则完成刷新后 pdflush 会 sleep 1s". 这种拥塞的保护机制描述只是写在源码里, 并没有写入官方文档或者形成规范, 所以也就意味着这种机制在不同的版本可能有不同的表现.
所以修改 dirty_writeback_centisecs 并不一定能给你带来多少性能的提升, 相反有可能出现你意想不到的问题. 一般建议用户使用默认值.
- ?
- 4.2 dirty_expire_centisecs
cat /proc/sys/vm/dirty_expire_centicecs 查看这个值, 默认是 3000(单位是 1/100 秒). 这个值表示 page cache 中的数据多久之后被标记为脏数据. 只有标记为脏的数据在下一个周期到来时 pdflush 才会刷入到磁盘, 这样就意味着用户写的数据在 30 秒之后才有可能被刷入磁盘, 在这期间断电都是会丢数据的. 如果想 pdfflush 刷新频率大写可以减小这个值, 比如: echo 1000>> /proc/sys/vm/dirty_expire_centicecs 设置为 10s 一个刷新周期.
- ?
- 4.3 dirty_backgroud_ratio
cat /proc/sys/vm/dirty_backgroud_ratio 查看这个值, 默认是 10(单位是百分比, 不同的内核版本可能有不同的默认值). 很多的描述文档中描述这个值表示最多缓存脏数据的空间占总内存的百分比. 其实不然, 查看源码的描述, 它的真实意义是占 (MemFree + Cached - Mapped) 的百分比. 达到这个上限后会唤醒 pdflush 把这些脏数据刷新到磁盘, 在把脏数据输入磁盘之前所有写 IO 会被阻塞. 所以如果这个值设的过大, 则会周期的出现一个写 IO 峰值, 而且这个峰值持续比较长时间, 在这段时间内用户的写 IO 会被阻塞. 对于一些业务场景需要把这个值设置的小写, 把峰值写 IO 平分为多次小的写 IO. 例如: echo 5>>?cat /proc/sys/vm/dirty_backgroud_ratio 把百分比降低到 5%.
4.4 ?dirty_ratio
cat /proc/sys/vm/dirty_ratio 查看这个值, 默认是 20(单位是百分比, 不同的内核版本可能有不同的默认值). 表示当脏数据占用总内存的百分比超过 20% 的时候, 内核会把所有的写操作阻塞掉, 等待 pdflush 把这些脏数据刷入到磁盘后才能恢复正常的 IO 写. 要注意的是当这个事件发生时, 会阻塞掉所有写操作. 这样会产生一个很大的问题, 一个长时间大 IO 会抢占更多的 IO 写资源, 可能把其它的小 IO 饿死. 因为大 IO 产生的脏数据较多, 很快达到这个阀值, 此时就会系统会阻塞掉所有的写 IO, 从而小写 IO 无法进行写操作.
来源: http://www.bubuko.com/infodetail-3168880.html