A/B 测试设计与分析时使用。适用于产品实验、功能验证、转化率优化。融合假设驱动 + 样本量计算 + 置信度判断。
日本語の概要は準備中です。原文の説明を表示しています。
设计事务边界、一致性策略、多租户隔离和数据生命周期时使用。适用于高并发写入、幂等、多租户 SaaS、软删归档和审计字段设计。融合 ACID + Saga + 乐观锁 + RLS + Tenant Per Schema。
インストールする前に、エージェントに与えられる指示の中身を確認できます。
参考来源:Pat Helland《Life beyond Distributed Transactions》、Martin Kleppmann《Designing Data-Intensive Applications》、AWS SaaS 多租户白皮书、Stripe / Slack / Notion 多租户实践。
1. 把隔离边界和一致性要求显式写入 schema 与约束
"tenant_id 字段" ≠ "多租户隔离"
还需要:查询过滤 + 唯一约束 + 权限边界 + 测试
2. 事务不应无限扩大
边界应等于业务不变量边界
3. 幂等和唯一性优先由数据库约束兜底
不靠应用代码判重
4. 不在事务里做外部调用
HTTP / 邮件 / 第三方 API 都不能放事务
5. 强一致 vs 最终一致:业务驱动
涉及钱:强一致
不影响财务:最终一致 + 补偿
6. 多租户三层防御:应用层 + 数据库层 + 测试层
单层防御必定漏
7. 软删除是甜蜜陷阱
破坏唯一约束、查询要带 WHERE deleted_at IS NULL
A - Atomicity(原子性):要么全成,要么全败
C - Consistency(一致性):事务前后业务规则一致
I - Isolation(隔离性):并发事务互不干扰
D - Durability(持久性):提交后数据不丢
| 级别 | 脏读 | 不可重复读 | 幻读 | 写偏斜 |
|---|---|---|---|---|
| Read Uncommitted | ✓ | ✓ | ✓ | ✓ |
| Read Committed(默认) | ✗ | ✓ | ✓ | ✓ |
| Repeatable Read(PG/MySQL 默认变体) | ✗ | ✗ | ✗ | ✓ |
| Serializable | ✗ | ✗ | ✗ | ✗ |
-- PostgreSQL
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- MySQL
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
建议:
- 默认 Read Committed 已能满足大多数业务
- 关键金融场景用 Serializable + 重试
- 慎用 Read Uncommitted(一般不需要)
# 反模式:事务包含外部调用
@transaction.atomic
def create_order(user_id, items):
order = Order.objects.create(...)
OrderItem.objects.bulk_create(...)
# 外部 HTTP 调用 → 事务持续 30 秒
payment_result = call_payment_gateway(order)
if payment_result.success:
order.status = 'paid'
order.save()
# 阶段 1:本地事务(仅 DB 操作)
@transaction.atomic
def create_order(user_id, items):
order = Order.objects.create(status='pending', ...)
OrderItem.objects.bulk_create(...)
return order
# 阶段 2:异步外部调用
def process_payment(order_id):
order = Order.objects.get(id=order_id)
result = call_payment_gateway(order)
# 阶段 3:本地事务更新状态
if result.success:
order.update(status='paid')
else:
order.update(status='failed')
# 补偿动作(释放库存、退款)
compensate(order)
-- 幂等性表
CREATE TABLE idempotency_keys (
key varchar(128) PRIMARY KEY,
request_hash varchar(64) NOT NULL,
response_body jsonb,
status varchar(32) NOT NULL, -- 'processing' / 'completed' / 'failed'
created_at timestamptz DEFAULT now(),
expires_at timestamptz NOT NULL DEFAULT (now() + INTERVAL '24 hours')
);
CREATE INDEX idx_idempotency_expires ON idempotency_keys(expires_at);
-- 同一订单不能支付两次
CREATE TABLE payments (
id bigserial PRIMARY KEY,
order_id bigint NOT NULL,
amount_cents bigint NOT NULL,
status varchar(32) NOT NULL,
created_at timestamptz DEFAULT now(),
-- 业务唯一:每个订单只能有一条成功的支付
CONSTRAINT uq_order_payment UNIQUE (order_id, status)
DEFERRABLE INITIALLY DEFERRED
);
-- 表设计
CREATE TABLE orders (
id bigserial PRIMARY KEY,
status varchar(32) NOT NULL,
version integer NOT NULL DEFAULT 1,
...
);
-- 更新时校验版本
UPDATE orders
SET status = 'paid', version = version + 1
WHERE id = ? AND version = ?;
-- 影响 0 行 → 版本冲突 → 应用层重试或返回 409
-- 高冲突场景:直接锁行
BEGIN;
SELECT * FROM accounts WHERE id = ? FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = ?;
COMMIT;
何时用:
乐观锁:冲突率低(< 5%),重试代价小
悲观锁:冲突率高,必须串行
# 中间件:每个查询都带 tenant_id
class TenantMiddleware:
def process_request(self, request):
request.tenant_id = get_tenant_from_token(request)
# ORM 自动过滤
class TenantAwareManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(tenant_id=current_tenant_id())
-- PostgreSQL Row Level Security(强烈推荐)
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.current_tenant_id')::bigint);
-- 应用每次连接时设置
SET LOCAL app.current_tenant_id = '123';
SELECT * FROM orders; -- 自动过滤
# 跨租户越权测试用例
def test_cross_tenant_isolation():
user_a = create_user(tenant=1)
user_b = create_user(tenant=2)
order_a = create_order(user=user_a) # tenant 1 的订单
# 用 user_b 的身份尝试访问 user_a 的订单
response = client.get(f'/orders/{order_a.id}', as_user=user_b)
assert response.status_code == 404 # 或 403
-- 所有租户共享表,靠 tenant_id 区分
CREATE TABLE orders (
id bigserial PRIMARY KEY,
tenant_id bigint NOT NULL REFERENCES tenants(id),
...
);
-- 复合唯一(必须含 tenant_id)
CREATE UNIQUE INDEX uq_orders_number
ON orders(tenant_id, order_number);
优势:
劣势:
适合:SaaS 中小租户、共用功能
-- 每个租户一个 schema
CREATE SCHEMA tenant_acme;
CREATE TABLE tenant_acme.orders (...);
CREATE SCHEMA tenant_globex;
CREATE TABLE tenant_globex.orders (...);
优势:
劣势:
适合:百级租户、企业版
每个租户独立数据库实例
优势:
- 完全隔离
- 性能 / 备份 / 安全独立
劣势:
- 资源消耗大
- 运维复杂
适合:大型企业客户、合规要求强(PII / 医疗)
-- 错:用户邮箱全局唯一
CREATE UNIQUE INDEX uq_users_email ON users(email);
-- 不同租户不能有同名邮箱
-- 对:租户内唯一
CREATE UNIQUE INDEX uq_users_email_tenant
ON users(tenant_id, email);
-- 错:软删后无法重新注册
CREATE UNIQUE INDEX uq_users_email
ON users(tenant_id, email);
-- 同 email 的删除用户阻止新注册
-- 对:部分索引
CREATE UNIQUE INDEX uq_users_email_active
ON users(tenant_id, email)
WHERE deleted_at IS NULL;
软删除(deleted_at):
✅ 用户可恢复
✅ 关联数据完整
✅ 审计需要
❌ 唯一约束复杂
❌ 查询都要带 WHERE
❌ 数据膨胀
硬删除:
✅ 简单
✅ 性能好
❌ 不可恢复
❌ 关联数据连锁删除
归档(删除前移到归档表):
✅ 主表干净
✅ 历史数据可查
❌ 跨表查询复杂
推荐:
- 用户数据:软删除(GDPR 30 天后硬删)
- 业务数据:软删除 + 6 个月归档
- 临时数据(缓存 / 会话):硬删除
- 审计日志:永不删除
-- 推荐字段
CREATE TABLE orders (
id bigserial PRIMARY KEY,
-- ... 业务字段 ...
-- 生命周期字段
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz, -- 软删
archived_at timestamptz, -- 归档
retention_until timestamptz, -- 保留期限
-- 审计字段
created_by bigint REFERENCES users(id),
updated_by bigint REFERENCES users(id),
deleted_by bigint REFERENCES users(id),
-- 乐观锁
version integer NOT NULL DEFAULT 1
);
1. 识别业务不变量和并发写入场景
- 哪些状态不能同时存在
- 哪些操作不能重复执行
- 哪些字段必须唯一
↓
2. 判断强一致、最终一致或补偿机制
- 涉及钱 → 强一致
- 通知 / 报表 → 最终一致
- 跨服务 → Saga
↓
3. 设计事务边界、锁策略、唯一约束、版本字段
- 事务最小化
- 数据库约束兜底
- 乐观锁优先
↓
4. 设计租户字段、复合约束、默认过滤规则
- 三层防御
- 复合唯一含 tenant_id
- RLS 兜底
↓
5. 设计删除、归档、审计和恢复策略
- 软删 + 部分索引
- 归档表
- 审计日志
↓
6. 输出一致性和隔离检查清单
| 项目 | 检查点 |
|---|---|
| 租户键 | 每张租户数据表是否有明确 tenant_id 字段 |
| 查询 | 是否默认带 tenant_id 过滤(中间件 / RLS) |
| 唯一性 | 唯一约束是否包含租户维度 |
| 后台操作 | 跨租户操作是否有审计和授权 |
| 测试 | 是否有跨租户越权回归用例 |
| 备份 | 单租户备份恢复是否可行 |
| 监控 | 单租户性能 / 错误是否可观测 |
| 删除 | 租户注销时数据如何处理(GDPR) |
templates/consistency-checklist-template.md — 一致性 + 多租户 + 软删除 + 审计 + RLS 配置完整清单□ 列出业务不变量
□ 说明事务边界和失败补偿
□ 幂等键、唯一约束、版本字段明确
□ 多租户三层防御(应用 + 数据库 + 测试)
□ 唯一约束包含 tenant_id
□ 软删除有部分唯一索引
□ 删除、归档、审计、恢复策略明确
□ 事务不包含外部调用
□ 隔离级别选择有依据
□ 跨服务一致性方案(Saga / 事件)
□ RLS 配置(PG)兜底
□ 与安全工作流协作评审
上游:
schema-design → 提供表结构基础
api-designer → 提供权限边界
下游:
index-access-pattern → 设计租户维度索引
data-operations-safety → 评估跨租户操作和数据修复风险
security-engineer → 评审敏感数据和权限边界
backend-engineer → 实现租户中间件
qa-engineer → 跨租户越权回归用例
references/consistency-multitenancy-guide.md — ACID 深度、Saga 模式、SaaS 多租户三种架构对比、RLS 实战、PostgreSQL 隔离级别真相、Slack / Notion 真实案例まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
A/B 测试设计与分析时使用。适用于产品实验、功能验证、转化率优化。融合假设驱动 + 样本量计算 + 置信度判断。
日本語の概要は準備中です。原文の説明を表示しています。
上线前业务方/产品方验收时使用。适用于功能交付确认、UAT、发布会签。融合 BDD Given-When-Then、Specification by Example、ATDD。
日本語の概要は準備中です。原文の説明を表示しています。
设计无障碍可访问的界面时使用。适用于满足 WCAG 标准、键盘导航、屏幕阅读器支持。优先使用 WCAG 2.2 AA 级标准 + 键盘 + 焦点 + 对比度 + ARIA。
日本語の概要は準備中です。原文の説明を表示しています。
实现可访问性(无障碍)时使用。覆盖 WCAG 2.2 AA / ARIA / 键盘导航 / 屏幕阅读器 / 颜色对比 / 焦点管理。融合 React Aria / Radix UI / Headless UI 实践 + axe-core 自动化测试。
日本語の概要は準備中です。原文の説明を表示しています。
AI 模型部署时使用。适用于推理服务 / GPU / TensorRT / 监控 / 扩缩容。
日本語の概要は準備中です。原文の説明を表示しています。
数据分析报告输出时使用。适用于业务分析报告、周报、专项分析、决策支持。融合洞察 + 建议 + 行动项。
日本語の概要は準備中です。原文の説明を表示しています。