云审核与多服部署
配置百度审核、MySQL 同步、降级策略和运行边界
云审核与多服部署
Redact 始终先执行本地检测。只有同时满足以下条件,才会请求百度:
- 本地词库没有命中;
- 没有命中已确认的云审核内容;
- 调用方传入
enableCloud=true; baidu.yml中的enabled为true;- MySQL 与云审核运行条件可用。
启用百度审核
先在 database.yml 中启用并填写 MySQL:
再在 baidu.yml 中启用云审核:
百度凭据,也可以使用环境变量:
环境变量优先于 YAML。
启用百度审核时,database.yml 中的 enabled 必须为 true,以便保存并同步云审核结果。
降级与 fail-closed
百度已经启用后,如果云审核服务尚未就绪、请求失败、结果未能保存或请求过多,Redact 返回 ERROR:
fail-closed: true:isViolation=true,净化 API 返回单个替换文本;fail-closed: false:isViolation=false,由上层业务记录或安排重试。
服务端没有启用百度时,允许云审核的 API 会退化为本地检测,不会返回这类 ERROR,也不会应用 fail-closed。
选择策略时需要考虑业务性质:公开聊天通常更关注即时拦截,玩家投稿、邮件或长文本则更适合暂存后重试或复审。
长文本与分片
百度单次文本审核上限为 20,000 UTF-8 字节。Redact 默认按 19,000 字节分片,为请求留出余量:
相邻分片会保留重叠上下文,但超过重叠长度的跨片内容仍可能无法由单个云端分片识别。超过 max-chunks 能承载的文本会按错误策略处理。
MySQL 数据
Redact 使用两张固定表:
| 表 | 内容 |
|---|---|
redact_dictionary | 云审核学习到的共享词条、分类、来源与创建节点 |
redact_cloud_hits | 短期保存的违规正文、正文哈希、判定、云端标识、来源节点、出现次数与过期时间 |
词条哈希和正文哈希使用唯一键去重。多个子服同时写入相同命中时,不需要额外的进程间锁。
API 查询只读取内存中的词库和缓存,不会为每条玩家消息同步访问 MySQL。
多子服配置
所有节点应:
- 连接同一个 MySQL 数据库;
- 使用不同的
server-id; - 保持相同的
matcher.case-sensitive; - 保持相同的
matcher.ignore-separators; - 根据数据库规模设置合理的连接池与同步周期;
- 让系统时间保持同步。
新学习词按自增 ID 同步;仍在保留期内的云命中正文按更新时间和 ID 增量同步。同步周期由 database.yml 中的 sync-interval-seconds 控制。当前节点的 YAML 词库仍是本地文件,不会自动上传到数据库。
写入与错误语义
云端返回 REJECT 或 REVIEW 后,共享词和云命中记录会在同一个 MySQL 事务中提交。只有事务提交成功,当前节点才会更新本地学习词和精确正文缓存。
写入失败时,本次审核返回 ERROR,并暂停发起新的云请求,直到数据库恢复。失败结果不会提前进入任一节点的本地缓存,因此不会形成只在单个子服生效的未持久化数据。
记录保留与清理
redact_cloud_hits 用于短期复用云审核结果,不是永久审计日志。完整原文默认保留 7 天,可配置为 1~90 天;重复命中相同正文会刷新保留期限。运行中节点的内存缓存会在到期后停止匹配,无需等待重启;后台任务按 expires_at 索引分批清理数据库记录,默认每 30 分钟执行一次。
redact_dictionary 是长期参与审核的共享词库。整段正文过期后,已经学习出的明确局部词条仍会保留;归一化后等于整段审核正文的片段不会进入长期词表。需要长期审计时,应由上层业务建立独立、具有访问控制和清理策略的审计记录。
数据库增长不与 API 调用总量直接对应:本地命中、本地通过和云端通过均不会写入 MySQL。redact_cloud_hits 的稳态行数约为“每日不同云命中正文数 × record-retention-days”;redact_dictionary 的行数约为累计去重后的有效学习词数。实际磁盘还会受到正文长度、索引、InnoDB 页利用率、二进制日志和备份策略影响,应使用生产样本复测并预留空间。
性能与容量建议
- 只判断是否违规时使用
contains,避免创建命中列表; - 只有需要分类和位置时才使用
check; - 不要把
matcher.max-reported-hits设置得接近无界; - 大词库应按真实词条长度、共同前缀和 JVM 堆容量测试;
- 长文本和批量审核应在业务异步线程执行;
- 云 API 仍会在调用线程完成本地扫描,主线程不得循环提交大量文本或等待 future;
- 当前节点内相同正文的进行中请求会合并为一次云调用,不同正文的突发流量由有界队列吸收,溢出后返回
ERROR; - 云端吞吐同时受工作线程、队列容量、百度账户限流和 MySQL 可用性影响,玩家级频率限制由调用方业务负责;
matcher.exact-cache-size越大,内存可保留的有效云命中正文哈希越多,占用内存也越高;- 云命中表只保留配置时间窗口内的数据,清理依赖
expires_at索引。
排查顺序
本地词条没有命中
确认 words.yml 层级正确,修改后已经完整重启;再检查大小写和分隔符配置是否符合预期。
调用 enableCloud=true 但没有云请求
检查 baidu.yml 中的 enabled、API Key、Secret Key,以及 database.yml 是否启用。调用参数不会覆盖服务端开关。
云审核持续返回 ERROR
检查 HTTP 与数据库日志、连接超时、请求超时、队列容量、云审核结果写入和百度账户状态。根据业务需要确认 fail-closed 是否应保持开启。
子服没有收到学习词
确认各节点连接同一个数据库,归一化配置一致,并等待至少一个 database.yml 的 sync-interval-seconds 周期。
