Redis数据类型: String/Hash/List/Set/ZSet的结构特征与选型
纲要
本文厘清 Redis 数据类型的一个关键认知点:数据类型指的是 value 的类型,而非 key 的类型,并逐一说明五种常用类型的结构特征与适用场景。
- 基本结构
Redis存储key-value键值对key固定为字符串类型value支持五种常用数据类型
- 五种类型
string字符串:最常用,普通字符串hash哈希:field-value结构,适合存对象list列表:按插入顺序排序,允许重复set集合:无序 ,不允许重复sorted set有序集合:元素关联score分值,按分值排序,不允许重复
- 典型场景
- 对象存储 →
hash - 任务队列 →
list - 排行榜 →
sorted set
- 对象存储 →
数据类型的准确含义
Redis 是 key-value 结构的数据库,存储的是键值对。需要明确的是:
通常所说的「Redis 数据类型」,指的是 value 部分的数据类型;key 则固定为字符串类型。
#mermaid-svg-XIlXsyRRFHOrskM0{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-XIlXsyRRFHOrskM0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XIlXsyRRFHOrskM0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XIlXsyRRFHOrskM0 .error-icon{fill:#552222;}#mermaid-svg-XIlXsyRRFHOrskM0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XIlXsyRRFHOrskM0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XIlXsyRRFHOrskM0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XIlXsyRRFHOrskM0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XIlXsyRRFHOrskM0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XIlXsyRRFHOrskM0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XIlXsyRRFHOrskM0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XIlXsyRRFHOrskM0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XIlXsyRRFHOrskM0 .marker.cross{stroke:#333333;}#mermaid-svg-XIlXsyRRFHOrskM0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XIlXsyRRFHOrskM0 p{margin:0;}#mermaid-svg-XIlXsyRRFHOrskM0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XIlXsyRRFHOrskM0 .cluster-label text{fill:#333;}#mermaid-svg-XIlXsyRRFHOrskM0 .cluster-label span{color:#333;}#mermaid-svg-XIlXsyRRFHOrskM0 .cluster-label span p{background-color:transparent;}#mermaid-svg-XIlXsyRRFHOrskM0 .label text,#mermaid-svg-XIlXsyRRFHOrskM0 span{fill:#333;color:#333;}#mermaid-svg-XIlXsyRRFHOrskM0 .node rect,#mermaid-svg-XIlXsyRRFHOrskM0 .node circle,#mermaid-svg-XIlXsyRRFHOrskM0 .node ellipse,#mermaid-svg-XIlXsyRRFHOrskM0 .node polygon,#mermaid-svg-XIlXsyRRFHOrskM0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XIlXsyRRFHOrskM0 .rough-node .label text,#mermaid-svg-XIlXsyRRFHOrskM0 .node .label text,#mermaid-svg-XIlXsyRRFHOrskM0 .image-shape .label,#mermaid-svg-XIlXsyRRFHOrskM0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-XIlXsyRRFHOrskM0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XIlXsyRRFHOrskM0 .rough-node .label,#mermaid-svg-XIlXsyRRFHOrskM0 .node .label,#mermaid-svg-XIlXsyRRFHOrskM0 .image-shape .label,#mermaid-svg-XIlXsyRRFHOrskM0 .icon-shape .label{text-align:center;}#mermaid-svg-XIlXsyRRFHOrskM0 .node.clickable{cursor:pointer;}#mermaid-svg-XIlXsyRRFHOrskM0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XIlXsyRRFHOrskM0 .arrowheadPath{fill:#333333;}#mermaid-svg-XIlXsyRRFHOrskM0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XIlXsyRRFHOrskM0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XIlXsyRRFHOrskM0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XIlXsyRRFHOrskM0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XIlXsyRRFHOrskM0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XIlXsyRRFHOrskM0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XIlXsyRRFHOrskM0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XIlXsyRRFHOrskM0 .cluster text{fill:#333;}#mermaid-svg-XIlXsyRRFHOrskM0 .cluster span{color:#333;}#mermaid-svg-XIlXsyRRFHOrskM0 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-XIlXsyRRFHOrskM0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XIlXsyRRFHOrskM0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-XIlXsyRRFHOrskM0 .icon-shape,#mermaid-svg-XIlXsyRRFHOrskM0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XIlXsyRRFHOrskM0 .icon-shape p,#mermaid-svg-XIlXsyRRFHOrskM0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XIlXsyRRFHOrskM0 .icon-shape .label rect,#mermaid-svg-XIlXsyRRFHOrskM0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XIlXsyRRFHOrskM0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XIlXsyRRFHOrskM0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XIlXsyRRFHOrskM0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} key
固定为 String
value
string
字符串
hash
哈希
list
列表
set
集合
sorted set
有序集合
这是一个高频误解点:初学者常以为 key 也有多种类型,实际上 key 永远只是字符串,Redis 的类型系统完全体现在 value 上。正因为 value 支持丰富的结构化类型,Redis 才被称为「数据结构存储系统」,而非简单的键值缓存。
string 字符串
最基础也最常用的类型,就是一个普通的字符串。
txt
key: "city"
value: "北京" ← string 类型
特征:
| 特征 | 说明 |
|---|---|
| 结构 | 单一字符串值 |
| 最大容量 | 单个 value 最大 512 MB |
| 使用频率 | 最高 |
| 典型用途 | 缓存单值数据、计数器(incr)、分布式锁(setnx)、验证码 |
string 类型虽然简单,但通过 incr、decr、setex、setnx 等原子命令,可以支撑计数器、限流、分布式锁等复杂场景。
hash 哈希
hash 的 value 部分本身又是一个 field-value 的映射结构。
txt
key: "user:1"
value: {
"name": "张三", ← field-value
"address": "北京", ← field-value
"phone": "138****" ← field-value
}
结构示意:
#mermaid-svg-Dh20RasDD4Pw81hS{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-Dh20RasDD4Pw81hS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Dh20RasDD4Pw81hS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Dh20RasDD4Pw81hS .error-icon{fill:#552222;}#mermaid-svg-Dh20RasDD4Pw81hS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Dh20RasDD4Pw81hS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Dh20RasDD4Pw81hS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Dh20RasDD4Pw81hS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Dh20RasDD4Pw81hS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Dh20RasDD4Pw81hS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Dh20RasDD4Pw81hS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Dh20RasDD4Pw81hS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Dh20RasDD4Pw81hS .marker.cross{stroke:#333333;}#mermaid-svg-Dh20RasDD4Pw81hS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Dh20RasDD4Pw81hS p{margin:0;}#mermaid-svg-Dh20RasDD4Pw81hS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Dh20RasDD4Pw81hS .cluster-label text{fill:#333;}#mermaid-svg-Dh20RasDD4Pw81hS .cluster-label span{color:#333;}#mermaid-svg-Dh20RasDD4Pw81hS .cluster-label span p{background-color:transparent;}#mermaid-svg-Dh20RasDD4Pw81hS .label text,#mermaid-svg-Dh20RasDD4Pw81hS span{fill:#333;color:#333;}#mermaid-svg-Dh20RasDD4Pw81hS .node rect,#mermaid-svg-Dh20RasDD4Pw81hS .node circle,#mermaid-svg-Dh20RasDD4Pw81hS .node ellipse,#mermaid-svg-Dh20RasDD4Pw81hS .node polygon,#mermaid-svg-Dh20RasDD4Pw81hS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Dh20RasDD4Pw81hS .rough-node .label text,#mermaid-svg-Dh20RasDD4Pw81hS .node .label text,#mermaid-svg-Dh20RasDD4Pw81hS .image-shape .label,#mermaid-svg-Dh20RasDD4Pw81hS .icon-shape .label{text-anchor:middle;}#mermaid-svg-Dh20RasDD4Pw81hS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Dh20RasDD4Pw81hS .rough-node .label,#mermaid-svg-Dh20RasDD4Pw81hS .node .label,#mermaid-svg-Dh20RasDD4Pw81hS .image-shape .label,#mermaid-svg-Dh20RasDD4Pw81hS .icon-shape .label{text-align:center;}#mermaid-svg-Dh20RasDD4Pw81hS .node.clickable{cursor:pointer;}#mermaid-svg-Dh20RasDD4Pw81hS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Dh20RasDD4Pw81hS .arrowheadPath{fill:#333333;}#mermaid-svg-Dh20RasDD4Pw81hS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Dh20RasDD4Pw81hS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Dh20RasDD4Pw81hS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Dh20RasDD4Pw81hS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Dh20RasDD4Pw81hS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Dh20RasDD4Pw81hS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Dh20RasDD4Pw81hS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Dh20RasDD4Pw81hS .cluster text{fill:#333;}#mermaid-svg-Dh20RasDD4Pw81hS .cluster span{color:#333;}#mermaid-svg-Dh20RasDD4Pw81hS 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-Dh20RasDD4Pw81hS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Dh20RasDD4Pw81hS rect.text{fill:none;stroke-width:0;}#mermaid-svg-Dh20RasDD4Pw81hS .icon-shape,#mermaid-svg-Dh20RasDD4Pw81hS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Dh20RasDD4Pw81hS .icon-shape p,#mermaid-svg-Dh20RasDD4Pw81hS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Dh20RasDD4Pw81hS .icon-shape .label rect,#mermaid-svg-Dh20RasDD4Pw81hS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Dh20RasDD4Pw81hS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Dh20RasDD4Pw81hS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Dh20RasDD4Pw81hS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} key: user:1
hash
field: name
value: 张三
field: address
value: 北京
field: phone
value: 138****
特征与用途:
| 特征 | 说明 |
|---|---|
| 结构 | field-value 键值对集合 |
| 适用数据 | 对象数据 |
| 设计方式 | 用对象 ID 作 key,对象属性作 field,属性值作 value |
| 优势 | 可单独读写某个字段,无需反序列化整个对象 |
为什么适合存对象 :若用 string 存对象,需先把对象序列化为 JSON 字符串整体存入;修改某一个属性时,必须取出整个字符串、反序列化、修改、再序列化写回。而 hash 可以直接对单个 field 读写,粒度更细、开销更小。
list 列表
list 是一个有序的字符串序列。
txt
key: "task:queue"
value: ["task1", "task2", "task3", "task2"]
↑ 按插入顺序排列,允许重复
特征:
| 特征 | 说明 |
|---|---|
| 顺序 | 按照插入顺序排序 |
| 重复元素 | 允许 |
| 操作端 | 支持从左侧(LPUSH)或右侧(RPUSH)插入 |
| 典型用途 | 任务队列、消息队列、最新列表 |
用作任务队列
list 的顺序性天然适合实现队列:
#mermaid-svg-KdBPaWIKP6SZKJIG{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-KdBPaWIKP6SZKJIG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KdBPaWIKP6SZKJIG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KdBPaWIKP6SZKJIG .error-icon{fill:#552222;}#mermaid-svg-KdBPaWIKP6SZKJIG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KdBPaWIKP6SZKJIG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KdBPaWIKP6SZKJIG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KdBPaWIKP6SZKJIG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KdBPaWIKP6SZKJIG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KdBPaWIKP6SZKJIG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KdBPaWIKP6SZKJIG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KdBPaWIKP6SZKJIG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KdBPaWIKP6SZKJIG .marker.cross{stroke:#333333;}#mermaid-svg-KdBPaWIKP6SZKJIG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KdBPaWIKP6SZKJIG p{margin:0;}#mermaid-svg-KdBPaWIKP6SZKJIG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KdBPaWIKP6SZKJIG .cluster-label text{fill:#333;}#mermaid-svg-KdBPaWIKP6SZKJIG .cluster-label span{color:#333;}#mermaid-svg-KdBPaWIKP6SZKJIG .cluster-label span p{background-color:transparent;}#mermaid-svg-KdBPaWIKP6SZKJIG .label text,#mermaid-svg-KdBPaWIKP6SZKJIG span{fill:#333;color:#333;}#mermaid-svg-KdBPaWIKP6SZKJIG .node rect,#mermaid-svg-KdBPaWIKP6SZKJIG .node circle,#mermaid-svg-KdBPaWIKP6SZKJIG .node ellipse,#mermaid-svg-KdBPaWIKP6SZKJIG .node polygon,#mermaid-svg-KdBPaWIKP6SZKJIG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KdBPaWIKP6SZKJIG .rough-node .label text,#mermaid-svg-KdBPaWIKP6SZKJIG .node .label text,#mermaid-svg-KdBPaWIKP6SZKJIG .image-shape .label,#mermaid-svg-KdBPaWIKP6SZKJIG .icon-shape .label{text-anchor:middle;}#mermaid-svg-KdBPaWIKP6SZKJIG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KdBPaWIKP6SZKJIG .rough-node .label,#mermaid-svg-KdBPaWIKP6SZKJIG .node .label,#mermaid-svg-KdBPaWIKP6SZKJIG .image-shape .label,#mermaid-svg-KdBPaWIKP6SZKJIG .icon-shape .label{text-align:center;}#mermaid-svg-KdBPaWIKP6SZKJIG .node.clickable{cursor:pointer;}#mermaid-svg-KdBPaWIKP6SZKJIG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KdBPaWIKP6SZKJIG .arrowheadPath{fill:#333333;}#mermaid-svg-KdBPaWIKP6SZKJIG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KdBPaWIKP6SZKJIG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KdBPaWIKP6SZKJIG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KdBPaWIKP6SZKJIG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KdBPaWIKP6SZKJIG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KdBPaWIKP6SZKJIG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KdBPaWIKP6SZKJIG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KdBPaWIKP6SZKJIG .cluster text{fill:#333;}#mermaid-svg-KdBPaWIKP6SZKJIG .cluster span{color:#333;}#mermaid-svg-KdBPaWIKP6SZKJIG 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-KdBPaWIKP6SZKJIG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KdBPaWIKP6SZKJIG rect.text{fill:none;stroke-width:0;}#mermaid-svg-KdBPaWIKP6SZKJIG .icon-shape,#mermaid-svg-KdBPaWIKP6SZKJIG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KdBPaWIKP6SZKJIG .icon-shape p,#mermaid-svg-KdBPaWIKP6SZKJIG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KdBPaWIKP6SZKJIG .icon-shape .label rect,#mermaid-svg-KdBPaWIKP6SZKJIG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KdBPaWIKP6SZKJIG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KdBPaWIKP6SZKJIG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KdBPaWIKP6SZKJIG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} LPUSH 从左侧插入
list
task3 task2 task1
RPOP 从右侧取出
先进先出
先插入的先被处理
工作方式:从列表左侧 把任务数据插入,从列表右侧 逐个取出执行。这样先进入列表的数据会先被处理,即 FIFO(先进先出)。
也可用
RPUSH+LPOP实现同样效果,关键是插入端与取出端必须为不同侧。
set 集合
set 是一个无序的字符串集合。
txt
key: "tags"
value: {"java", "redis", "mysql"}
↑ 无序,且不允许重复
特征:
| 特征 | 说明 |
|---|---|
| 顺序 | 无序 |
| 重复元素 | 不允许,重复添加会覆盖 |
| 典型用途 | 标签、好友关系、共同关注(交集/并集/差集) |
去重机制 :集合中已有元素 a,再次添加 a 时,第二次的 a 会把前一个覆盖掉,从而保证集合内元素唯一。
set 真正的价值在于集合运算:sinter(交集)、sunion(并集)、sdiff(差集),可高效实现「共同好友」「可能认识的人」这类需求。
sorted set 有序集合
sorted set(zset)是 set 的增强版:每个元素都关联一个 score(分值) ,集合按 score 排序。
txt
key: "ranking"
value: {
"videoA" → score: 15200,
"videoB" → score: 9800,
"videoC" → score: 23400
}
特征:
| 特征 | 说明 |
|---|---|
| 顺序 | 按 score 分值排序 |
| 重复元素 | 不允许 (同 set,重复会被覆盖) |
score 作用 |
仅用于排序依据 |
| 典型用途 | 各类排行榜、延迟队列、优先级队列 |
#mermaid-svg-CEA72Gmslx1XignN{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-CEA72Gmslx1XignN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CEA72Gmslx1XignN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CEA72Gmslx1XignN .error-icon{fill:#552222;}#mermaid-svg-CEA72Gmslx1XignN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CEA72Gmslx1XignN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CEA72Gmslx1XignN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CEA72Gmslx1XignN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CEA72Gmslx1XignN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CEA72Gmslx1XignN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CEA72Gmslx1XignN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CEA72Gmslx1XignN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CEA72Gmslx1XignN .marker.cross{stroke:#333333;}#mermaid-svg-CEA72Gmslx1XignN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CEA72Gmslx1XignN p{margin:0;}#mermaid-svg-CEA72Gmslx1XignN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CEA72Gmslx1XignN .cluster-label text{fill:#333;}#mermaid-svg-CEA72Gmslx1XignN .cluster-label span{color:#333;}#mermaid-svg-CEA72Gmslx1XignN .cluster-label span p{background-color:transparent;}#mermaid-svg-CEA72Gmslx1XignN .label text,#mermaid-svg-CEA72Gmslx1XignN span{fill:#333;color:#333;}#mermaid-svg-CEA72Gmslx1XignN .node rect,#mermaid-svg-CEA72Gmslx1XignN .node circle,#mermaid-svg-CEA72Gmslx1XignN .node ellipse,#mermaid-svg-CEA72Gmslx1XignN .node polygon,#mermaid-svg-CEA72Gmslx1XignN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CEA72Gmslx1XignN .rough-node .label text,#mermaid-svg-CEA72Gmslx1XignN .node .label text,#mermaid-svg-CEA72Gmslx1XignN .image-shape .label,#mermaid-svg-CEA72Gmslx1XignN .icon-shape .label{text-anchor:middle;}#mermaid-svg-CEA72Gmslx1XignN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CEA72Gmslx1XignN .rough-node .label,#mermaid-svg-CEA72Gmslx1XignN .node .label,#mermaid-svg-CEA72Gmslx1XignN .image-shape .label,#mermaid-svg-CEA72Gmslx1XignN .icon-shape .label{text-align:center;}#mermaid-svg-CEA72Gmslx1XignN .node.clickable{cursor:pointer;}#mermaid-svg-CEA72Gmslx1XignN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CEA72Gmslx1XignN .arrowheadPath{fill:#333333;}#mermaid-svg-CEA72Gmslx1XignN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CEA72Gmslx1XignN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CEA72Gmslx1XignN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CEA72Gmslx1XignN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CEA72Gmslx1XignN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CEA72Gmslx1XignN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CEA72Gmslx1XignN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CEA72Gmslx1XignN .cluster text{fill:#333;}#mermaid-svg-CEA72Gmslx1XignN .cluster span{color:#333;}#mermaid-svg-CEA72Gmslx1XignN 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-CEA72Gmslx1XignN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CEA72Gmslx1XignN rect.text{fill:none;stroke-width:0;}#mermaid-svg-CEA72Gmslx1XignN .icon-shape,#mermaid-svg-CEA72Gmslx1XignN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CEA72Gmslx1XignN .icon-shape p,#mermaid-svg-CEA72Gmslx1XignN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CEA72Gmslx1XignN .icon-shape .label rect,#mermaid-svg-CEA72Gmslx1XignN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CEA72Gmslx1XignN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CEA72Gmslx1XignN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CEA72Gmslx1XignN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} sorted set: ranking
videoC → 23400
videoA → 15200
videoB → 9800
排名 1
排名 2
排名 3
经典场景------排行榜 :视频播放量排行、商品销量排行、积分排行等,都可以把被排序主体作为元素、把排序依据(播放量、销量、积分)作为 score 存入,直接按 score 区间或名次取数据。
五种类型横向对比
| 类型 | 是否有序 | 排序依据 | 是否允许重复 | 典型场景 |
|---|---|---|---|---|
string |
--- | --- | --- | 单值缓存、计数器、分布式锁、验证码 |
hash |
否 | --- | field 不可重复 |
对象存储(用户信息、购物车) |
list |
是 | 插入顺序 | 允许 | 任务队列、消息队列、最新动态 |
set |
否 | --- | 不允许 | 标签、去重、集合运算(共同好友) |
sorted set |
是 | score 分值 |
不允许 | 排行榜、优先级队列、延迟队列 |
#mermaid-svg-TDv6OBrs0nLU4HOq{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-TDv6OBrs0nLU4HOq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TDv6OBrs0nLU4HOq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TDv6OBrs0nLU4HOq .error-icon{fill:#552222;}#mermaid-svg-TDv6OBrs0nLU4HOq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TDv6OBrs0nLU4HOq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TDv6OBrs0nLU4HOq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TDv6OBrs0nLU4HOq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TDv6OBrs0nLU4HOq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TDv6OBrs0nLU4HOq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TDv6OBrs0nLU4HOq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TDv6OBrs0nLU4HOq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TDv6OBrs0nLU4HOq .marker.cross{stroke:#333333;}#mermaid-svg-TDv6OBrs0nLU4HOq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TDv6OBrs0nLU4HOq p{margin:0;}#mermaid-svg-TDv6OBrs0nLU4HOq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TDv6OBrs0nLU4HOq .cluster-label text{fill:#333;}#mermaid-svg-TDv6OBrs0nLU4HOq .cluster-label span{color:#333;}#mermaid-svg-TDv6OBrs0nLU4HOq .cluster-label span p{background-color:transparent;}#mermaid-svg-TDv6OBrs0nLU4HOq .label text,#mermaid-svg-TDv6OBrs0nLU4HOq span{fill:#333;color:#333;}#mermaid-svg-TDv6OBrs0nLU4HOq .node rect,#mermaid-svg-TDv6OBrs0nLU4HOq .node circle,#mermaid-svg-TDv6OBrs0nLU4HOq .node ellipse,#mermaid-svg-TDv6OBrs0nLU4HOq .node polygon,#mermaid-svg-TDv6OBrs0nLU4HOq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TDv6OBrs0nLU4HOq .rough-node .label text,#mermaid-svg-TDv6OBrs0nLU4HOq .node .label text,#mermaid-svg-TDv6OBrs0nLU4HOq .image-shape .label,#mermaid-svg-TDv6OBrs0nLU4HOq .icon-shape .label{text-anchor:middle;}#mermaid-svg-TDv6OBrs0nLU4HOq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TDv6OBrs0nLU4HOq .rough-node .label,#mermaid-svg-TDv6OBrs0nLU4HOq .node .label,#mermaid-svg-TDv6OBrs0nLU4HOq .image-shape .label,#mermaid-svg-TDv6OBrs0nLU4HOq .icon-shape .label{text-align:center;}#mermaid-svg-TDv6OBrs0nLU4HOq .node.clickable{cursor:pointer;}#mermaid-svg-TDv6OBrs0nLU4HOq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TDv6OBrs0nLU4HOq .arrowheadPath{fill:#333333;}#mermaid-svg-TDv6OBrs0nLU4HOq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TDv6OBrs0nLU4HOq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TDv6OBrs0nLU4HOq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TDv6OBrs0nLU4HOq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TDv6OBrs0nLU4HOq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TDv6OBrs0nLU4HOq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TDv6OBrs0nLU4HOq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TDv6OBrs0nLU4HOq .cluster text{fill:#333;}#mermaid-svg-TDv6OBrs0nLU4HOq .cluster span{color:#333;}#mermaid-svg-TDv6OBrs0nLU4HOq 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-TDv6OBrs0nLU4HOq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TDv6OBrs0nLU4HOq rect.text{fill:none;stroke-width:0;}#mermaid-svg-TDv6OBrs0nLU4HOq .icon-shape,#mermaid-svg-TDv6OBrs0nLU4HOq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TDv6OBrs0nLU4HOq .icon-shape p,#mermaid-svg-TDv6OBrs0nLU4HOq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TDv6OBrs0nLU4HOq .icon-shape .label rect,#mermaid-svg-TDv6OBrs0nLU4HOq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TDv6OBrs0nLU4HOq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TDv6OBrs0nLU4HOq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TDv6OBrs0nLU4HOq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
否,且需去重
是
插入顺序
自定义分值
否,单值
需要存储数据
是否为对象
(多字段)
hash
是否需要排序
set
排序依据
list
sorted set
string
完整可运行代码
五种类型的 Java 操作示例
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.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 演示 Redis 五种数据类型的基本写入与读取。
* 每种类型对应 RedisTemplate 的一个 opsForXxx 操作接口。
*/
@SpringBootTest
public class RedisDataTypeTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* string 类型:最基础的键值存储。
*/
@Test
public void testString() {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
ops.set("city", "北京");
System.out.println("string 读取:" + ops.get("city"));
}
/**
* hash 类型:适合存储对象,按 field 粒度读写。
*/
@Test
public void testHash() {
HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
// 单个字段写入
ops.put("user:1", "name", "张三");
ops.put("user:1", "address", "北京");
ops.put("user:1", "phone", "13800138000");
System.out.println("hash 单字段读取 name:" + ops.get("user:1", "name"));
System.out.println("hash 全部字段:" + ops.entries("user:1"));
System.out.println("hash 全部 field:" + ops.keys("user:1"));
}
/**
* list 类型:按插入顺序排序,允许重复,可用作任务队列。
*/
@Test
public void testList() {
ListOperations<String, Object> ops = redisTemplate.opsForList();
// 从左侧依次插入,最终顺序为 task3, task2, task1
ops.leftPush("task:queue", "task1");
ops.leftPush("task:queue", "task2");
ops.leftPush("task:queue", "task3");
// 从右侧弹出,实现先进先出
System.out.println("list 弹出:" + ops.rightPop("task:queue"));
System.out.println("list 剩余:" + ops.range("task:queue", 0, -1));
}
/**
* set 类型:无序且自动去重。
*/
@Test
public void testSet() {
SetOperations<String, Object> ops = redisTemplate.opsForSet();
// 重复添加 "java" 只保留一个
ops.add("tags", "java", "redis", "mysql", "java");
Set<Object> members = ops.members("tags");
System.out.println("set 成员(自动去重):" + members);
System.out.println("set 是否包含 redis:" + ops.isMember("tags", "redis"));
}
/**
* sorted set 类型:按 score 排序,适用于排行榜。
*/
@Test
public void testZSet() {
ZSetOperations<String, Object> ops = redisTemplate.opsForZSet();
ops.add("ranking", "videoA", 15200);
ops.add("ranking", "videoB", 9800);
ops.add("ranking", "videoC", 23400);
// 按 score 倒序取前 3 名,并附带分值
Set<ZSetOperations.TypedTuple<Object>> tuples =
ops.reverseRangeWithScores("ranking", 0, 2);
if (tuples != null) {
tuples.forEach(t -> System.out.println(" 成员:" + t.getValue() + ",分值:" + t.getScore()));
}
}
/**
* 清理本文产生的测试数据。
*/
@Test
public void cleanUp() {
redisTemplate.delete("city");
redisTemplate.delete("user:1");
redisTemplate.delete("task:queue");
redisTemplate.delete("tags");
redisTemplate.delete("ranking");
System.out.println("清理完成,剩余 key:" + redisTemplate.keys("*"));
}
}
工程目录结构
txt
springdataredis_demo/
├── pom.xml
└── src/
├── main/
│ ├── java/com/itheima/
│ │ ├── App.java # Spring Boot 启动类
│ │ └── config/
│ │ └── RedisConfig.java # RedisTemplate 序列化配置
│ └── resources/
│ └── application.yml # Redis 连接配置
└── test/
└── java/com/itheima/test/
└── RedisDataTypeTest.java # 五大数据类型操作示例
API 速览
| 操作接口 | 对应类型 | 核心方法 |
|---|---|---|
ValueOperations |
string |
set、get、setIfAbsent、increment、set(k, v, timeout) |
HashOperations |
hash |
put、get、entries、keys、values、hasKey |
ListOperations |
list |
leftPush、rightPush、leftPop、rightPop、range、size |
SetOperations |
set |
add、members、isMember、remove、intersect、union |
ZSetOperations |
sorted set |
add、range、reverseRangeWithScores、score、rank、incrementScore |
获取方式(RedisTemplate 提供的方法):
| 方法 | 返回类型 |
|---|---|
redisTemplate.opsForValue() |
ValueOperations |
redisTemplate.opsForHash() |
HashOperations |
redisTemplate.opsForList() |
ListOperations |
redisTemplate.opsForSet() |
SetOperations |
redisTemplate.opsForZSet() |
ZSetOperations |
官方文档
- Redis 数据类型官方介绍:https://redis.io/docs/data-types/
- Redis 数据类型教程:https://redis.io/docs/data-types/tutorial/
- String 命令参考:https://redis.io/commands/?group=string
- Hash 命令参考:https://redis.io/commands/?group=hash
- List 命令参考:https://redis.io/commands/?group=list
- Set 命令参考:https://redis.io/commands/?group=set
- Sorted Set 命令参考:https://redis.io/commands/?group=sorted-set
总结
本文的关键在于纠正一个认知偏差:Redis 的数据类型描述的是 value ,key 恒为字符串。五种类型可按两个维度区分------是否有序(list/sorted set 有序,hash/set 无序)与是否允许重复(list 允许,set/sorted set 不允许)。选型上,多字段对象用 hash 以获得字段级读写粒度,需要保序且允许重复用 list(队列场景),需要去重用 set,需要按自定义分值排名的用 sorted set(排行榜场景)。