3. Redis基础回顾:常用数据结构、命令、连接方式、错误码分类
在契约测试中,对Redis错误码的断言依赖于对Redis底层通信机制的准确理解。本节系统梳理Redis的核心数据结构、操作命令、连接模式及错误码体系,为后续构建搜索服务的契约测试用例奠定基础。
3.1 常用数据结构与适用场景
Redis提供多种数据结构,搜索服务中高频使用的包括以下五种:
| 数据结构 | 内部编码 | 典型搜索场景 | 时间复杂度 |
|---|---|---|---|
| String | int / embstr / raw | 缓存搜索结果摘要、存储API限流计数器 | O(1) |
| Hash | ziplist / hashtable | 存储文档元数据(标题、摘要、得分) | O(1) 单字段 |
| List | quicklist | 消息队列、搜索日志写入管道 | O(1) 头尾操作 |
| Set | intset / hashtable | 去重索引、标签集合运算 | O(1) 成员判断 |
| Sorted Set | ziplist / skiplist | 搜索热词排名、分页排序 | O(log N) 插入/查询 |
契约测试关注点: 不同数据结构在序列化/反序列化时可能产生不同的错误码。例如,对Hash类型执行String命令会返回
WRONGTYPE 错误,契约测试中需针对此类操作断言特定错误码。
3.2 核心命令分类与错误码映射
Redis命令按功能分为五类,每类命令在契约测试中对应不同的错误码断言策略:
- 键管理命令:
DEL、EXISTS、EXPIRE、TTL— 错误码多为WRONGTYPE(类型不匹配)或NOSCRIPT(脚本不存在)。 - 字符串命令:
GET、SET、INCR、MGET— 常见错误码WRONGTYPE、OOM(内存不足)。 - 哈希命令:
HGET、HSET、HGETALL— 错误码WRONGTYPE、NOSCRIPT。 - 集合命令:
SADD、SMEMBERS、SINTER— 错误码WRONGTYPE、BUSYGROUP(流消费组冲突)。 - 有序集合命令:
ZADD、ZRANGE、ZREVRANK— 错误码WRONGTYPE、MIN/MAX参数格式错误。
# 契约测试中典型的错误码断言示例(伪代码)
# 对Hash类型执行List命令,期望返回WRONGTYPE
> LPUSH doc:123 "value"
(error) WRONGTYPE Operation against a key holding the wrong kind of value
# 内存超限时写入失败
> SET cache:key "large_value"
(error) OOM command not allowed when used memory > 'maxmemory'
3.3 连接方式与通信协议
Redis支持三种连接方式,每种方式在契约测试中影响错误码的传输格式:
| 连接方式 | 协议 | 端口 | 错误码传输特点 |
|---|---|---|---|
| 单机TCP | RESP2 / RESP3 | 6379 | 错误码以 -ERR 前缀行内返回 |
| Sentinel高可用 | RESP2 + 哨兵协议 | 26379 | 主从切换时返回 READONLY 或 MASTERDOWN |
| Cluster集群 | RESP2 + 集群协议 | 6379+ | 槽位错误 MOVED / ASK 重定向 |
契约测试关键点: 在Cluster模式下,
MOVED 和 ASK 错误码是正常重定向信号,而非异常。契约测试需区分“业务错误码”与“协议重定向码”,避免误判。
3.4 错误码分类体系
Redis错误码按来源分为六大类,契约测试中需针对每类设计不同的断言逻辑:
- 语法错误(-ERR): 命令格式错误、参数数量不对。例如
ERR wrong number of arguments for 'get' command。 - 类型错误(-WRONGTYPE): 对错误的数据结构执行操作。搜索服务中常见于误用Hash/List命令。
- 权限/认证错误(-NOAUTH / -NOPERM): 未认证或ACL权限不足。契约测试需模拟认证失败场景。
- 资源限制错误(-OOM / -LOADING): 内存超限或持久化加载中。搜索服务高并发时易触发。
- 集群重定向错误(-MOVED / -ASK): 槽位迁移或重分配。契约测试需验证客户端重试逻辑。
- 主从错误(-READONLY / -MASTERDOWN): 从节点只读或主节点宕机。搜索服务读多写少场景需覆盖。
常见陷阱: 契约测试中容易将
MOVED 错误码当作异常处理,导致测试误报。正确做法是:在Cluster模式下,MOVED 应触发客户端自动重定向,契约测试应断言重定向后的正确响应,而非直接断言错误。
3.5 Redis通信协议与错误码传输机制
下图展示了RESP2协议下错误码的传输链路,以及契约测试中如何捕获并断言错误码:
3.6 契约测试中的错误码断言策略
基于上述分类,在搜索服务的契约测试中,建议采用以下断言策略:
- 精确匹配: 对
WRONGTYPE、OOM等确定性错误码,使用字符串精确匹配。 - 前缀匹配: 对
ERR类错误(如参数错误),使用前缀匹配-ERR并验证错误描述中的关键词。 - 重定向忽略: 在Cluster模式下,契约测试应忽略
MOVED和ASK错误码,转而验证客户端是否成功重试并返回正确结果。 - 超时与连接错误: 网络层面的超时错误(如
ETIMEDOUT)不属于Redis错误码,契约测试需单独设计超时断言逻辑。
// 契约测试中错误码断言示例(Java + Jedis)
@Test
void testWrongTypeError() {
try {
jedis.lpush("hashKey", "value"); // 对Hash类型执行List命令
fail("Expected WRONGTYPE error");
} catch (JedisDataException e) {
assertTrue(e.getMessage().startsWith("WRONGTYPE"));
assertEquals("Operation against a key holding the wrong kind of value",
e.getMessage().substring(10));
}
}
@Test
void testClusterRedirect() {
// 契约测试不直接断言MOVED,而是验证重试后的结果
String result = clusterJedis.get("key_on_another_slot");
assertNotNull(result);
assertEquals("expected_value", result);
}
最佳实践: 在契约测试中,建议将Redis错误码断言封装为独立的断言工具类,支持正则匹配、前缀匹配和精确匹配三种模式。这样当Redis版本升级导致错误描述微调时,只需修改工具类,无需逐个调整测试用例。