LogoArcartX Doc

云审核与多服部署

配置百度审核、MySQL 同步、降级策略和运行边界

云审核与多服部署

Redact 始终先执行本地检测。只有同时满足以下条件,才会请求百度:

  1. 本地词库没有命中;
  2. 没有命中已确认的云审核内容;
  3. 调用方传入 enableCloud=true
  4. baidu.yml 中的 enabledtrue
  5. MySQL 与云审核运行条件可用。

启用百度审核

先在 database.yml 中启用并填写 MySQL:

enabled: true
 
mysql:
  host: "127.0.0.1"
  database: "arcartx"
  username: "arcartx"
  password: "请填写密码"

再在 baidu.yml 中启用云审核:

enabled: true
api-key: "请填写 API Key"
secret-key: "请填写 Secret Key"

百度凭据,也可以使用环境变量:

REDACT_BAIDU_API_KEY
REDACT_BAIDU_SECRET_KEY

环境变量优先于 YAML。

启用百度审核时,database.yml 中的 enabled 必须为 true,以便保存并同步云审核结果。

降级与 fail-closed

fail-closed: true

百度已经启用后,如果云审核服务尚未就绪、请求失败、结果未能保存或请求过多,Redact 返回 ERROR

  • fail-closed: trueisViolation=true,净化 API 返回单个替换文本;
  • fail-closed: falseisViolation=false,由上层业务记录或安排重试。

服务端没有启用百度时,允许云审核的 API 会退化为本地检测,不会返回这类 ERROR,也不会应用 fail-closed。

选择策略时需要考虑业务性质:公开聊天通常更关注即时拦截,玩家投稿、邮件或长文本则更适合暂存后重试或复审。

长文本与分片

百度单次文本审核上限为 20,000 UTF-8 字节。Redact 默认按 19,000 字节分片,为请求留出余量:

max-request-bytes: 19000
max-chunks: 16
chunk-overlap-codepoints: 64

相邻分片会保留重叠上下文,但超过重叠长度的跨片内容仍可能无法由单个云端分片识别。超过 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 词库仍是本地文件,不会自动上传到数据库。

写入与错误语义

云端返回 REJECTREVIEW 后,共享词和云命中记录会在同一个 MySQL 事务中提交。只有事务提交成功,当前节点才会更新本地学习词和精确正文缓存。

写入失败时,本次审核返回 ERROR,并暂停发起新的云请求,直到数据库恢复。失败结果不会提前进入任一节点的本地缓存,因此不会形成只在单个子服生效的未持久化数据。

记录保留与清理

record-retention-days: 7
cleanup-interval-minutes: 30

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.ymlsync-interval-seconds 周期。