🕸️ 第九章 安全措施
📄 一句话概括

性能管理只有两步——先量,再调;调的抓手是进程优先级,而优先级里最容易记错的两条是:普通用户只能调高不能调低,而且它只在有竞争时才起作用。

📝 本节和前面几节的关系

9-7 讲的是怎么把数据采上来,这一节讲采到数据之后怎么动手。它是 9-7 的直接延续,也是全章唯一一节需要动手敲命令的内容。教材 9-8 的并列关键词是【检查使用率、修改进程的优先级】。

一、先量,再调

性能管理的顺序不能颠倒。先量清楚瓶颈在哪,再动手调。 测的顺序基本固定:

这一步最常被跳过的判断是:CPU 满不等于 CPU 不够。 如果 wa 很高,说明 CPU 是在等磁盘,这时候加 CPU 一点用都没有, 该换的是存储。调优的第一个动作永远是确认瓶颈真的在你要调的那个地方。

二、调优先级的工具,各有各的分工

确认瓶颈之后,调的手段有好几种,它们管的事情完全不同:

一个务实的习惯转变值得单独说:从【烦了敲一条 renice】,改成【把策略写进 systemd 单元文件】。 前者只有你记得,后者重启之后还在,而且能被别人 review。

nice 和 cgroups 的区别也要分清:nice 只是把尺子(相对份额),cgroups 才是把刀(绝对上限)。 要卡死一条线,只能用后者。

三、nice 值的两条规矩

nice 的取值范围是 −20 到 19,数字越小越优先(默认是 0)。 这里有两条最容易记错、也最容易踩坑的规矩:

还有两个常见误区:

另外提醒一句:nice -10 cmd 这种写法有歧义,规范写法是 nice -n -10 cmd。 脚本里尤其要注意——歧义写法在不同实现下行为不一样。

四、落到场景:惯用的配法

把上面这些拼起来,就是几种常见的配法:

这里有一条不成文的经验值得记住:频繁改优先级本身就是信号。 如果天天要 renice,说明这台机器的容量已经不够了—— 该做的是加资源或者分机器,而不是继续在优先级上找平衡。

最后补一句:激进地给某个进程设很低的 nice 值(比如 −20),会让别的进程明显变卡。 日常调优的原则是小幅调、测完再看, 而不是一次调到底。

五、动手 Demo:把优先级与巡检口径算一遍

优先级调优里的几个数,其实都能算成更直观的说法:

print("  nice 范围 -20 ~ 19,跨 %d 档" % (19 - (-20)))
print("  默认 0 到最低 19,还有 %d 档可让步" % (19 - 0))
print("  CPU 告警阈值 90%%,留 %.0f 个百分点的余量" % (100 - 90))
print("  每 5 分钟巡检,一天 %d 次" % (24 * 60 // 5))
print("  把队列进程设成 nice 10:它只在有竞争时才让路")

实跑输出:

--------------------------------------------------------------------
CPU 满了,先动谁
--------------------------------------------------------------------
  服务器的性能管理只有两步:先量,再调。量的是各种使用率,
  调的是各进程占资源的优先级。这里说的优先级,主要是 CPU 上的分寸。

  Linux 里调优先级用的还是那几个老命令,但 2026 年的习惯变了:

  工具                   作用                     什么时候用
  -----------------------------------------------------------------------
  nice                   启动时给个优先级         提前知道这是个后台活
  renice                 改已在跑进程的优先级     发现某个进程霸占 CPU
  cgroups / CPUQuota     给服务设硬上限           要保证不能超过某条线
  systemd 单元文件       把优先级写成配置         服务重启后仍然生效
  ionice                 调的是磁盘读写优先级     备份、同步把磁盘拖慢时
  taskset                绑定到指定 CPU 核        要减少线程来回跳的开销
  -----------------------------------------------------------------------

  nice 值的范围是 −20 到 19,数字越小越优先。有两条规矩容易踩:

  要点                           说明
  --------------------------------------------------------------
  普通用户只能调高不能调低       把优先级往上提需要管理员权限
  nice 只在有竞争时才起作用      机器闲着的时候,改不改都一样快
  它只管 CPU,不管内存和磁盘     磁盘拖慢要去动 ionice
  改父进程不等于改子进程         真正吃 CPU 的往往是子进程
  --------------------------------------------------------------

  落到具体场景,惯用的配法是这样的:

  场景                 做法                             为什么
  -------------------------------------------------------------------------
  数据库服务器         主进程给高优先,备份给低优先     查询不能被备份拖慢
  Web 应用             Nginx 与 PHP-FPM 保持默认        它本身就该及时响应
  队列消费进程         给低优先                         晚几秒处理没人察觉
  大文件备份、解压     低优先 + 低磁盘优先              把磁盘留给在线业务
  -------------------------------------------------------------------------

  小算例:把队列进程设成 nice 10,它和默认的 Web 进程抢 CPU 时,
  注意这不是对半分——nice 差 10 通常意味着 Web 进程能拿到绝大部分时间片。
  nice 是把尺子,不是把刀;要卡死上限得用 cgroups 的 CPUQuota。

  还有一个不成文的经验:频繁改优先级本身就是信号。如果天天要 renice,
  说明这台机器的容量已经不够,该加资源或者该分机器了。

第一行的 39 档,说明 nice 是个粗颗粒的旋钮,不是精密仪器。 第三行的 10 个百分点余量,是留给突发流量的缓冲——阈值不是越贴越好。 最该记住的还是最后一行那句话:nice 只在有竞争时才起作用。 没有竞争的时候,你怎么调都测不出差别,会误以为【这个参数没用】。

30 秒实验

  1. 在你的电脑上跑一个吃 CPU 的任务,用任务管理器把它的优先级调低,看看界面是不是更流畅了。
  2. 在 Linux 上敲 nice -n 10 sleep 100 &,再用 ps -o pid,ni,cmd 看看它的 nice 值。
  3. 敲一次 uptime,看那三个数字(1、5、15 分钟负载),和你机器的核数对比一下。

常见误区

  1. 错误:CPU 使用率高就要加 CPU。——纠正:先看 wa(等待 I/O);wa 高说明瓶颈在磁盘,加 CPU 一点用都没有。
  2. 错误:调了 nice 就能让程序变快。——纠正:nice 只在有 CPU 竞争时才起作用;机器闲着的时候改不改一个样。
  3. 错误:nice 能限制一个进程最多用多少 CPU。——纠正:nice 只是相对份额(尺子),要卡死上限得用 cgroups 的 CPUQuota(刀)。
自测三问(点开对答案) 1. 性能管理的第一步是什么? —— **先量,再调。** 而且要先确认瓶颈真的在你要调的地方——比如 `wa` 高说明瓶颈是磁盘,加 CPU 没用。 2. nice 和 cgroups 的本质区别是什么? —— **nice 是相对份额(尺子),只在有竞争时起作用;cgroups 的 CPUQuota 是内核强制的绝对上限(刀)。** 要卡死一条线只能用后者。 3. 为什么普通用户不能把 nice 值调小(提权)? —— **因为随便提权会饿死别的进程,把整台机器拖垮**;提权需要管理员权限,这是故意的限制。

相关笔记