Skip to content

Redis 客户端

RedisClient 是池化的命令执行入口:每次命令从连接池借一条连接、完成一次"编码 → 写出 → 读回复"往返后归还。注入方式:

cangjie
@Inject
var redis: RedisClient

命令 API

string / key

cangjie
redis.get(key): ?String                       // GET,键不存在返回 None
redis.set(key, v): Bool                       // SET
redis.setPx(key, v, ttlMs): Bool              // SET k v PX ttl(带毫秒过期)
redis.setNxPx(key, v, ttlMs): Bool            // SET k v NX PX ttl(不存在才写,锁原语)
redis.del([k1, k2]): Int64                    // DEL,返回删除数
redis.exists(key): Bool
redis.pexpire(key, ttlMs): Bool
redis.pttl(key): Int64                        // 剩余毫秒;-1 无过期,-2 键不存在
redis.incr(key): Int64
redis.incrBy(key, n): Int64

hash

cangjie
redis.hget(key, field): ?String
redis.hset(key, field, v): Int64              // 返回新建字段数(覆盖已有计 0)
redis.hdel(key, [f1, f2]): Int64
redis.hexists(key, field): Bool
redis.hlen(key): Int64
redis.hgetAll(key): Array<(String, String)>   // 整表 (field, value) 对

list

cangjie
redis.lpush(key, [v1, v2]): Int64             // 返回压入后长度
redis.rpush(key, [v1, v2]): Int64
redis.lpop(key): ?String
redis.rpop(key): ?String
redis.lrange(key, start, stop): Array<String> // 闭区间,-1 为末尾;(k, 0, -1) 取整表
redis.llen(key): Int64

set / zset

cangjie
redis.sadd(key, [m1, m2]): Int64              // 返回新增成员数
redis.srem(key, [m1]): Int64
redis.sismember(key, m): Bool
redis.smembers(key): Array<String>
redis.scard(key): Int64

redis.zadd(key, score, member): Int64         // score: Float64
redis.zscore(key, member): ?Float64
redis.zrange(key, start, stop): Array<String>
redis.zrangeByScore(key, minScore, maxScore): Array<String>
redis.zrem(key, [m1]): Int64
redis.zcard(key): Int64

脚本 / 发布 / 逃生舱

cangjie
redis.eval(script, keys, args): RespValue     // EVAL Lua 脚本
redis.publish(channel, message): Int64        // 返回收到消息的订阅者数
redis.ping(): Bool
redis.raw(["OBJECT", "ENCODING", "k"]): RespValue  // 任意命令,拿原始 RespValue

RespValue 提供 asString(): ?String / asInt(): Int64 / asArray(): Array<RespValue> / isOk(): Bool 收窄方法。

连接池

池参数来自 [redis]pool.* 配置:

  • borrow:优先复用空闲连接(LIFO)→ 未达 pool.max 时新建(锁外建连不阻塞他人)→ 已满阻塞等归还
  • 预热pool.min > 0 时启动即建好常驻连接(连不上会抛错,等效 fail-fast)
  • 空闲回收:空闲超过 pool.idleTimeoutMs 且总数高于 pool.min 的连接被惰性关闭
  • 毒连接不回流:IO 出错的连接被标记 broken,归还时直接销毁并让出名额,下次借用新建健康连接

每条连接在建立时完成 AUTH(有密码)与 SELECT dbdb > 0)握手,池内连接始终处于就绪状态,借用方零感知。

错误语义

两类异常严格区分:

异常含义连接处置
RedisException服务端错误回复(-ERR / -WRONGTYPE 等)、协议违例、回复类型不符连接保活,正常归还复用
RedisConnectionExceptionIO 失败 / 超时 / 对端关闭连接销毁重建(discard)

命令不自动重试INCRLPUSH 等命令非幂等,连接级异常时自动重试有重复执行风险。ace-redis 只做连接自愈(坏连接销毁、下次借用新建),命令层面把异常抛给调用方决定。需要重试语义的幂等操作可配合 @Retry[n] 宏。

cangjie
try {
    redis.incr("counter")
} catch (e: RedisConnectionException) {
    // Redis 不可达:降级/告警,勿盲目重试非幂等命令
}

已知边界

  • 值按 UTF-8 文本处理(RespBulk(String)),暂不支持存取任意二进制值;二进制数据先做 Base64 等文本编码
  • 单连接一次只跑一个命令往返,暂无 pipeline / RESP3 / Cluster 支持

基于 Apache-2.0 许可证发布