# 流量型止血动作

LLMS 索引： [llms.txt](/llms.txt)

---

流量型止血的目标不是让所有请求都继续进入，而是让系统重新获得**完成有价值工作的
能力**。在过载区间里，少接收一些工作通常比全部接收、全部超时更可用。

## 34.5.1 限流、熔断、摘除非关键负载 {#item-34-5-1}

### 越靠近来源，拒绝成本越低

```text
client / edge
  -> application admission
      -> local pool
          -> proxy / PgBouncer
              -> PostgreSQL
```

在应用 admission 拒绝一个尚未创建事务的请求，成本通常远低于让它拿到 database
connection、执行一半、生成 WAL 后再取消。因此控制顺序优先：

1. 阻止新的低优先级到达；
2. 冻结无抖动重试、autoscaling 和批量 worker 扩张；
3. 缩小 batch/report/migration pool；
4. 对依赖数据库的非关键功能打开熔断或静态降级；
5. 最后才在数据库内取消已经进入的 exact work。

### 限流、熔断、摘流回答不同问题

| 控制 | 回答 | 典型状态 |
|---|---|---|
| rate limit | 单位时间允许多少新工作 | token/leaky bucket |
| concurrency limit | 同时允许多少在途工作 | semaphore/pool |
| queue bound | 等待多少、等多久 | length + deadline |
| circuit breaker | 下游失败时是否继续尝试 | closed/open/half-open |
| load shedding | 哪类工作先被拒绝 | priority/admission class |
| route removal | 哪个后端不再接新流量 | health/maintenance state |

熔断打开不等于数据库恢复；它只是停止继续伤害下游。half-open probe 必须有很小并发，
否则所有实例同时探测会形成下一轮风暴。

### 按业务价值而不是技术便利舍弃

一个可执行的 shedding 顺序需要产品 owner 参与：

```yaml
preserve:
  - payment commit
  - authentication write
  - incident/admin probe
degrade:
  - recommendation to cached response
  - dashboard to stale snapshot
pause:
  - ETL
  - report export
  - reindex/migration
reject:
  - best-effort refresh
```

“所有 SELECT 都是低价值”或“写都更重要”并不成立。某些 read 是支付授权前置条件，
某些 write 只是可重算的埋点。

## 34.5.2 取消查询、暂停批处理与只读降级 {#item-34-5-2}

### 取消只命中已证明的工作集

安全筛选示例：

```sql
WITH target AS (
  SELECT pid, backend_start
  FROM pg_stat_activity
  WHERE application_name LIKE 'report-worker:%'
    AND state = 'active'
    AND query_start < clock_timestamp() - interval '30 seconds'
    AND pid <> pg_backend_pid()
)
SELECT pid,
       backend_start,
       pg_cancel_backend(pid) AS signaled
FROM target;
```

生产中还应绑定数据库、role、query/job tag、变更单与 owner。`LIKE 'report-worker:%'`
只有在 application_name 受治理、不能被任意业务伪造时才够用。

取消后等待并验收，不要立即升级为 terminate：

```text
target sessions disappear or become idle/aborted
root lock releases
waiters make progress
application does not recreate work
useful completion rate rises
rollback/recovery cost remains bounded
```

### 暂停 producer 比逐条 cancel 更有效

batch 系统通常有 scheduler、queue consumer 或 worker deployment。先暂停 producer，
再处理 in-flight work；否则数据库每取消一条，调度器就补一条。暂停要记录：

```text
queue name and partition
last acknowledged item/checkpoint
in-flight ownership
resume condition
duplicate/replay semantics
maximum backlog after pause
```

如果任务没有 checkpoint 与幂等性，暂停本身可能产生业务不一致，需要应用 owner 决策。

### 只读降级有一致性前提

把读流量移到 replica 可以减少 primary 的部分 CPU/I/O，但必须回答：

```text
can this operation tolerate replica lag?
does it require read-your-write or monotonic reads?
will long reads delay replay or create conflicts?
does replica share the same storage/CPU failure domain?
is offline/analytics capacity isolated?
what happens when no eligible replica exists?
```

不要把写请求改成“返回成功但不落库”，除非业务明确设计了 durable queue/ledger 和补偿。
也不要把所有查询涌向一台 replica：这可能让 replay 落后，进一步破坏读语义和 HA
候选质量。

Pigsty 的 replica/offline 服务可以表达路由意图，不能替代这些语义判断。路由后用
`pg_is_in_recovery()`、`transaction_read_only`、replay lag 与业务 token 复核。

## 34.5.3 每个动作写清收益、代价、停止条件和回退 {#item-34-5-3}

### 动作卡，而不是命令清单

```yaml
action_id: FLOW-07
hypothesis:
  report batch consumes the OLTP server pool
target:
  application_name_prefix: "report-worker:"
  pool: report
expected_benefit:
  free_at_least_connections: 12
  reduce_lock_waiters_below: 3
cost:
  report_jobs_paused: true
  duplicate_risk: reconciled-by-job-id
guard:
  exclude_admin_and_oltp: true
stop_condition:
  useful_tps_not_improved_after: 120s
  post_cancel_io_exceeds_baseline_by: 2x
rollback:
  restore_pool_limit: after 15m stable window
evidence:
  before: ...
  after: ...
owner: ...
```

四个字段不可省：

1. **收益**：哪个指标应在多长时间内变化；
2. **代价**：谁被拒绝、延迟或需要补偿；
3. **停止条件**：什么证据说明假设错误或副作用更大；
4. **回退**：如何撤销临时配置、恢复任务并验证没有重放。

### 一次只改变可辨识的控制变量

同时扩容、重启、cancel、改 pool 和改路由，曲线即使恢复也无法知道哪个动作有效；
某个有害动作可能被另一个动作掩盖。事故很急时可以并行动作，但必须按独立目标分组，
记录精确时间和 owner：

```text
T0 admission limit
T1 batch pause
T2 exact cancel
T3 service probe recovery
T4 queue below stop threshold
```

涉及同一变量的相反动作不能并发，例如一个人缩 pool、另一个人扩大 `max_connections`。

### 止血成功的定义

至少同时满足：

```text
user success and tail latency recover
queue/rejection trend is understood
database has resource headroom, not merely lower traffic
replicas/archive/backup remain healthy
no unknown large rollback or retention boundary remains
temporary controls have owner, expiry and rollback evidence
```

服务恢复后不要马上取消全部限流。先保持观察窗口，逐级放量；每一级都验证完成率、
尾延迟、资源余量与重试量。一次把 backlog 全部释放，会制造第二次尖峰。

---

[上一节：CPU、内存、I/O 与 OOM](../04/) · [返回本章目录](../) · [下一节：保留型故障的安全路由](../06/) ·
[查看全书目录](/toc/) · [查看索引中心](/indexes/)
