Redis命令: string与hash类型的读写、过期与条件设置
纲要
本文进入 Redis 命令实操。Redis 命令按数据类型分类组织,本文覆盖使用频率最高的两类:string 与 hash。
- 命令体系总览
- 按数据类型分类:string / hash / list / set / sorted set
- 另有通用命令:对所有类型生效
- string 命令
- SET / GET:基本读写,同 key 后写覆盖前写
- SETEX:带过期时间写入,验证码场景
- SETNX:key 不存在才写入,分布式锁底层
- hash 命令
- HSET / HGET:按 field 读写
- HDEL / HKEYS / HVALS / HGETALL
- 关键返回值
- nil 等价于 null
- SETNX 返回 1 成功、0 未执行
命令体系总览
Redis 通过命令操作数据,这一点类似于用 SQL 操作 MySQL:
| MySQL | SQL 语句 | insert into 表 … | select … from 表 |
| Redis | Redis 命令 | SET key value | GET key |
由于 Redis 有五种数据类型,命令也按类型分组:
#mermaid-svg-lj7YbEBdeq48DshK{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lj7YbEBdeq48DshK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lj7YbEBdeq48DshK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lj7YbEBdeq48DshK .error-icon{fill:#552222;}#mermaid-svg-lj7YbEBdeq48DshK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lj7YbEBdeq48DshK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lj7YbEBdeq48DshK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lj7YbEBdeq48DshK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lj7YbEBdeq48DshK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lj7YbEBdeq48DshK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lj7YbEBdeq48DshK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lj7YbEBdeq48DshK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lj7YbEBdeq48DshK .marker.cross{stroke:#333333;}#mermaid-svg-lj7YbEBdeq48DshK svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lj7YbEBdeq48DshK p{margin:0;}#mermaid-svg-lj7YbEBdeq48DshK .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-lj7YbEBdeq48DshK .cluster-label text{fill:#333;}#mermaid-svg-lj7YbEBdeq48DshK .cluster-label span{color:#333;}#mermaid-svg-lj7YbEBdeq48DshK .cluster-label span p{background-color:transparent;}#mermaid-svg-lj7YbEBdeq48DshK .label text,#mermaid-svg-lj7YbEBdeq48DshK span{fill:#333;color:#333;}#mermaid-svg-lj7YbEBdeq48DshK .node rect,#mermaid-svg-lj7YbEBdeq48DshK .node circle,#mermaid-svg-lj7YbEBdeq48DshK .node ellipse,#mermaid-svg-lj7YbEBdeq48DshK .node polygon,#mermaid-svg-lj7YbEBdeq48DshK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lj7YbEBdeq48DshK .rough-node .label text,#mermaid-svg-lj7YbEBdeq48DshK .node .label text,#mermaid-svg-lj7YbEBdeq48DshK .image-shape .label,#mermaid-svg-lj7YbEBdeq48DshK .icon-shape .label{text-anchor:middle;}#mermaid-svg-lj7YbEBdeq48DshK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-lj7YbEBdeq48DshK .rough-node .label,#mermaid-svg-lj7YbEBdeq48DshK .node .label,#mermaid-svg-lj7YbEBdeq48DshK .image-shape .label,#mermaid-svg-lj7YbEBdeq48DshK .icon-shape .label{text-align:center;}#mermaid-svg-lj7YbEBdeq48DshK .node.clickable{cursor:pointer;}#mermaid-svg-lj7YbEBdeq48DshK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-lj7YbEBdeq48DshK .arrowheadPath{fill:#333333;}#mermaid-svg-lj7YbEBdeq48DshK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lj7YbEBdeq48DshK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lj7YbEBdeq48DshK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lj7YbEBdeq48DshK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lj7YbEBdeq48DshK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lj7YbEBdeq48DshK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-lj7YbEBdeq48DshK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lj7YbEBdeq48DshK .cluster text{fill:#333;}#mermaid-svg-lj7YbEBdeq48DshK .cluster span{color:#333;}#mermaid-svg-lj7YbEBdeq48DshK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lj7YbEBdeq48DshK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lj7YbEBdeq48DshK rect.text{fill:none;stroke-width:0;}#mermaid-svg-lj7YbEBdeq48DshK .icon-shape,#mermaid-svg-lj7YbEBdeq48DshK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lj7YbEBdeq48DshK .icon-shape p,#mermaid-svg-lj7YbEBdeq48DshK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-lj7YbEBdeq48DshK .icon-shape .label rect,#mermaid-svg-lj7YbEBdeq48DshK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lj7YbEBdeq48DshK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-lj7YbEBdeq48DshK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-lj7YbEBdeq48DshK :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Redis 常用命令
string 命令SET / GET / SETEX / SETNX
hash 命令HSET / HGET / HDEL / HKEYS / HVALS / HGETALL
list 命令LPUSH / LRANGE / RPOP / LLEN / BRPOP
set 命令SADD / SMEMBERS / SCARD / SINTER / SUNION / SDIFF / SREM
sorted set 命令ZADD / ZRANGE / ZINCRBY / ZREM
通用命令KEYS / EXISTS / TYPE / TTL / DEL
练习环境建议:命令在 Windows 与 Linux 版的 Redis 上完全一致。练习阶段推荐用 Windows 版——双击 redis-server.exe 启动服务,再双击 redis-cli.exe 打开客户端即可,无需开虚拟机。
string 类型命令
string 是最常用的类型,核心命令有四个。
| SET | SET key value | 设置指定 key 的值 |
| GET | GET key | 获取指定 key 的值 |
| SETEX | SETEX key seconds value | 设置值并指定过期时间(秒) |
| SETNX | SETNX key value | 仅当 key 不存在时才设置值 |
SET 与 GET
127.0.0.1:6379> SET name 小明
OK
127.0.0.1:6379> GET name
"小明"
返回 OK 表示执行成功。注意 GET 的返回值被双引号包裹,说明它是 string 类型。
key 不存在时:
127.0.0.1:6379> GET age
(nil)
nil 等价于 Java 中的 null,表示值不存在。这是 Redis 中表示「空」的统一方式。
数值也会被存成字符串
127.0.0.1:6379> SET age 20
OK
127.0.0.1:6379> GET age
"20"
注意:即使写入时 20 没有加引号,取回时仍带双引号。只要使用 SET 命令,存入的数据最终都会转为字符串存储。
相同 key 会覆盖
127.0.0.1:6379> SET age 30
OK
127.0.0.1:6379> GET age
"30"
后设置的 30 覆盖了先前的 20。结论:key 相同时,后写入的值覆盖先写入的值。
SETEX 设置过期时间
SETEX = SET + EXpire,在写值的同时指定存活秒数。
127.0.0.1:6379> SETEX city 10 北京
OK
127.0.0.1:6379> GET city
"北京"
# 等待 10 秒后
127.0.0.1:6379> GET city
(nil)
时间一到,Redis 自动清理该键值对,无需人工干预。
Redis
客户端
Redis
客户端
#mermaid-svg-xTN04bMzlvcPpIrU{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xTN04bMzlvcPpIrU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xTN04bMzlvcPpIrU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xTN04bMzlvcPpIrU .error-icon{fill:#552222;}#mermaid-svg-xTN04bMzlvcPpIrU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xTN04bMzlvcPpIrU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xTN04bMzlvcPpIrU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xTN04bMzlvcPpIrU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xTN04bMzlvcPpIrU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xTN04bMzlvcPpIrU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xTN04bMzlvcPpIrU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xTN04bMzlvcPpIrU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xTN04bMzlvcPpIrU .marker.cross{stroke:#333333;}#mermaid-svg-xTN04bMzlvcPpIrU svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xTN04bMzlvcPpIrU p{margin:0;}#mermaid-svg-xTN04bMzlvcPpIrU .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xTN04bMzlvcPpIrU text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-xTN04bMzlvcPpIrU .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-xTN04bMzlvcPpIrU .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-xTN04bMzlvcPpIrU .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-xTN04bMzlvcPpIrU .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-xTN04bMzlvcPpIrU #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-xTN04bMzlvcPpIrU .sequenceNumber{fill:white;}#mermaid-svg-xTN04bMzlvcPpIrU #sequencenumber{fill:#333;}#mermaid-svg-xTN04bMzlvcPpIrU #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-xTN04bMzlvcPpIrU .messageText{fill:#333;stroke:none;}#mermaid-svg-xTN04bMzlvcPpIrU .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xTN04bMzlvcPpIrU .labelText,#mermaid-svg-xTN04bMzlvcPpIrU .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-xTN04bMzlvcPpIrU .loopText,#mermaid-svg-xTN04bMzlvcPpIrU .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-xTN04bMzlvcPpIrU .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-xTN04bMzlvcPpIrU .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-xTN04bMzlvcPpIrU .noteText,#mermaid-svg-xTN04bMzlvcPpIrU .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-xTN04bMzlvcPpIrU .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xTN04bMzlvcPpIrU .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xTN04bMzlvcPpIrU .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xTN04bMzlvcPpIrU .actorPopupMenu{position:absolute;}#mermaid-svg-xTN04bMzlvcPpIrU .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-xTN04bMzlvcPpIrU .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xTN04bMzlvcPpIrU .actor-man circle,#mermaid-svg-xTN04bMzlvcPpIrU line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-xTN04bMzlvcPpIrU :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
倒计时至第 10 秒
SETEX city 10 北京
OK
GET city(第 1 秒)
"北京"
自动清理 city
GET city(第 11 秒)
(nil)
典型应用——手机验证码登录:服务端生成验证码后存入 Redis 并设置 5 分钟有效期,时间到自动失效。这样无需在应用层维护过期逻辑,也避免了 Session 的局限性。
# 验证码 5 分钟有效
SETEX code:13800138000 300 1234
SETNX 条件设置
SETNX = SET if Not eXists:只有当 key 不存在时才设置,已存在则不做任何操作。
127.0.0.1:6379> SETNX k1 value1
(integer) 1
127.0.0.1:6379> SETNX k1 value2
(integer) 0
127.0.0.1:6379> GET k1
"value1"
| 1 | 设置成功(key 原先不存在) |
| 0 | 未执行(key 已存在) |
第二次 SETNX k1 value2 返回 0,且 GET k1 仍为 value1,说明第二次写入被跳过。
典型应用——分布式锁:分布式环境下的并发控制依赖「抢锁」这一原子动作,而 SETNX 的「不存在才设置」语义正是抢锁的底层实现原理。
#mermaid-svg-kW2eaQFfeFm1QPwN{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kW2eaQFfeFm1QPwN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kW2eaQFfeFm1QPwN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kW2eaQFfeFm1QPwN .error-icon{fill:#552222;}#mermaid-svg-kW2eaQFfeFm1QPwN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kW2eaQFfeFm1QPwN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kW2eaQFfeFm1QPwN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kW2eaQFfeFm1QPwN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kW2eaQFfeFm1QPwN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kW2eaQFfeFm1QPwN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kW2eaQFfeFm1QPwN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kW2eaQFfeFm1QPwN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kW2eaQFfeFm1QPwN .marker.cross{stroke:#333333;}#mermaid-svg-kW2eaQFfeFm1QPwN svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kW2eaQFfeFm1QPwN p{margin:0;}#mermaid-svg-kW2eaQFfeFm1QPwN .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-kW2eaQFfeFm1QPwN .cluster-label text{fill:#333;}#mermaid-svg-kW2eaQFfeFm1QPwN .cluster-label span{color:#333;}#mermaid-svg-kW2eaQFfeFm1QPwN .cluster-label span p{background-color:transparent;}#mermaid-svg-kW2eaQFfeFm1QPwN .label text,#mermaid-svg-kW2eaQFfeFm1QPwN span{fill:#333;color:#333;}#mermaid-svg-kW2eaQFfeFm1QPwN .node rect,#mermaid-svg-kW2eaQFfeFm1QPwN .node circle,#mermaid-svg-kW2eaQFfeFm1QPwN .node ellipse,#mermaid-svg-kW2eaQFfeFm1QPwN .node polygon,#mermaid-svg-kW2eaQFfeFm1QPwN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kW2eaQFfeFm1QPwN .rough-node .label text,#mermaid-svg-kW2eaQFfeFm1QPwN .node .label text,#mermaid-svg-kW2eaQFfeFm1QPwN .image-shape .label,#mermaid-svg-kW2eaQFfeFm1QPwN .icon-shape .label{text-anchor:middle;}#mermaid-svg-kW2eaQFfeFm1QPwN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kW2eaQFfeFm1QPwN .rough-node .label,#mermaid-svg-kW2eaQFfeFm1QPwN .node .label,#mermaid-svg-kW2eaQFfeFm1QPwN .image-shape .label,#mermaid-svg-kW2eaQFfeFm1QPwN .icon-shape .label{text-align:center;}#mermaid-svg-kW2eaQFfeFm1QPwN .node.clickable{cursor:pointer;}#mermaid-svg-kW2eaQFfeFm1QPwN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kW2eaQFfeFm1QPwN .arrowheadPath{fill:#333333;}#mermaid-svg-kW2eaQFfeFm1QPwN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kW2eaQFfeFm1QPwN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kW2eaQFfeFm1QPwN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kW2eaQFfeFm1QPwN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kW2eaQFfeFm1QPwN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kW2eaQFfeFm1QPwN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kW2eaQFfeFm1QPwN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kW2eaQFfeFm1QPwN .cluster text{fill:#333;}#mermaid-svg-kW2eaQFfeFm1QPwN .cluster span{color:#333;}#mermaid-svg-kW2eaQFfeFm1QPwN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kW2eaQFfeFm1QPwN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kW2eaQFfeFm1QPwN rect.text{fill:none;stroke-width:0;}#mermaid-svg-kW2eaQFfeFm1QPwN .icon-shape,#mermaid-svg-kW2eaQFfeFm1QPwN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kW2eaQFfeFm1QPwN .icon-shape p,#mermaid-svg-kW2eaQFfeFm1QPwN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kW2eaQFfeFm1QPwN .icon-shape .label rect,#mermaid-svg-kW2eaQFfeFm1QPwN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kW2eaQFfeFm1QPwN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kW2eaQFfeFm1QPwN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kW2eaQFfeFm1QPwN :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
服务实例 ASETNX lock 1返回 1 抢锁成功
获得锁执行业务DEL lock 释放
服务实例 BSETNX lock 1返回 0 抢锁失败
等待或放弃
string 类型的完整命令远不止这四个(官方文档共 20 个)。完整的命令清单可查阅 Redis 中文网 http://www.redis.net.cn 的「Redis 教程」菜单。
hash 类型命令
hash 是一个 string 类型的 field 和 value 的映射表,特别适合存储对象。
三层结构
#mermaid-svg-fsWODK0uvZxwXH8T{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fsWODK0uvZxwXH8T .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fsWODK0uvZxwXH8T .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fsWODK0uvZxwXH8T .error-icon{fill:#552222;}#mermaid-svg-fsWODK0uvZxwXH8T .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fsWODK0uvZxwXH8T .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fsWODK0uvZxwXH8T .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fsWODK0uvZxwXH8T .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fsWODK0uvZxwXH8T .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fsWODK0uvZxwXH8T .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fsWODK0uvZxwXH8T .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fsWODK0uvZxwXH8T .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fsWODK0uvZxwXH8T .marker.cross{stroke:#333333;}#mermaid-svg-fsWODK0uvZxwXH8T svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fsWODK0uvZxwXH8T p{margin:0;}#mermaid-svg-fsWODK0uvZxwXH8T .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-fsWODK0uvZxwXH8T .cluster-label text{fill:#333;}#mermaid-svg-fsWODK0uvZxwXH8T .cluster-label span{color:#333;}#mermaid-svg-fsWODK0uvZxwXH8T .cluster-label span p{background-color:transparent;}#mermaid-svg-fsWODK0uvZxwXH8T .label text,#mermaid-svg-fsWODK0uvZxwXH8T span{fill:#333;color:#333;}#mermaid-svg-fsWODK0uvZxwXH8T .node rect,#mermaid-svg-fsWODK0uvZxwXH8T .node circle,#mermaid-svg-fsWODK0uvZxwXH8T .node ellipse,#mermaid-svg-fsWODK0uvZxwXH8T .node polygon,#mermaid-svg-fsWODK0uvZxwXH8T .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fsWODK0uvZxwXH8T .rough-node .label text,#mermaid-svg-fsWODK0uvZxwXH8T .node .label text,#mermaid-svg-fsWODK0uvZxwXH8T .image-shape .label,#mermaid-svg-fsWODK0uvZxwXH8T .icon-shape .label{text-anchor:middle;}#mermaid-svg-fsWODK0uvZxwXH8T .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fsWODK0uvZxwXH8T .rough-node .label,#mermaid-svg-fsWODK0uvZxwXH8T .node .label,#mermaid-svg-fsWODK0uvZxwXH8T .image-shape .label,#mermaid-svg-fsWODK0uvZxwXH8T .icon-shape .label{text-align:center;}#mermaid-svg-fsWODK0uvZxwXH8T .node.clickable{cursor:pointer;}#mermaid-svg-fsWODK0uvZxwXH8T .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fsWODK0uvZxwXH8T .arrowheadPath{fill:#333333;}#mermaid-svg-fsWODK0uvZxwXH8T .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fsWODK0uvZxwXH8T .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fsWODK0uvZxwXH8T .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fsWODK0uvZxwXH8T .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fsWODK0uvZxwXH8T .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fsWODK0uvZxwXH8T .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fsWODK0uvZxwXH8T .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fsWODK0uvZxwXH8T .cluster text{fill:#333;}#mermaid-svg-fsWODK0uvZxwXH8T .cluster span{color:#333;}#mermaid-svg-fsWODK0uvZxwXH8T div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fsWODK0uvZxwXH8T .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fsWODK0uvZxwXH8T rect.text{fill:none;stroke-width:0;}#mermaid-svg-fsWODK0uvZxwXH8T .icon-shape,#mermaid-svg-fsWODK0uvZxwXH8T .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fsWODK0uvZxwXH8T .icon-shape p,#mermaid-svg-fsWODK0uvZxwXH8T .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fsWODK0uvZxwXH8T .icon-shape .label rect,#mermaid-svg-fsWODK0uvZxwXH8T .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fsWODK0uvZxwXH8T .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fsWODK0uvZxwXH8T .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fsWODK0uvZxwXH8T :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
key如 001
value 整体为 hash
field: namevalue: 小明
field: agevalue: 20
field: phonevalue: 138***
命令参数与结构的对应关系:
| key | 整个 Redis 键值对的 key |
| field | value 内部的字段名 |
| value | field 对应的值 |
重点:HDEL 删除的是 key 下的某个 field,不是删除整个 key。这是初学 hash 最常见的误解。
| HSET | HSET key field value | 设置 key 中 field 的值 |
| HGET | HGET key field | 获取 key 中 field 的值 |
| HDEL | HDEL key field [field …] | 删除一个或多个 field |
| HKEYS | HKEYS key | 返回所有 field |
| HVALS | HVALS key | 返回所有 value |
| HGETALL | HGETALL key | 返回所有 field 与 value |
HSET 与 HGET
以存储用户信息为例,用用户 ID 作为 key,属性作为 field:
127.0.0.1:6379> HSET 001 name 小明
(integer) 1
127.0.0.1:6379> HSET 001 age 20
(integer) 1
127.0.0.1:6379> HGET 001 name
"小明"
127.0.0.1:6379> HGET 001 age
"20"
两个 HSET 使用同一个 key(001),因此代表同一个用户对象的不同属性。
HDEL 删除字段
127.0.0.1:6379> HDEL 001 age
(integer) 1
127.0.0.1:6379> HGET 001 age
(nil)
HDEL 后可接多个 field,一次性删除多个字段。删除后该 field 变为 nil。
HKEYS / HVALS / HGETALL
127.0.0.1:6379> HKEYS 001
1) "name"
2) "age"
127.0.0.1:6379> HVALS 001
1) "小明"
2) "20"
127.0.0.1:6379> HGETALL 001
1) "name"
2) "小明"
3) "age"
4) "20"
三者的区别:
| HKEYS | 仅所有 field |
| HVALS | 仅所有 value |
| HGETALL | field 与 value 交替列出 |
HGETALL 的输出是 field、value、field、value 交替排列,需成对阅读。
若 key 本身不存在(如 HGET 002 name),同样返回 nil。
完整可运行代码
Java 中对应的操作
package com.itheima.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 演示 Redis string 与 hash 类型命令在 Java 中的对应操作。
*/
@SpringBootTest
public class RedisStringHashCommandTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 对应 SET / GET:基本读写。
*/
@Test
public void testSetAndGet() {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
ops.set("name", "小明");
System.out.println("GET name -> " + ops.get("name"));
// key 不存在时返回 null,等价于命令行中的 nil
System.out.println("GET notExist -> " + ops.get("notExist"));
// 相同 key 后写覆盖前写
ops.set("age", "20");
ops.set("age", "30");
System.out.println("GET age -> " + ops.get("age"));
}
/**
* 对应 SETEX:写入时指定过期时间。
*/
@Test
public void testSetex() {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
// 验证码 5 分钟有效
ops.set("code:13800138000", "1234", 5, TimeUnit.MINUTES);
System.out.println("GET code -> " + ops.get("code:13800138000"));
System.out.println("剩余有效期(秒)-> " + redisTemplate.getExpire("code:13800138000"));
}
/**
* 对应 SETNX:key 不存在才设置,可用于分布式锁。
*/
@Test
public void testSetnx() {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
redisTemplate.delete("k1");
Boolean first = ops.setIfAbsent("k1", "value1");
Boolean second = ops.setIfAbsent("k1", "value2");
System.out.println("第一次 SETNX -> " + first);
System.out.println("第二次 SETNX -> " + second);
System.out.println("GET k1 -> " + ops.get("k1"));
}
/**
* 对应 HSET / HGET / HDEL / HKEYS / HVALS / HGETALL。
*/
@Test
public void testHash() {
HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
ops.put("001", "name", "小明");
ops.put("001", "age", "20");
System.out.println("HGET 001 name -> " + ops.get("001", "name"));
System.out.println("HKEYS 001 -> " + ops.keys("001"));
System.out.println("HVALS 001 -> " + ops.values("001"));
System.out.println("HGETALL 001 -> " + ops.entries("001"));
// HDEL 删除的是 field,而非整个 key
ops.delete("001", "age");
Map<Object, Object> after = ops.entries("001");
System.out.println("删除 age 后 HGETALL -> " + after);
// 验证 key 本身仍然存在
System.out.println("key 001 是否存在 -> " + Boolean.TRUE.equals(redisTemplate.hasKey("001")));
}
}
工程目录结构
springdataredis_demo/
├── pom.xml
└── src/
├── main/
│ ├── java/com/itheima/
│ │ ├── App.java
│ │ └── config/
│ │ └── RedisConfig.java
│ └── resources/
│ └── application.yml
└── test/
└── java/com/itheima/test/
└── RedisStringHashCommandTest.java
API 速览
| SET key value | opsForValue().set(k, v) | 设置值 |
| GET key | opsForValue().get(k) | 取值,不存在返回 null |
| SETEX key sec value | opsForValue().set(k, v, timeout, unit) | 带过期时间写入 |
| SETNX key value | opsForValue().setIfAbsent(k, v) | 不存在才设置,返回 Boolean |
| HSET key f v | opsForHash().put(k, f, v) | 设置字段 |
| HGET key f | opsForHash().get(k, f) | 取字段值 |
| HDEL key f | opsForHash().delete(k, f) | 删除字段 |
| HKEYS key | opsForHash().keys(k) | 所有 field |
| HVALS key | opsForHash().values(k) | 所有 value |
| HGETALL key | opsForHash().entries(k) | 所有 field-value |
| TTL key | getExpire(k) | 剩余有效期 |
| EXISTS key | hasKey(k) | 键是否存在 |
官方文档
- Redis 命令总览:https://redis.io/commands
- String 命令参考:https://redis.io/commands/?group=string
- Hash 命令参考:https://redis.io/commands/?group=hash
- Redis 中文网教程:http://www.redis.net.cn/tutorial/3501.html
总结
本文覆盖了 string 与 hash 两类高频命令。string 的四个命令体现了三种写入语义:普通写入(SET,同键覆盖)、带过期写入(SETEX,验证码场景)、条件写入(SETNX,返回 1/0,分布式锁底层)。hash 的核心是理解 key → field → value 三层结构——命令中的 field 位于 value 内部,因此 HDEL 删的是字段而非整个键。Redis 统一用 nil 表达「不存在」,对应 Java 中的 null。
网硕互联帮助中心





评论前必须登录!
注册