3、错误码设计原则
在 Redis 哨兵模式的安全合规断言验证体系中,错误码是后端与客户端、运维监控、审计系统之间沟通的“通用语言”。一套规范、统一、可扩展的错误码设计,能大幅降低排障成本,提升合规审计的透明度。本节从格式统一、分类分层、文档化三个维度展开。
3.1 统一错误码格式
所有错误码必须遵循固定的数字格式,避免出现“A001”、“ERR-100”等风格混杂的编码。推荐采用 5 位数字 结构,前 2 位标识模块或层级,后 3 位标识具体错误。
| 错误码 | 格式说明 | 示例 |
|---|---|---|
10001 |
系统级异常(通用) | 系统内部错误 |
20015 |
业务级异常(哨兵切换) | 哨兵主从切换超时 |
30042 |
安全级异常(认证/授权) | 哨兵连接密码错误 |
格式硬性规则:
- 纯数字,无字母、无连字符、无下划线。
- 固定 5 位长度,不足前补零(如
01001)。 - 每个错误码对应唯一的 英文标识符(如
SENTINEL_FAILOVER_TIMEOUT),用于代码内部断言。
3.2 错误码分类:系统级、业务级、安全级
根据 Redis 哨兵场景的运维与合规需求,将错误码划分为三个层级,每个层级预留充足的编码空间。
| 分类 | 编码范围 | 典型场景(哨兵模式) | 合规关注点 |
|---|---|---|---|
| 系统级 | 10001 – 19999 | Redis 连接池耗尽、哨兵进程崩溃、磁盘 I/O 异常 | 基础设施故障告警、SLA 监控 |
| 业务级 | 20001 – 29999 | 主从切换失败、哨兵选举超时、数据同步延迟 | 业务连续性审计、切换记录可追溯 |
| 安全级 | 30001 – 39999 | 哨兵密码错误、ACL 权限不足、TLS 握手失败 | 等保 2.0 合规、访问控制审计 |
设计建议: 安全级错误码应避免在响应体中返回过于详细的堆栈信息(如“密码错误” vs “用户不存在”),防止攻击者利用错误码差异进行枚举攻击。建议统一返回
30001(认证失败),详细原因记录在服务端审计日志中。
3.3 错误码文档化
错误码文档化是合规审计的硬性要求,也是团队协作的“活字典”。文档化包含三个层次:代码内注解、独立错误码手册、自动化断言映射表。
3.3.1 代码内注解(Java 枚举示例)
/**
* 哨兵模式错误码枚举
* 分类:安全级 (30001-39999)
* 合规要求:等保 2.0 三级 - 身份鉴别
*/
public enum SentinelErrorCode {
// 系统级
SYS_CONNECTION_POOL_EXHAUSTED(10001, "Redis连接池耗尽"),
SYS_SENTINEL_PROCESS_DOWN(10002, "哨兵进程不可达"),
// 业务级
BIZ_FAILOVER_TIMEOUT(20015, "哨兵主从切换超时"),
BIZ_REPLICATION_LAG(20023, "数据同步延迟超过阈值"),
// 安全级
SEC_AUTH_FAILED(30001, "哨兵连接认证失败"),
SEC_ACL_DENIED(30042, "ACL权限不足"),
SEC_TLS_HANDSHAKE_FAILED(30055, "TLS握手失败");
private final int code;
private final String message;
SentinelErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() { return code; }
public String getMessage() { return message; }
}
3.3.2 独立错误码手册(表格结构)
| 错误码 | 英文标识符 | 中文描述 | 分类 | 合规标签 |
|---|---|---|---|---|
10001 |
SYS_CONNECTION_POOL_EXHAUSTED | Redis连接池耗尽 | 系统级 | SLA |
20015 |
BIZ_FAILOVER_TIMEOUT | 哨兵主从切换超时 | 业务级 | BCP |
30001 |
SEC_AUTH_FAILED | 哨兵连接认证失败 | 安全级 | 等保2.0 |
30042 |
SEC_ACL_DENIED | ACL权限不足 | 安全级 | 等保2.0 |
3.3.3 自动化断言映射表
在测试框架或断言验证工具中,维护一份 错误码 → 断言策略 的映射关系,实现自动化验证。
// 伪代码:断言映射表
Map<Integer, AssertionStrategy> errorCodeAssertionMap = new HashMap<>() {{
put(10001, new SystemAssertion()); // 触发基础设施告警
put(20015, new RetryAssertion()); // 自动重试 + 记录切换日志
put(30001, new AuditAssertion()); // 记录审计日志,不返回详细原因
put(30042, new AuditAssertion()); // 同上
}};
合规避坑提醒:
- 错误码手册必须纳入版本管理(Git),每次新增或修改错误码需经过安全合规评审。
- 安全级错误码的响应体禁止返回
stackTrace或detailMessage,防止信息泄露。 - 文档化不是一次性工作,建议在 CI/CD 流水线中加入错误码覆盖率检查,确保每个错误码都有对应的文档条目。