按需求查找
| 想做什么 | 优先查哪里 | 代表操作 |
|---|---|---|
| 缓存、验证码、计数、条件写入 | 字符串 | SET、GET、INCR、SET ... NX EX |
| 过期时间、删缓存、找 key | 通用键操作 | EXPIRE、TTL、UNLINK、SCAN |
| 存对象、改字段、记录投票方向 | 哈希 | HSET、HGET、HINCRBY |
| 排行榜、帖子排序、按分数筛选 | 有序集合 | ZADD、ZRANGE、ZINCRBY |
| 去重、成员判断、共同关注 | 集合 | SADD、SISMEMBER、SINTER |
| 简单队列、保留最近若干条记录 | 列表 | RPUSH、BLPOP、LTRIM |
| 批量请求、原子更新、比较后修改 | 批处理与事务、Lua 脚本 | Pipeline、MULTI、WATCH、EVAL |
| 连接调试、服务端时间、慢命令 | 连接与诊断、redis-cli | PING、TIME、INFO、SLOWLOG GET |
| 消息确认、失败后重新处理 | 流 | XREADGROUP、XACK、XAUTOCLAIM |
| 实时广播、签到、估算去重数、附近的人 | 发布订阅、位图与位域、HyperLogLog、地理空间 | PUBLISH、SETBIT、PFCOUNT、GEOSEARCH |
| 在 Go 中调用 Redis | go-redis | .Result()、.Err()、ZAddNX、NewScript |
读表时常见的词 key 是 Redis 键名;field 是 Hash 字段;member 是 Set/ZSet 成员;score 是 ZSet 分数;TTL 是剩余生存时间。nil 表示空回复,和空字符串、数字 0 不同。相同选项在不同命令中可能含义不同,以所在行的说明为准。
字符串
用于缓存字符串或序列化后的 JSON,也可保存供计数命令操作的数值。
| 命令 | 示例 | 注释 |
|---|---|---|
SET |
SET user:1:name Jasper |
设置或覆盖值,包括覆盖其他数据类型;默认清除原 TTL。 |
GET |
GET user:1:name |
读取字符串;key 不存在返回 nil,类型不符报错。 |
SET ... EX / PX |
SET session:1 token EX 1800 |
原子写入并设置 TTL;EX 为秒,PX 为毫秒。 |
SET ... NX |
SET lock:job random-token NX EX 30 |
仅在 key 不存在时写入;成功返回 OK,未写入返回 nil。 |
MGET |
MGET user:1:name user:2:name |
批量读取,顺序与参数一致;不存在或非字符串的项返回 nil。 |
MSET |
MSET user:1:name Jasper user:2:name Lee |
原子批量写入;覆盖目标值并清除各 key 原 TTL,不支持 EX。 |
INCR / DECR |
INCR page:views |
整数加 1 / 减 1,返回新值;不存在按 0 处理。 |
INCRBY / DECRBY |
DECRBY stock:1 2 |
按指定整数增减,返回新值;不会自动阻止库存变成负数。 |
INCRBYFLOAT |
INCRBYFLOAT weight:1 0.5 |
增加浮点数,可用负数减少;金额精确计算宜使用最小单位整数。 |
GETEX |
GETEX session:1 EX 1800 |
读取并刷新 TTL;PERSIST 可移除 TTL;不带选项则不改 TTL。 |
GETDEL |
GETDEL reset:token |
原子读取并删除字符串 key;不存在返回 nil。 |
SET ... XX |
SET session:1 new-token XX EX 1800 |
仅在 key 已存在时写入;不满足条件返回 nil。 |
SET ... KEEPTTL |
SET user:1:name Lee KEEPTTL |
覆盖值并保留原 TTL;原来不存在则创建无 TTL 的 key。 |
SET ... GET |
SET counter 0 GET |
写入新值并返回旧字符串值;旧值不存在返回 nil,写入仍可能成功。 |
SET ... EXAT / PXAT |
SET token:1 abc EXAT 1893456000 |
按 Unix 秒 / 毫秒时间戳设置到期时间,示例时间应替换。 |
MSETNX |
MSETNX a 1 b 2 |
所有目标 key 都不存在才全部写入;成功 1,否则 0。 |
STRLEN |
STRLEN user:1:name |
返回字节长度,非 Unicode 字符数;不存在返回 0。 |
APPEND |
APPEND text " world" |
追加字符串,返回追加后的字节长度;不存在则创建。 |
GETRANGE |
GETRANGE text 0 4 |
按字节下标截取,首尾均包含;支持负下标。 |
SETRANGE |
SETRANGE text 6 Redis |
从字节偏移量 6 开始覆盖;越界的空隙用零字节填充。 |
MSETEX |
MSETEX 2 a 1 b 2 EX 60 |
8.4+。原子批量写入并设置统一 TTL;2 是 key 数量。 |
SET ... IFEQ |
SET state:1 done IFEQ pending KEEPTTL |
8.4+。当前值等于 pending 才写入,适合简单比较后更新。 |
DELEX ... IFEQ |
DELEX lock:job IFEQ random-token |
8.4+。值匹配才原子删除;成功 1,未删除 0。 |
锁的边界 random-token 应替换为每次加锁生成的唯一随机值。释放锁必须比较令牌后原子删除;旧版本使用 Lua,不能直接 DEL。锁到期不代表业务已经结束,需要严格互斥的业务还须处理执行超时、续期和故障切换问题。
通用键操作
适用于各种数据类型,字段级 TTL 则见 Hash 部分。
| 命令 | 示例 | 注释 |
|---|---|---|
DEL |
DEL cache:user:1 cache:user:2 |
删除一个或多个 key,返回实际删除数量。 |
UNLINK |
UNLINK cache:large |
立即移除 key,内存异步回收;清理大 key 时优先考虑。 |
EXISTS |
EXISTS user:1 user:2 |
返回存在的 key 数量;重复传入同一 key 会重复计数。 |
EXPIRE / PEXPIRE |
EXPIRE session:1 1800 |
设置秒 / 毫秒 TTL;成功 1,key 不存在等情况返回 0。 |
TTL / PTTL |
TTL session:1 |
返回剩余秒 / 毫秒;-1 为无 TTL,-2 为 key 不存在。 |
SCAN |
SCAN 0 MATCH user:* COUNT 100 |
返回下一游标和一批 key;继续传回游标,直到返回 0。 |
TYPE |
TYPE user:1 |
查看数据类型;不存在返回 none。 |
EXPIRE ... NX / XX |
EXPIRE session:1 1800 NX |
7.0+。NX 仅在尚无 TTL 时设置;XX 仅在已有 TTL 时设置。 |
EXPIRE ... GT / LT |
EXPIRE session:1 3600 GT |
7.0+。仅延长 / 缩短到期时间;无 TTL 按无限远处理。 |
PERSIST |
PERSIST session:1 |
移除 key 的 TTL;成功 1,不存在或原本无 TTL 返回 0。 |
EXPIREAT / PEXPIREAT |
EXPIREAT token:1 1893456000 |
按 Unix 秒 / 毫秒时间戳设置到期时间。 |
EXPIRETIME / PEXPIRETIME |
EXPIRETIME token:1 |
7.0+。读取绝对到期时间戳;-1 无 TTL,-2 不存在。 |
SCAN ... TYPE |
SCAN 0 MATCH user:* COUNT 100 TYPE hash |
只返回指定类型;过滤不会变成按类型建立的索引查询。 |
RENAME |
RENAME user:1 user:1001 |
重命名并保留源 key 的 TTL;会覆盖目标 key,源不存在报错。 |
RENAMENX |
RENAMENX user:1 user:1001 |
仅在目标不存在时重命名;成功 1,目标存在 0。 |
COPY |
COPY user:1 user:1:backup |
复制 key;目标存在时默认不复制,加 REPLACE 可覆盖。 |
KEYS |
KEYS user:* |
一次扫描并返回所有匹配 key;可能阻塞服务,仅限受控调试。 |
TTL EXPIRE key 0、负 TTL 或过去的绝对到期时间会立即删除 key。INCR、HSET、LPUSH 等修改已有值的操作通常保留整个 key 的 TTL;普通 SET、MSET 覆盖值会清除 TTL。新建 key 也不会自动获得 TTL。
SCAN COUNT 100 是工作量提示,不保证返回 100 条;一轮可能为空或出现重复项。只有返回游标 0 才结束,不能用“本轮为空”判断结束。扫描无序且不提供快照,也不能直接当业务分页接口。HSCAN、SSCAN、ZSCAN 同样遵循这些规则。
哈希
用于对象字段、局部更新,以及 用户 ID → 投票方向 等映射。
| 命令 | 示例 | 注释 |
|---|---|---|
HSET |
HSET user:1 name Jasper age 20 |
写入多个字段,存在则覆盖;返回新增字段数,更新已有字段也可能返回 0。 |
HGET |
HGET user:1 name |
读取单个字段;key 或字段不存在返回 nil。 |
HMGET |
HMGET user:1 name age |
按参数顺序返回多个字段;不存在的项为 nil。 |
HGETALL |
HGETALL user:1 |
返回全部字段和值;大 Hash 使用 HSCAN 分批读取。 |
HDEL |
HDEL user:1 email avatar |
删除指定字段,返回实际删除数;最后一个字段删除后 key 也删除。 |
HEXISTS |
HEXISTS user:1 email |
字段存在返回 1,否则 0。 |
HINCRBY |
HINCRBY user:1 login_count 1 |
字段整数值增加指定增量,返回新值;不存在按 0 处理。 |
HLEN |
HLEN user:1 |
返回字段数量;key 不存在返回 0。 |
HSETNX |
HSETNX user:1 created_by api |
仅在字段不存在时写入;成功 1,已存在 0。 |
HSCAN |
HSCAN user:1 0 MATCH a* COUNT 100 |
游标遍历字段和值;MATCH 匹配字段名。 |
HINCRBYFLOAT |
HINCRBYFLOAT user:1 weight 0.5 |
字段浮点值增加指定增量,返回新值。 |
HKEYS / HVALS |
HKEYS user:1 |
分别返回全部字段名 / 值;大 Hash 慎用。 |
HSTRLEN |
HSTRLEN user:1 name |
返回字段值的字节长度;字段不存在返回 0。 |
HRANDFIELD |
HRANDFIELD user:1 2 WITHVALUES |
随机读取字段及值;正数数量不重复,负数允许重复。 |
HEXPIRE / HPEXPIRE |
HEXPIRE user:1 60 FIELDS 1 otp |
7.4+。设置字段级秒 / 毫秒 TTL;1 是字段数量。 |
HTTL / HPTTL |
HTTL user:1 FIELDS 1 otp |
7.4+。查看字段剩余秒 / 毫秒;字段无 TTL 为 -1,不存在为 -2。 |
HPERSIST |
HPERSIST user:1 FIELDS 1 otp |
7.4+。移除指定字段的 TTL,不改变整个 key 的 TTL。 |
HSETEX |
HSETEX user:1 EX 60 FIELDS 1 otp 123456 |
8.0+。原子写入字段并设置其 TTL,避免两条命令间留下空隙。 |
HGETEX |
HGETEX user:1 EX 60 FIELDS 1 otp |
8.0+。读取字段并刷新其 TTL。 |
HGETDEL |
HGETDEL user:1 FIELDS 1 otp |
8.0+。原子读取并删除指定字段。 |
两层 TTL EXPIRE user:1 作用于整个 Hash,HEXPIRE 作用于字段;整个 key 到期时所有字段一起删除。HSET 覆盖字段会清除该字段自身的 TTL,但保留整个 key 的 TTL。
有序集合
成员唯一,按 score 排序,适合排行榜、帖子列表和时间索引。
读写与排序
| 命令 | 示例 | 注释 |
|---|---|---|
ZADD |
ZADD rank 100 u1 95 u2 |
添加或更新成员分数;默认返回新增成员数,不统计仅改分数的成员。 |
ZRANGE |
ZRANGE rank 0 9 |
按分数升序取前 10 名;下标从 0 开始,结束下标包含在内。 |
ZRANGE ... REV |
ZRANGE rank 0 9 REV |
按分数降序取前 10 名;全部成员使用 0 -1。 |
ZRANGE ... WITHSCORES |
ZRANGE rank 0 9 REV WITHSCORES |
返回成员及分数;WITHSCORES 不改变排序。 |
ZSCORE |
ZSCORE rank u1 |
读取成员分数;成员不存在返回 nil。 |
ZINCRBY |
ZINCRBY rank 10 u1 |
增加成员分数并返回新分数;不存在则以增量为初始分数。 |
ZREM |
ZREM rank u1 u2 |
删除成员,返回实际删除数。 |
ZCARD |
ZCARD rank |
返回成员总数。 |
ZREVRANK / ZRANK |
ZREVRANK rank u1 |
返回降序 / 升序排名,从 0 开始;不存在返回 nil。 |
ZMSCORE |
ZMSCORE rank u1 u2 |
批量读取分数,保持参数顺序;不存在的项为 nil。 |
ZRANGE ... BYSCORE |
ZRANGE rank 80 100 BYSCORE |
查询 80 <= score <= 100,按分数升序。 |
ZRANGE ... BYSCORE REV |
ZRANGE rank 100 80 BYSCORE REV |
同一分数区间降序;参数顺序改成上界在前、下界在后。 |
ZRANGE ... BYSCORE LIMIT |
ZRANGE rank 100 80 BYSCORE REV LIMIT 0 10 |
从匹配结果中跳过 0 个、取 10 个;大偏移量仍有遍历开销。 |
ZCOUNT |
ZCOUNT rank 80 100 |
统计分数区间内的成员数量。 |
ZREMRANGEBYSCORE |
ZREMRANGEBYSCORE rank -inf 0 |
删除分数小于等于 0 的成员;返回删除数。 |
ZREMRANGEBYRANK |
ZREMRANGEBYRANK rank 0 9 |
删除升序排名前 10 个,即分数最低的 10 个。 |
ZSCAN |
ZSCAN rank 0 MATCH u* COUNT 100 |
游标遍历成员及分数;返回顺序不保证按分数排列。 |
条件写入与弹出
| 命令 | 示例 | 注释 |
|---|---|---|
ZADD ... NX |
ZADD rank NX 100 u1 |
只添加新成员,不覆盖已有成员的分数;对应 go-redis ZAddNX。 |
ZADD ... XX |
ZADD rank XX 110 u1 |
只更新已有成员,不新增;对应 ZAddXX。 |
ZADD ... GT / LT |
ZADD rank XX GT 120 u1 |
已有成员仅接受更高 / 更低分数;单用 GT、LT 仍允许新增。 |
ZADD ... CH |
ZADD rank CH 120 u1 |
返回新增和分数发生变化的成员总数;分数未变化不计入。 |
ZADD ... INCR |
ZADD rank XX INCR 10 u1 |
条件式增分,只能传一组分数和成员;条件不满足返回 nil。 |
ZPOPMAX / ZPOPMIN |
ZPOPMAX rank 2 |
原子移除并返回最高 / 最低分成员及分数,示例最多弹出 2 个。 |
BZPOPMAX / BZPOPMIN |
BZPOPMAX queue:priority 5 |
阻塞式弹出一个成员,超时单位秒;0 无限等待。 |
ZMPOP |
ZMPOP 2 z1 z2 MIN COUNT 3 |
7.0+。从第一个非空有序集合弹出最多 3 个最低分成员。 |
BZMPOP |
BZMPOP 5 2 z1 z2 MIN COUNT 3 |
7.0+。阻塞式 ZMPOP,首个参数是秒级超时。 |
集合运算与字典序
| 命令 | 示例 | 注释 |
|---|---|---|
ZINTERSTORE |
ZINTERSTORE common 2 z1 z2 |
交集存入目标;2 是输入 key 数,默认将相同成员分数相加。 |
ZINTERSTORE ... WEIGHTS |
ZINTERSTORE feed:go 2 posts:score community:go WEIGHTS 1 0 |
取两者交集并保留 posts:score 的分数;第二个输入可为 Set。 |
ZUNIONSTORE |
ZUNIONSTORE total 2 z1 z2 AGGREGATE MAX |
并集存入目标;聚合可选 SUM、MIN、MAX,默认 SUM。 |
ZINTER / ZUNION |
ZINTER 2 z1 z2 WITHSCORES |
直接返回交集 / 并集,可带分数;不创建目标 key。 |
ZDIFF / ZDIFFSTORE |
ZDIFF 2 z1 z2 WITHSCORES |
返回第一个集合减去后续集合的差集;保存形式为 ZDIFFSTORE out 2 z1 z2。 |
ZINTERCARD |
ZINTERCARD 2 z1 z2 |
7.0+。只返回交集成员数量。 |
ZRANGESTORE |
ZRANGESTORE top10 rank 0 9 REV |
将范围查询结果及原分数保存为新有序集合;会覆盖目标。 |
ZRANGE ... BYLEX |
ZRANGE names "[a" "(n" BYLEX |
查字典序 a <= member < n;要求集合内所有成员分数相同。 |
ZLEXCOUNT |
ZLEXCOUNT names "[a" "(n" |
统计指定字典序区间;同样要求所有分数相同。 |
ZREMRANGEBYLEX |
ZREMRANGEBYLEX names "[a" "(n" |
删除指定字典序区间内的成员。 |
区间速记 分数默认包含边界,(80 表示不含 80,-inf / +inf 表示无穷。字典序用 [ 包含、( 排除,- / + 表示无界。普通按排名分页直接使用 start stop;LIMIT offset count 仅用于 BYSCORE 或 BYLEX。
排序与选项 同分成员按字节字典序排序,REV 也会反转同分顺序。NX 与 XX 互斥,NX、GT、LT 三者互斥。score 使用双精度浮点数,整数精确范围为 [-2^53, 2^53];更大的整数 ID 应作为字符串成员保存。
集合
无序、成员唯一,适合去重、标签和关系判断。
| 命令 | 示例 | 注释 |
|---|---|---|
SADD |
SADD tags:1 go redis |
添加成员,重复项忽略;返回实际新增数。 |
SISMEMBER |
SISMEMBER tags:1 go |
成员存在返回 1,否则 0。 |
SREM |
SREM tags:1 redis |
删除成员,返回实际删除数。 |
SCARD |
SCARD tags:1 |
返回成员数量。 |
SMEMBERS |
SMEMBERS tags:1 |
返回全部成员,不保证顺序;大集合用 SSCAN。 |
SMISMEMBER |
SMISMEMBER tags:1 go redis |
批量判断成员是否存在,按参数顺序返回 1 / 0。 |
SSCAN |
SSCAN tags:1 0 MATCH g* COUNT 100 |
游标遍历成员;第一项是 key,第二项是游标。 |
SINTER |
SINTER following:u1 following:u2 |
返回交集,例如两人共同关注的用户。 |
SUNION |
SUNION tags:1 tags:2 |
返回去重后的并集。 |
SDIFF |
SDIFF following:u1 following:u2 |
返回第一个集合中存在、后续集合中都不存在的成员。 |
SPOP |
SPOP pool 2 |
随机移除并返回最多 2 个成员。 |
SRANDMEMBER |
SRANDMEMBER pool 2 |
随机读取,不删除;正数量不重复,负数量允许重复。 |
SMOVE |
SMOVE pending done task1 |
原子移动一个成员到目标集合;成功 1,源中不存在 0。 |
SINTERSTORE |
SINTERSTORE common users:a users:b |
交集写入目标集合,会覆盖目标。 |
SUNIONSTORE |
SUNIONSTORE all users:a users:b |
并集写入目标集合,会覆盖目标。 |
SDIFFSTORE |
SDIFFSTORE only:a users:a users:b |
差集写入目标集合,会覆盖目标。 |
SINTERCARD |
SINTERCARD 2 users:a users:b |
7.0+。只计算交集数量;2 是输入 key 数。 |
列表
按插入位置排列,允许重复成员。常见 FIFO 队列使用 RPUSH 入队、LPOP / BLPOP 出队。
| 命令 | 示例 | 注释 |
|---|---|---|
RPUSH |
RPUSH queue job1 job2 |
从右端依次插入,结果为 job1, job2;返回列表长度。 |
LPOP |
LPOP queue |
移除并返回左端元素;列表不存在返回 nil。 |
BLPOP |
BLPOP queue 5 |
无元素时最多等待 5 秒;返回 key 和元素,超时返回 nil。 |
LPUSH |
LPUSH recent item1 item2 |
从左端依次插入,最终左到右为 item2, item1。 |
RPOP / BRPOP |
BRPOP queue 5 |
从右端弹出;BRPOP 可按秒阻塞等待。 |
LRANGE |
LRANGE recent 0 9 |
返回前 10 个元素;首尾下标均包含,0 -1 返回全部。 |
LLEN |
LLEN queue |
返回列表长度;不存在返回 0。 |
LTRIM |
LTRIM recent 0 99 |
只保留指定区间,示例保留前 100 个;其他元素删除。 |
LPOP / RPOP 带数量 |
LPOP queue 3 |
一次弹出最多 3 个元素,返回数组。 |
LMOVE |
LMOVE queue processing LEFT RIGHT |
原子地从源左端弹出并推入目标右端;源为空返回 nil。 |
BLMOVE |
BLMOVE queue processing LEFT RIGHT 5 |
阻塞式移动,最后一个参数是秒级超时。 |
LREM |
LREM processing 1 job1 |
正数从左删、负数从右删,绝对值为数量;0 删除全部匹配项。 |
LINDEX |
LINDEX recent 0 |
读取指定下标;-1 表示最后一个,越界返回 nil。 |
LSET |
LSET recent 0 item0 |
修改指定下标的元素;key 不存在或下标越界报错。 |
LPOS |
LPOS recent item1 |
查找匹配元素的下标;无匹配返回 nil,COUNT 可取多个。 |
LINSERT |
LINSERT recent BEFORE item1 item0 |
在第一个匹配元素之前 / 之后插入;可选 BEFORE / AFTER。 |
LPUSHX / RPUSHX |
RPUSHX queue job3 |
仅在列表已存在时插入;不会创建新列表。 |
LMPOP |
LMPOP 2 q1 q2 LEFT COUNT 3 |
7.0+。从第一个非空列表弹出最多 3 个元素。 |
BLMPOP |
BLMPOP 5 2 q1 q2 LEFT COUNT 3 |
7.0+。阻塞式批量弹出,首个参数是秒级超时。 |
队列边界 上述阻塞命令的 0 表示无限等待。直接 LPOP / BLPOP 后消费者崩溃,消息可能丢失;LMOVE 到处理中列表仍需自行实现确认和超时重试。需要消费者组与待确认记录时,优先查看 Streams。
批处理与事务
先选机制,再查命令。单个 INCR、ZINCRBY 等命令本身已是原子操作。
| 机制 | 适用情况 | 注意 |
|---|---|---|
| Pipeline | 批量执行互不依赖的请求,减少网络往返 | 不保证整批原子性;结果在整批执行后读取。 |
MULTI + EXEC |
多条已知命令需要连续执行,期间不插入其他客户端命令 | 没有传统数据库式回滚。 |
WATCH + 事务 |
在 Go 中先读值,再计算,提交前检查值是否被修改 | 冲突后重读并有限重试;必须在同一连接完成。 |
| Lua | 根据 Redis 中的当前值判断并更新,例如扣库存、投票、释放锁 | 服务端原子执行,但运行错误不会撤销此前写入。 |
| 命令 | 示例 | 注释 |
|---|---|---|
MULTI |
MULTI |
开始事务,后续命令先排队,通常返回 QUEUED。 |
EXEC |
EXEC |
执行队列,返回各命令结果;WATCH 冲突时返回 nil,整批不执行。 |
WATCH |
WATCH stock:1 |
监视 key;必须在 MULTI 前调用,修改、过期、淘汰都可能导致冲突。 |
DISCARD |
DISCARD |
丢弃尚未执行的事务队列,同时取消监视。 |
UNWATCH |
UNWATCH |
取消当前连接对所有 key 的监视。 |
同一交互连接中逐行执行下面的命令,可将计数与设置 TTL 放入一个事务。
MULTI
INCR counter:demo
EXPIRE counter:demo 60
EXEC
这会在每次执行时刷新 TTL。固定窗口计数通常只在首次计数时设置 TTL,需要 Lua 或其他条件式实现。事务执行阶段某条命令失败,其他命令仍可能成功;不要把返回错误理解成“全部没有执行”。
Lua 脚本
执行与管理
| 命令 | 示例 | 注释 |
|---|---|---|
EVAL |
EVAL "return redis.call('GET', KEYS[1])" 1 user:1:name |
执行脚本;1 是 key 数量,后面先传 key,再传普通参数。 |
EVALSHA |
EVALSHA <sha1> 1 user:1:name |
用已缓存脚本的 SHA1 执行;缓存不存在返回 NOSCRIPT。 |
SCRIPT LOAD |
SCRIPT LOAD "return redis.call('GET', KEYS[1])" |
缓存脚本并返回 SHA1,不执行;示例可供上一行使用。 |
SCRIPT EXISTS |
SCRIPT EXISTS <sha1> |
检查指定脚本是否在当前服务器缓存中。 |
EVAL_RO / EVALSHA_RO |
EVAL_RO "return redis.call('GET', KEYS[1])" 1 user:1:name |
7.0+。执行只读脚本;包含写操作会报错。 |
<sha1> 需替换为 SCRIPT LOAD 返回的值。脚本缓存可能因重启、故障切换等丢失,应用必须处理 NOSCRIPT;go-redis 的普通客户端调用可使用 NewScript(...).Run(...)。
脚本中常查的语法
| 操作 | 示例 | 注释 |
|---|---|---|
KEYS[n] |
local key = KEYS[1] |
读取传入的 Redis key;所有访问的 key 都应显式传入,下标从 1 开始。 |
ARGV[n] |
local userID = ARGV[1] |
读取普通参数;Redis 传入脚本的参数是字符串。 |
redis.call() |
local value = redis.call("HGET", KEYS[1], ARGV[1]) |
调用 Redis 命令;命令错误会终止脚本。 |
tonumber() |
local n = tonumber(ARGV[2]) |
转成数字;转换失败返回 nil,应先校验再比较或计算。 |
tostring() |
return tostring(score) |
转成字符串;需要保留小数返回值时很有用。 |
TIME |
local now = tonumber(redis.call("TIME")[1]) |
读取服务端当前 Unix 秒;第二项为当前秒内的微秒数。 |
local |
local delta = new - old |
声明局部变量;Redis 脚本中的自定义变量应使用 local。 |
if ... then ... end |
if old == new then return 0 end |
条件判断,支持 elseif 和 else。 |
== / ~= / >= |
if now >= deadline then return 0 end |
~= 表示不等于;两侧应是可比较的值。 |
and / or / not |
if not n then return redis.error_reply("ERR invalid number") end |
逻辑运算;Lua 中只有 false、nil 为假,数字 0 也为真。 |
false / nil |
if value == false then return 0 end |
默认 RESP2 的空回复映射为 false;Lua 无值或转换失败用 nil。 |
return / {} |
return {old, new, delta} |
返回数组式 table;默认协议转换中直接返回小数会截去小数部分。 |
for / # |
for i = 1, #ARGV do redis.call("SADD", KEYS[1], ARGV[i]) end |
#ARGV 取序列长度;循环只处理有界、少量数据。 |
redis.pcall() |
local r = redis.pcall("INCR", KEYS[1]) |
捕获命令错误,错误回复可检查 r.err;不会自动回滚。 |
redis.error_reply() |
return redis.error_reply("ERR invalid argument") |
显式返回 Redis 错误,客户端会收到非空 error。 |
数值检查 先处理不存在的值,再做转换。tonumber(value) or 0 会把“缺失”和“非法数值”都变成 0,只能在业务确实允许时使用。用户 ID 等标识通常保持字符串,不要为了比较而随意转成 Lua 数字。
执行边界 脚本执行期间会阻塞其他命令,不要在脚本里做全库扫描或大循环。先校验参数和数据类型,再开始写入。默认脚本内部使用 RESP2 转换规则,不能仅因客户端采用 RESP3 就把空值判断改成 nil。
连接与诊断
| 命令 | 示例 | 注释 |
|---|---|---|
PING |
PING |
检查连接是否正常响应,通常返回 PONG。 |
TIME |
TIME |
返回两个字符串,分别为 Unix 秒和当前秒内的微秒数。 |
INFO |
INFO server |
查看版本与运行信息;常用分区有 memory、stats、clients、keyspace。 |
DBSIZE |
DBSIZE |
当前逻辑数据库的 key 数量,不是某类集合的元素数量。 |
MEMORY USAGE |
MEMORY USAGE user:1 |
估算指定 key 的内存占用,单位字节。 |
SLOWLOG GET |
SLOWLOG GET 10 |
读取最近的慢命令;耗时不包含与客户端通信的时间。 |
SLOWLOG LEN |
SLOWLOG LEN |
返回慢日志条数。 |
CLIENT LIST |
CLIENT LIST |
查看客户端连接;连接很多时注意回复规模。 |
CLIENT SETNAME |
CLIENT SETNAME bluebell-api |
命名当前连接,便于排障;连接池客户端通常通过配置统一设置。 |
CLIENT INFO / CLIENT ID |
CLIENT INFO |
查看当前连接信息 / ID。 |
CLIENT GETNAME |
CLIENT GETNAME |
读取当前连接名称。 |
AUTH |
AUTH default password |
认证当前连接;不要把真实密码写入共享记录。 |
SELECT |
SELECT 1 |
切换当前连接的逻辑数据库;Redis Cluster 仅支持 DB 0。 |
HELLO |
HELLO 3 |
协商 RESP 协议;使用客户端库时通常由库处理。 |
ACL WHOAMI |
ACL WHOAMI |
查看当前连接使用的 ACL 用户。 |
ACL LOG |
ACL LOG 10 |
查看最近的认证或权限拒绝记录,通常需要管理权限。 |
CONFIG GET |
CONFIG GET maxmemory maxmemory-policy |
查看运行配置;一次传多个参数模式需要 7.0+。 |
OBJECT ENCODING |
OBJECT ENCODING user:1 |
查看内部编码,用于理解内存和性能,不等同于 TYPE。 |
LATENCY LATEST |
LATENCY LATEST |
查看延迟监控事件;通常需先启用延迟监控阈值。 |
COMMAND INFO |
COMMAND INFO GET HEXPIRE |
检查服务端是否认识这些命令;不支持的命令对应项为 nil。 |
Cluster 提醒 多 key 命令、事务和 Lua 通常要求相关 key 位于同一 hash slot。需要关联的 key 可使用相同 hash tag,例如 order:{123}:data 与 order:{123}:lock。扫描整个集群要遍历各主节点,单次 SCAN 只扫描当前节点。
redis-cli
以下是终端中的 Shell 命令,redis 是示例容器名。
| 命令 / 选项 | 示例 | 注释 |
|---|---|---|
| 本机连接 | redis-cli |
默认连接 127.0.0.1:6379 并进入交互模式。 |
| 指定地址 | redis-cli -h 127.0.0.1 -p 6379 |
指定主机与端口。 |
| 认证 | redis-cli --user default --askpass |
交互输入密码;也支持预先配置 REDISCLI_AUTH 环境变量。 |
| Docker 容器 | docker exec -it redis redis-cli |
从容器内连接 Redis;按实际情况替换容器名和认证参数。 |
| 单次执行 | redis-cli GET user:1:name |
执行一条命令后退出。 |
| 选择数据库 | redis-cli -n 1 |
连接后选择 DB 1,不适用于 Cluster。 |
| 扫描 key | redis-cli --scan --pattern 'user:*' |
使用 SCAN 增量列出匹配 key;仍需考虑扫描负载和重复结果。 |
| 运行脚本文件 | redis-cli --eval unlock.lua lock:job , random-token |
逗号两侧要留空格;前面是 KEYS,后面是 ARGV。 |
| 大 key 排查 | redis-cli --bigkeys |
按类型统计字符串长度或容器元素数,不能直接当内存占用排名。 |
| 内存排查 | redis-cli --memkeys |
扫描 key 的内存占用;较新 CLI 可用 --keystats 综合统计。 |
| 延迟采样 | redis-cli --latency |
持续测量客户端到 Redis 的往返延迟。 |
| 实时统计 | redis-cli --stat |
持续输出 key 数、内存、连接、请求等统计。 |
| 跟随集群重定向 | redis-cli -c -h 127.0.0.1 -p 6379 |
自动跟随 MOVED / ASK;不会自动聚合全节点扫描。 |
| TLS 连接 | redis-cli --tls --cacert ca.pem -h redis.example.com |
使用 TLS 并验证服务端证书;不要用跳过验证代替正确配置。 |
CLI 选项是否可用取决于本机 redis-cli 的版本,可先运行 redis-cli --help。在 Shell 中执行原生命令时,*、>、$、( 等应按需加引号,例如 redis-cli XADD orders '*' id 1001。
流
Streams 可保存消息和消费者组的待确认记录。通常在业务处理成功后 XACK,处理逻辑应能承受重复投递。
生产、消费与确认
| 命令 | 示例 | 注释 |
|---|---|---|
XADD |
XADD orders * id 1001 status new |
追加消息,* 自动生成消息 ID;返回实际 ID。 |
XGROUP CREATE |
XGROUP CREATE orders workers 0 MKSTREAM |
创建组;0 从历史开始,$ 仅消费之后的新消息;MKSTREAM 可创建流。 |
XREADGROUP |
XREADGROUP GROUP workers c1 COUNT 10 BLOCK 5000 STREAMS orders > |
读取该组未投递过的新消息,记录到 PEL;BLOCK 单位毫秒。 |
XACK |
XACK orders workers 1710000000000-0 |
从该组的待确认列表 PEL 移除;不会删除流中的消息。 |
XPENDING |
XPENDING orders workers |
查看待确认消息总量、ID 范围及消费者概况。 |
XPENDING 明细 |
XPENDING orders workers - + 10 |
查看待确认消息 ID、所属消费者、空闲毫秒和投递次数。 |
XAUTOCLAIM |
XAUTOCLAIM orders workers c2 60000 0-0 COUNT 10 |
接管空闲至少 60000 毫秒的消息;按返回游标继续扫描,0-0 表示本轮结束。 |
XCLAIM |
XCLAIM orders workers c2 60000 1710000000000-0 |
接管指定的待确认消息;空闲阈值单位毫秒。 |
XREADGROUP 读待确认 |
XREADGROUP GROUP workers c1 COUNT 10 STREAMS orders 0 |
读取当前消费者自己尚未确认的消息,不是读取全部历史。 |
XREADGROUP ... CLAIM |
XREADGROUP GROUP workers c2 COUNT 10 CLAIM 60000 STREAMS orders > |
8.4+。优先接管超时待确认消息,再按规则读取新消息;返回结构可能附带接管信息。 |
XACKDEL |
XACKDEL orders workers ACKED IDS 1 1710000000000-0 |
8.2+。确认消息;ACKED 仅在所有组都已读取并确认时删除消息。 |
普通读取、清理与管理
| 命令 | 示例 | 注释 |
|---|---|---|
XREAD |
XREAD COUNT 10 STREAMS orders 0-0 |
不使用消费者组;读取指定 ID 之后的消息,不写入 PEL。 |
XREAD ... BLOCK |
XREAD BLOCK 5000 COUNT 10 STREAMS orders $ |
从当前末尾等待新消息;$ 仅用于首次定位,之后传上次最后读取的 ID。 |
XRANGE |
XRANGE orders - + COUNT 10 |
按 ID 升序读取,默认包含边界;- / + 表示最小 / 最大。 |
XREVRANGE |
XREVRANGE orders + - COUNT 10 |
按 ID 降序读取,取最近 10 条;上界在前。 |
XLEN |
XLEN orders |
返回流中仍保留的消息数量。 |
XADD ... MAXLEN |
XADD orders MAXLEN ~ 10000 * id 1002 |
追加时顺便近似裁剪;~ 不保证长度严格等于上限。 |
XTRIM |
XTRIM orders MAXLEN ~ 10000 |
裁剪旧消息;可能影响尚未处理的消息,保留策略须覆盖重试窗口。 |
XDEL |
XDEL orders 1710000000000-0 |
删除流中的消息;不等同于对消费者组执行确认。 |
XINFO GROUPS |
XINFO GROUPS orders |
查看消费者组及待确认量等状态。 |
XINFO CONSUMERS |
XINFO CONSUMERS orders workers |
查看消费者及其待确认数量等状态。 |
XINFO STREAM |
XINFO STREAM orders |
查看流长度、首尾 ID 等信息。 |
XGROUP CREATECONSUMER |
XGROUP CREATECONSUMER orders workers c2 |
显式创建消费者;通常也可由首次 XREADGROUP 自动创建。 |
XGROUP SETID |
XGROUP SETID orders workers 0 |
修改组的最后投递 ID;不等于清空 PEL,使用前确认重复投递影响。 |
XGROUP DELCONSUMER |
XGROUP DELCONSUMER orders workers c1 |
删除消费者;应先处理或转移其待确认消息,否则这些记录无法再接管。 |
XGROUP DESTROY |
XGROUP DESTROY orders workers |
删除消费者组及其 PEL,不删除流中的消息。 |
BLOCK 0 表示无限等待;这里的单位是毫秒,和列表阻塞命令的秒不同。PEL 是已投递但尚未确认的记录;不能只读取 > 而从不处理 PEL。Streams 的持久性还取决于 Redis 的持久化和复制配置。
发布订阅
适合在线实时通知。Pub/Sub 不保存离线消息、不提供确认和重放,断线期间的消息会丢失。
| 命令 | 示例 | 注释 |
|---|---|---|
PUBLISH |
PUBLISH notice:user:1 updated |
发布消息,返回接收客户端数;不代表业务处理成功。 |
SUBSCRIBE |
SUBSCRIBE notice:user:1 |
订阅频道并持续接收消息;通常使用专门的订阅连接。 |
UNSUBSCRIBE |
UNSUBSCRIBE notice:user:1 |
取消频道订阅;不带频道则取消当前连接的全部普通频道订阅。 |
PSUBSCRIBE |
PSUBSCRIBE notice:user:* |
按 glob 模式订阅,* 可匹配多个字符。 |
PUNSUBSCRIBE |
PUNSUBSCRIBE notice:user:* |
取消模式订阅。 |
PUBSUB NUMSUB |
PUBSUB NUMSUB notice:user:1 |
返回频道直接订阅者数,不包含模式订阅者。 |
PUBSUB CHANNELS |
PUBSUB CHANNELS notice:* |
查看存在直接订阅者的匹配频道,不包含仅由模式订阅覆盖的频道。 |
SSUBSCRIBE / SPUBLISH |
SPUBLISH notice:{1} updated |
7.0+。分片 Pub/Sub,配合 SSUBSCRIBE 使用;取消用 SUNSUBSCRIBE。 |
位图与位域
两者底层都是 String。位图保存单个 bit,位域把一段 bit 解释成整数。
位图
| 命令 | 示例 | 注释 |
|---|---|---|
SETBIT |
SETBIT signin:2026-09 17 1 |
设置第 17 个偏移位置的 bit,返回旧值;偏移量从 0 开始。 |
GETBIT |
GETBIT signin:2026-09 17 |
读取 bit;超出已有长度的位返回 0。 |
BITCOUNT |
BITCOUNT signin:2026-09 |
统计值为 1 的 bit 数,例如已签到天数。 |
BITCOUNT 字节范围 |
BITCOUNT flags 0 1 |
只统计第 0 到第 1 字节,首尾包含;默认范围单位为字节。 |
BITCOUNT ... BIT |
BITCOUNT flags 0 7 BIT |
7.0+。按 bit 范围统计,示例统计前 8 位。 |
BITOP |
BITOP AND active:both active:d1 active:d2 |
位运算后保存到目标;常用 AND、OR、XOR、NOT,NOT 只接一个源。 |
BITPOS |
BITPOS flags 1 |
查找第一个值为 1 的 bit 位置;也可查 0。 |
业务中的“第 18 天”可映射为偏移量 17,需自行统一规则。设置很大的偏移量会扩展底层字符串,使用稀疏的大整数 ID 前应评估内存占用。
位域
| 命令 | 示例 | 注释 |
|---|---|---|
BITFIELD ... SET |
BITFIELD stats SET u8 0 10 |
从第 0 位写入 8 位无符号整数,返回旧值;i8 表示 8 位有符号整数。 |
BITFIELD ... GET |
BITFIELD stats GET u8 0 |
读取指定宽度和偏移的整数。 |
BITFIELD ... INCRBY |
BITFIELD stats INCRBY u8 0 1 |
对指定位域加 1,返回新值。 |
BITFIELD ... OVERFLOW |
BITFIELD stats OVERFLOW SAT INCRBY u8 0 1 |
WRAP 回绕、SAT 保持在上下界、FAIL 不修改并返回空项;默认 WRAP。 |
BITFIELD_RO |
BITFIELD_RO stats GET u8 0 |
只读执行位域 GET。 |
HyperLogLog
用于低内存的近似去重计数,不能取回成员,也不能判断某个成员是否已出现。
| 命令 | 示例 | 注释 |
|---|---|---|
PFADD |
PFADD uv:day u1 u2 |
加入观测值;返回结构是否变化,不能作为精确的新增人数。 |
PFCOUNT |
PFCOUNT uv:day |
返回不同元素数量的估计值。 |
PFCOUNT 多 key |
PFCOUNT uv:d1 uv:d2 |
返回多个 HyperLogLog 并集的估计数量,不是简单相加。 |
PFMERGE |
PFMERGE uv:week uv:d1 uv:d2 |
合并多个 HyperLogLog 到目标 key。 |
地理空间
适合附近地点、距离计算。坐标顺序始终是经度在前、纬度在后。
| 命令 | 示例 | 注释 |
|---|---|---|
GEOADD |
GEOADD stores 113.26 23.13 gz 114.06 22.54 sz |
写入或更新地点坐标;成员唯一。 |
GEOSEARCH |
GEOSEARCH stores FROMLONLAT 113.26 23.13 BYRADIUS 5 km ASC COUNT 10 WITHDIST |
查中心坐标 5 千米内最近的 10 个地点,并返回距离。 |
GEOSEARCH ... FROMMEMBER |
GEOSEARCH stores FROMMEMBER gz BYBOX 10 20 km |
以已有成员为中心,查宽 10、高 20 千米的矩形范围。 |
GEODIST |
GEODIST stores gz sz km |
计算两个成员距离;单位可选 m、km、mi、ft。 |
GEOPOS |
GEOPOS stores gz sz |
读取成员坐标,不存在的项返回 nil。 |
GEOSEARCHSTORE |
GEOSEARCHSTORE nearby stores FROMMEMBER gz BYRADIUS 5 km |
将搜索结果保存到目标;加 STOREDIST 可用距离作为分数。 |
ZREM |
ZREM stores gz |
删除地理成员;GEO 底层使用有序集合。 |
GEOHASH |
GEOHASH stores gz |
返回位置的 geohash 字符串。 |
管理与高风险操作
以下操作可能修改配置、删除数据或增加负载,使用前确认实例、权限与备份。ASYNC 只改变释放内存的方式,不提供撤销能力。
| 命令 | 示例 | 注释 |
|---|---|---|
BGSAVE |
BGSAVE |
后台生成 RDB 快照;创建子进程等过程仍可能带来停顿和内存压力。 |
LASTSAVE |
LASTSAVE |
返回最近一次成功保存 RDB 的 Unix 秒时间戳。 |
BGREWRITEAOF |
BGREWRITEAOF |
后台重写 AOF,重建更紧凑的日志;关注磁盘和内存资源。 |
CONFIG SET |
CONFIG SET maxmemory 512mb |
修改运行配置;先确认内存限制与淘汰策略是否适合实例。 |
CONFIG REWRITE |
CONFIG REWRITE |
将当前配置重写到启动配置文件;需要文件存在且可写。 |
MONITOR |
MONITOR |
实时查看命令,开销大且可能暴露业务参数;仅短时、受控排障。 |
CLIENT KILL |
CLIENT KILL ID 42 |
关闭指定连接;可能影响正在处理的请求。 |
SCRIPT KILL |
SCRIPT KILL |
尝试终止尚未修改数据的运行中脚本;已写入数据的脚本不能这样终止。 |
SCRIPT FLUSH |
SCRIPT FLUSH ASYNC |
清空脚本缓存,后续 EVALSHA 可能收到 NOSCRIPT。 |
FLUSHDB |
FLUSHDB ASYNC |
高危。删除当前逻辑数据库全部 key。 |
FLUSHALL |
FLUSHALL ASYNC |
极高危。删除当前 Redis 实例所有逻辑数据库的 key。 |
Redis Cluster 的这些管理命令通常针对所连接节点;不要把单节点清理或快照误认为全集群操作。
go-redis
初始化与结果处理
安装并导入 github.com/redis/go-redis/v9,包名为 redis。示例按需导入标准库 context、errors、fmt、time。
go get github.com/redis/go-redis/v9
客户端在应用启动时创建并复用,退出时关闭;不要为每个请求创建客户端。ctx 使用调用方传入的上下文。下面片段位于能返回 error 的函数中,实际连接参数由配置提供。
rdb := redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379",
Password: "", // 本地无密码示例;线上从配置或环境读取。
DB: 0,
})
if err := rdb.Ping(ctx).Err(); err != nil {
_ = rdb.Close()
return fmt.Errorf("连接 Redis: %w", err)
}
// rdb 交给后续业务复用,在应用退出时调用 rdb.Close()。
| 写法 | 示例 | 注释 |
|---|---|---|
.Err() |
err := rdb.Set(ctx, "k", "v", time.Minute).Err() |
只关心命令是否出错;常用于写操作。 |
.Result() |
value, err := rdb.Get(ctx, "k").Result() |
同时取得返回值和错误,读取时优先使用。 |
.Val() |
value := cmd.Val() |
只取值,不处理错误;应先检查该命令的错误。 |
.Int64() |
n, err := rdb.Get(ctx, "counter").Int64() |
将字符串解析为整数;缺失、非法数字、溢出均需处理。 |
redis.Nil |
errors.Is(err, redis.Nil) |
表示空回复,例如 GET 未命中、ZSCORE 成员不存在、阻塞读取超时。 |
HGETALL、LRANGE、SMEMBERS 查不到数据通常返回空容器和 nil 错误。MGET / HMGET 的未命中位于结果切片的 nil 项中;不能把所有“没数据”都统一判断为 redis.Nil。
value, err := rdb.Get(ctx, "user:1:name").Result()
switch {
case errors.Is(err, redis.Nil):
// 缓存未命中,按业务决定是否回源。
case err != nil:
return fmt.Errorf("读取缓存: %w", err)
default:
fmt.Println(value) // 空字符串也可能是合法的命中值。
}
常用原生命令映射
以下列出调用表达式,实际使用时接收结果并检查错误。token 代表每次加锁生成的唯一随机令牌。
| Redis 操作 | go-redis 示例 | 注释 |
|---|---|---|
SET ... EX |
rdb.Set(ctx, "k", "v", 30*time.Second).Err() |
TTL 使用 time.Duration;0 表示写入后不设 TTL。 |
GET |
rdb.Get(ctx, "k").Result() |
返回 string, error。 |
SET ... NX EX |
rdb.SetNX(ctx, "lock:job", token, 30*time.Second).Result() |
返回 bool, error;条件不满足是 false, nil。 |
SET ... XX EX |
rdb.SetXX(ctx, "k", "v", time.Minute).Result() |
只更新已有 key;返回布尔结果。 |
SET ... KEEPTTL |
rdb.Set(ctx, "k", "v", redis.KeepTTL).Err() |
覆盖值并保留旧 TTL,和传 0 不同。 |
GETEX / GETDEL |
rdb.GetEx(ctx, "k", time.Minute).Result() |
刷新 TTL 并读值;取后删除用 rdb.GetDel(ctx, "k")。 |
MGET |
rdb.MGet(ctx, "k1", "k2").Result() |
返回 []any, error,未命中的项为 nil。 |
INCR / INCRBY |
rdb.IncrBy(ctx, "counter", 2).Result() |
返回 int64, error;Incr 固定加 1。 |
DEL / UNLINK |
rdb.Unlink(ctx, "k1", "k2").Result() |
返回删除数量和错误。 |
EXISTS |
rdb.Exists(ctx, "k1", "k2").Result() |
返回存在数量,类型为 int64,并非布尔值。 |
EXPIRE |
rdb.Expire(ctx, "k", time.Minute).Result() |
返回是否成功设置 TTL;ExpireNX 等对应条件选项。 |
TTL / PTTL |
rdb.TTL(ctx, "k").Result() |
返回 time.Duration, error,特殊负值见表后说明。 |
HSET |
rdb.HSet(ctx, "user:1", "name", "Jasper", "age", 20).Result() |
字段和值交替传入,也可使用 map[string]any。 |
HGET / HMGET |
rdb.HMGet(ctx, "user:1", "name", "age").Result() |
HGet 返回字符串,HMGet 返回保持字段顺序的切片。 |
HGETALL |
rdb.HGetAll(ctx, "user:1").Result() |
返回 map[string]string, error;.Scan(&obj) 可映射 redis 标签字段。 |
HINCRBY |
rdb.HIncrBy(ctx, "user:1", "login_count", 1).Result() |
返回字段的新整数值。 |
SADD / SISMEMBER |
rdb.SIsMember(ctx, "tags:1", "go").Result() |
SIsMember 返回布尔值;SAdd 返回新增数量。 |
LRANGE |
rdb.LRange(ctx, "recent", 0, 9).Result() |
返回 []string, error,结束下标包含在内。 |
BLPOP |
rdb.BLPop(ctx, 5*time.Second, "queue").Result() |
超时参数在 key 前;结果包含 key 和弹出的值。 |
ZADD |
rdb.ZAdd(ctx, "rank", redis.Z{Score: 100, Member: "u1"}).Result() |
redis.Z 保存成员和分数;可传多组。 |
ZADD ... NX / XX |
rdb.ZAddNX(ctx, "rank", redis.Z{Score: 100, Member: "u1"}).Result() |
返回新增数;ZAddXX 只更新,成功也可返回 0,变更数需 Ch。 |
ZINCRBY |
rdb.ZIncrBy(ctx, "rank", 10, "u1").Result() |
增量在成员前,返回新分数 float64。 |
ZSCORE / ZREVRANK |
rdb.ZScore(ctx, "rank", "u1").Result() |
分数为 float64,排名为 int64;成员不存在时注意 redis.Nil。 |
ZRANGE |
rdb.ZRange(ctx, "rank", 0, 9).Result() |
升序成员列表;倒序、分数区间使用下面的 ZRangeArgs。 |
TIME |
rdb.Time(ctx).Result() |
返回 time.Time, error;.Unix() 是秒,.UnixMilli() 是毫秒。 |
| 任意已支持的原生命令 | rdb.Do(ctx, "COMMAND", "INFO", "HEXPIRE").Result() |
库暂无专用方法时的补充;不会让旧服务器获得新命令能力。 |
时间参数 不要把 30 当作 30 秒传入 time.Duration,应写 30*time.Second。TTL / PTTL 返回的哨兵值是 time.Duration(-1) 和 time.Duration(-2),直接判断 ttl == -1 / ttl == -2;不要和 -time.Second 比较,也不要先调用 .Seconds() 再判断。
名称对照 Redis 没有名为 ZAddNX 的原生命令,它是库对 ZADD ... NX 的封装。ZRangeByScore、ZRevRange 等旧方法在旧代码中仍常见,新写范围查询可统一使用 ZRangeArgs。
有序集合选项
// ZRANGE rank 100 80 BYSCORE REV LIMIT 0 10 WITHSCORES
items, err := rdb.ZRangeArgsWithScores(ctx, redis.ZRangeArgs{
Key: "rank", Start: 100, Stop: 80,
ByScore: true, Rev: true, Offset: 0, Count: 10,
}).Result()
if err != nil {
return err
}
fmt.Println(items) // []redis.Z;Member 为成员,Score 为 float64。
只取降序前 10 名时使用 Start: 0, Stop: 9, Rev: true,不设置 ByScore、Offset、Count。只要成员列表则用 ZRangeArgs。组合 XX、GT、CH 时用 ZAddArgs,选项结构中的字段名是 XX、GT、Ch,成员放入 Members: []redis.Z{...}。
批处理、扫描与脚本
_, err := rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {
pipe.Set(ctx, "cache:a", "1", time.Minute)
pipe.Set(ctx, "cache:b", "2", time.Minute)
return nil
})
if err != nil {
return err // 不代表整批都没有执行。
}
Pipelined 自动执行批处理;要用事务则改成 TxPipelined。手动创建 Pipeline() / TxPipeline() 后要调用 Exec(ctx)。有读命令时,等待批处理执行结束,再对保存的命令对象调用 .Result() 并检查各自错误。
乐观锁使用 rdb.Watch(ctx, func(tx *redis.Tx) error { ... }, keys...);回调中通过 tx 读取,再用 tx.TxPipelined 提交。errors.Is(err, redis.TxFailedErr) 表示监视冲突,应重读并有限重试。
iter := rdb.Scan(ctx, 0, "user:*", 100).Iterator()
for iter.Next(ctx) {
fmt.Println(iter.Val())
}
if err := iter.Err(); err != nil {
return err
}
迭代器代为推进游标,不会消除 SCAN 的重复结果或快照限制;Cluster 中需要遍历各主节点。
// 脚本对象创建一次并复用;释放锁前核对令牌。
var unlockScript = redis.NewScript(`
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
end
return 0
`)
func unlock(ctx context.Context, rdb *redis.Client, key, token string) (bool, error) {
n, err := unlockScript.Run(ctx, rdb, []string{key}, token).Int64()
if err != nil {
return false, err
}
return n == 1, nil // false 表示本次未删除,可能已过期或令牌不匹配。
}
Run(ctx, rdb, keys, args...) 中,keys 必须是 []string,其余参数对应 ARGV;库自动填写 EVAL 的 key 数量。普通客户端的 Run 先尝试 EVALSHA,遇到 NOSCRIPT 后改用 EVAL。不要把这一自动回退直接套用于尚未执行的 Pipeline;批处理中需预加载脚本或使用 EVAL。
参考资料
命令名链接指向对应的 Redis 官方页面;版本标记表示本表写法的最低服务端版本。托管 Redis 的命令权限与可用性还应检查产品限制。
Redis 命令参考 · 事务 · Pipeline · Lua API · redis-cli · 分布式锁 · Cluster 规范
go-redis 官方指南 · go-redis API · ZSet 实现 · 脚本封装 · 返回值解析