Java 接入Redis: 五大数据类型与存储结构选型

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

数据类型的准确含义

Rediskey-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 类型虽然简单,但通过 incrdecrsetexsetnx 等原子命令,可以支撑计数器、限流、分布式锁等复杂场景。

hash 哈希

hashvalue 部分本身又是一个 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 setzset)是 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 setgetsetIfAbsentincrementset(k, v, timeout)
HashOperations hash putgetentrieskeysvalueshasKey
ListOperations list leftPushrightPushleftPoprightPoprangesize
SetOperations set addmembersisMemberremoveintersectunion
ZSetOperations sorted set addrangereverseRangeWithScoresscorerankincrementScore

获取方式(RedisTemplate 提供的方法):

方法 返回类型
redisTemplate.opsForValue() ValueOperations
redisTemplate.opsForHash() HashOperations
redisTemplate.opsForList() ListOperations
redisTemplate.opsForSet() SetOperations
redisTemplate.opsForZSet() ZSetOperations

官方文档

总结

本文的关键在于纠正一个认知偏差:Redis 的数据类型描述的是 valuekey 恒为字符串。五种类型可按两个维度区分------是否有序(list/sorted set 有序,hash/set 无序)与是否允许重复(list 允许,set/sorted set 不允许)。选型上,多字段对象用 hash 以获得字段级读写粒度,需要保序且允许重复用 list(队列场景),需要去重用 set,需要按自定义分值排名的用 sorted set(排行榜场景)。

相关推荐
Wang's Blog1 小时前
Java 接入Redis: 字符串与哈希类型操作命令
java·服务器·redis
智慧物业老杨5 小时前
物业数字化落地思考:真正的转型,是底层数据秩序的重构
java·大数据·人工智能·微服务·系统架构
星空8 小时前
金蝶苍穹build.gradle配置
java·build.gradle
充电zcx9 小时前
Linux:4:开发工具详解
linux·运维·服务器
步行cgn11 小时前
Spring 基于 XML 的自动装配:byName 详解
java·后端·spring
大帅点兵11 小时前
Apache Ant 1.9.9 完整讲解
java
LuTshoes12 小时前
spring ai 实战 手搓 PlaneExecuteAgent
java·人工智能·spring·ai
这料鬼有毒12 小时前
二刷hot100-73.矩阵置零
java
caoerzhong12 小时前
JeeWMS 开源仓库管理系统二次开发与接口对接实战:Java WMS 如何与 ERP、MES 和自动化设备打通
java·开源