内存数据结构存储的定位、NoSQL对比与应用场景
纲要
本文从 Redis 的官方定义出发,厘清它在整个数据存储体系中的位置,回答三个问题:Redis 到底是什么、NoSQL 与关系型数据库的本质差异是什么、Redis 应该用在哪些场景。
Redis的本质- 开源的、基于内存的数据结构存储系统
- 三种角色:数据库、缓存、消息中间件
C语言开发,键值对结构,官方测试10W+ QPS
NoSQL概念澄清- 全称
Not Only SQL,泛指非关系型数据库这一类别 - 与关系型数据库是互补而非取代关系
- 全称
Redis应用场景- 缓存、任务队列、消息队列、分布式锁
- 核心认知
- 内存有限,因此
Redis适合存热点数据,而非全量数据
- 内存有限,因此
Redis 是什么
Redis 官网(https://redis.io)给出的定义是:
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker.
翻译过来:Redis 是一个开源的、基于内存的数据结构存储系统 ,可以用作数据库 、缓存 和消息中间件。
拆解这句话可以得到 Redis 的四个关键属性:
| 属性 | 说明 |
|---|---|
| 开源 | BSD 许可协议,源码开放 |
| 基于内存 | 数据存放于内存,这是高性能的根本原因 |
| 数据结构存储 | 不只是简单的 key-value,value 支持多种结构化类型 |
| 多角色 | 同时可承担数据库、缓存、消息中间件三种职责 |
补充两个技术事实:
Redis使用C语言开发- 官方测试性能可达 10 万+ QPS (
Queries Per Second,每秒查询次数)
为什么基于内存就快
MySQL 等传统数据库将数据存储在磁盘 上,而 Redis 将数据存储在内存 中。内存的读写速度比磁盘高出几个数量级,这是 Redis 高性能的物理基础。
#mermaid-svg-NbqtxZQ1ONZ1jMqT{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-NbqtxZQ1ONZ1jMqT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .error-icon{fill:#552222;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .marker.cross{stroke:#333333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NbqtxZQ1ONZ1jMqT p{margin:0;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .cluster-label text{fill:#333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .cluster-label span{color:#333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .cluster-label span p{background-color:transparent;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .label text,#mermaid-svg-NbqtxZQ1ONZ1jMqT span{fill:#333;color:#333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .node rect,#mermaid-svg-NbqtxZQ1ONZ1jMqT .node circle,#mermaid-svg-NbqtxZQ1ONZ1jMqT .node ellipse,#mermaid-svg-NbqtxZQ1ONZ1jMqT .node polygon,#mermaid-svg-NbqtxZQ1ONZ1jMqT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .rough-node .label text,#mermaid-svg-NbqtxZQ1ONZ1jMqT .node .label text,#mermaid-svg-NbqtxZQ1ONZ1jMqT .image-shape .label,#mermaid-svg-NbqtxZQ1ONZ1jMqT .icon-shape .label{text-anchor:middle;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .rough-node .label,#mermaid-svg-NbqtxZQ1ONZ1jMqT .node .label,#mermaid-svg-NbqtxZQ1ONZ1jMqT .image-shape .label,#mermaid-svg-NbqtxZQ1ONZ1jMqT .icon-shape .label{text-align:center;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .node.clickable{cursor:pointer;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .arrowheadPath{fill:#333333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NbqtxZQ1ONZ1jMqT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NbqtxZQ1ONZ1jMqT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NbqtxZQ1ONZ1jMqT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .cluster text{fill:#333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .cluster span{color:#333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT 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-NbqtxZQ1ONZ1jMqT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NbqtxZQ1ONZ1jMqT rect.text{fill:none;stroke-width:0;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .icon-shape,#mermaid-svg-NbqtxZQ1ONZ1jMqT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .icon-shape p,#mermaid-svg-NbqtxZQ1ONZ1jMqT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .icon-shape .label rect,#mermaid-svg-NbqtxZQ1ONZ1jMqT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NbqtxZQ1ONZ1jMqT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NbqtxZQ1ONZ1jMqT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NbqtxZQ1ONZ1jMqT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 热点数据
全量数据
应用请求
数据位置
Redis 内存读写
纳秒 ~ 微秒级
MySQL 磁盘读写
毫秒级
响应返回
内存有限决定了它的边界
一个必然被追问的问题是:既然 Redis 这么快,能不能把 MySQL 换掉,所有数据都存 Redis?
不能。 原因有二:
- 内存容量有限且昂贵,无法承载海量数据
- 内存易失,断电后数据丢失(虽有持久化机制,但定位不同)
因此 Redis 的正确用法是:存储热点数据。所谓热点数据,指短时间内有大量用户频繁访问的数据,例如:
- 秒杀、抢购活动中的热点商品
- 高频访问的资讯、新闻
- 首页聚合数据
这类数据若全部压在 MySQL 上,数据库压力极大;放入 Redis 后,请求在内存层直接返回,数据库只承担剩余的冷数据访问。
NoSQL 概念澄清
Redis 常被称为「结构化的 NoSQL 数据库」。这里的 NoSQL 是理解 Redis 定位的关键。
NoSQL 不是某个数据库
NoSQL 全称 Not Only SQL ,意为「不仅仅是 SQL」。它不是指某一个具体的数据库产品 ,而是泛指一类数据库------非关系型数据库。
这一点极易被误解,需要明确:MySQL 是一个数据库的名字,而 NoSQL 是一类数据库的统称。
与关系型数据库的本质差异
#mermaid-svg-VOCgxXVZ5aBPm6OA{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-VOCgxXVZ5aBPm6OA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VOCgxXVZ5aBPm6OA .error-icon{fill:#552222;}#mermaid-svg-VOCgxXVZ5aBPm6OA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VOCgxXVZ5aBPm6OA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VOCgxXVZ5aBPm6OA .marker.cross{stroke:#333333;}#mermaid-svg-VOCgxXVZ5aBPm6OA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VOCgxXVZ5aBPm6OA p{margin:0;}#mermaid-svg-VOCgxXVZ5aBPm6OA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VOCgxXVZ5aBPm6OA .cluster-label text{fill:#333;}#mermaid-svg-VOCgxXVZ5aBPm6OA .cluster-label span{color:#333;}#mermaid-svg-VOCgxXVZ5aBPm6OA .cluster-label span p{background-color:transparent;}#mermaid-svg-VOCgxXVZ5aBPm6OA .label text,#mermaid-svg-VOCgxXVZ5aBPm6OA span{fill:#333;color:#333;}#mermaid-svg-VOCgxXVZ5aBPm6OA .node rect,#mermaid-svg-VOCgxXVZ5aBPm6OA .node circle,#mermaid-svg-VOCgxXVZ5aBPm6OA .node ellipse,#mermaid-svg-VOCgxXVZ5aBPm6OA .node polygon,#mermaid-svg-VOCgxXVZ5aBPm6OA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VOCgxXVZ5aBPm6OA .rough-node .label text,#mermaid-svg-VOCgxXVZ5aBPm6OA .node .label text,#mermaid-svg-VOCgxXVZ5aBPm6OA .image-shape .label,#mermaid-svg-VOCgxXVZ5aBPm6OA .icon-shape .label{text-anchor:middle;}#mermaid-svg-VOCgxXVZ5aBPm6OA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VOCgxXVZ5aBPm6OA .rough-node .label,#mermaid-svg-VOCgxXVZ5aBPm6OA .node .label,#mermaid-svg-VOCgxXVZ5aBPm6OA .image-shape .label,#mermaid-svg-VOCgxXVZ5aBPm6OA .icon-shape .label{text-align:center;}#mermaid-svg-VOCgxXVZ5aBPm6OA .node.clickable{cursor:pointer;}#mermaid-svg-VOCgxXVZ5aBPm6OA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VOCgxXVZ5aBPm6OA .arrowheadPath{fill:#333333;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VOCgxXVZ5aBPm6OA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VOCgxXVZ5aBPm6OA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VOCgxXVZ5aBPm6OA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VOCgxXVZ5aBPm6OA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VOCgxXVZ5aBPm6OA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VOCgxXVZ5aBPm6OA .cluster text{fill:#333;}#mermaid-svg-VOCgxXVZ5aBPm6OA .cluster span{color:#333;}#mermaid-svg-VOCgxXVZ5aBPm6OA 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-VOCgxXVZ5aBPm6OA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VOCgxXVZ5aBPm6OA rect.text{fill:none;stroke-width:0;}#mermaid-svg-VOCgxXVZ5aBPm6OA .icon-shape,#mermaid-svg-VOCgxXVZ5aBPm6OA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VOCgxXVZ5aBPm6OA .icon-shape p,#mermaid-svg-VOCgxXVZ5aBPm6OA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VOCgxXVZ5aBPm6OA .icon-shape .label rect,#mermaid-svg-VOCgxXVZ5aBPm6OA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VOCgxXVZ5aBPm6OA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VOCgxXVZ5aBPm6OA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VOCgxXVZ5aBPm6OA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 非关系型数据库 NoSQL
没有表的概念
以键值对形式存储
数据之间没有关联
使用专有命令操作数据
关系型数据库 RDBMS
数据存储在表中
表之间存在关联关系
支持外键约束
使用 SQL 操作数据
| 对比维度 | 关系型数据库 | NoSQL 数据库 |
|---|---|---|
| 存储结构 | 二维表 | 键值对 / 文档 / 列族 / 图 |
| 数据关联 | 表间关联,支持外键 | 数据之间无关联 |
| 操作语言 | SQL(select / insert / update / delete) |
各产品专有命令 |
| 事务支持 | 强事务 ACID |
通常较弱或仅部分支持 |
| 扩展方式 | 纵向扩展为主 | 天然支持横向扩展 |
| 典型产品 | MySQL、Oracle、DB2、SQL Server |
Redis、MongoDB、Memcached |
互补而非取代
NoSQL 数据库并不是要取代关系型数据库,而是对关系型数据库的补充。
实际项目中,一个系统同时使用 MySQL(存核心业务数据,保证事务与一致性)与 Redis(存热点数据,提供高并发读取)是标准架构。二者分工明确,不存在替代关系。
Redis 应用场景
Redis 的应用面很广,按使用频率排序主要有以下几类:
| 场景 | 说明 | 依赖特性 |
|---|---|---|
| 缓存 | 缓存热点数据,降低数据库压力 | 内存存储、高性能、支持过期时间 |
| 任务队列 | 把待处理任务放入队列,按序消费 | list 类型的顺序性 |
| 消息队列 | 发布订阅模式的消息传递 | pub/sub、stream |
| 分布式锁 | 分布式环境下的并发控制 | setnx 原子操作、过期时间 |
| 排行榜 | 各类实时排名 | sorted set 的分值排序 |
| 计数器 | 点赞数、浏览量等高频自增 | incr 原子自增 |
其中缓存是最主要的使用场景 ,也是后续项目实战中 Redis 承担的核心职责。
#mermaid-svg-QWwqRt4KQg6UmnJV{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-QWwqRt4KQg6UmnJV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QWwqRt4KQg6UmnJV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QWwqRt4KQg6UmnJV .error-icon{fill:#552222;}#mermaid-svg-QWwqRt4KQg6UmnJV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QWwqRt4KQg6UmnJV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QWwqRt4KQg6UmnJV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QWwqRt4KQg6UmnJV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QWwqRt4KQg6UmnJV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QWwqRt4KQg6UmnJV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QWwqRt4KQg6UmnJV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QWwqRt4KQg6UmnJV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QWwqRt4KQg6UmnJV .marker.cross{stroke:#333333;}#mermaid-svg-QWwqRt4KQg6UmnJV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QWwqRt4KQg6UmnJV p{margin:0;}#mermaid-svg-QWwqRt4KQg6UmnJV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QWwqRt4KQg6UmnJV .cluster-label text{fill:#333;}#mermaid-svg-QWwqRt4KQg6UmnJV .cluster-label span{color:#333;}#mermaid-svg-QWwqRt4KQg6UmnJV .cluster-label span p{background-color:transparent;}#mermaid-svg-QWwqRt4KQg6UmnJV .label text,#mermaid-svg-QWwqRt4KQg6UmnJV span{fill:#333;color:#333;}#mermaid-svg-QWwqRt4KQg6UmnJV .node rect,#mermaid-svg-QWwqRt4KQg6UmnJV .node circle,#mermaid-svg-QWwqRt4KQg6UmnJV .node ellipse,#mermaid-svg-QWwqRt4KQg6UmnJV .node polygon,#mermaid-svg-QWwqRt4KQg6UmnJV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QWwqRt4KQg6UmnJV .rough-node .label text,#mermaid-svg-QWwqRt4KQg6UmnJV .node .label text,#mermaid-svg-QWwqRt4KQg6UmnJV .image-shape .label,#mermaid-svg-QWwqRt4KQg6UmnJV .icon-shape .label{text-anchor:middle;}#mermaid-svg-QWwqRt4KQg6UmnJV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QWwqRt4KQg6UmnJV .rough-node .label,#mermaid-svg-QWwqRt4KQg6UmnJV .node .label,#mermaid-svg-QWwqRt4KQg6UmnJV .image-shape .label,#mermaid-svg-QWwqRt4KQg6UmnJV .icon-shape .label{text-align:center;}#mermaid-svg-QWwqRt4KQg6UmnJV .node.clickable{cursor:pointer;}#mermaid-svg-QWwqRt4KQg6UmnJV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QWwqRt4KQg6UmnJV .arrowheadPath{fill:#333333;}#mermaid-svg-QWwqRt4KQg6UmnJV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QWwqRt4KQg6UmnJV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QWwqRt4KQg6UmnJV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QWwqRt4KQg6UmnJV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QWwqRt4KQg6UmnJV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QWwqRt4KQg6UmnJV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QWwqRt4KQg6UmnJV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QWwqRt4KQg6UmnJV .cluster text{fill:#333;}#mermaid-svg-QWwqRt4KQg6UmnJV .cluster span{color:#333;}#mermaid-svg-QWwqRt4KQg6UmnJV 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-QWwqRt4KQg6UmnJV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QWwqRt4KQg6UmnJV rect.text{fill:none;stroke-width:0;}#mermaid-svg-QWwqRt4KQg6UmnJV .icon-shape,#mermaid-svg-QWwqRt4KQg6UmnJV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QWwqRt4KQg6UmnJV .icon-shape p,#mermaid-svg-QWwqRt4KQg6UmnJV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QWwqRt4KQg6UmnJV .icon-shape .label rect,#mermaid-svg-QWwqRt4KQg6UmnJV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QWwqRt4KQg6UmnJV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QWwqRt4KQg6UmnJV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QWwqRt4KQg6UmnJV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Redis 应用场景
缓存
最常用
任务队列
消息队列
分布式锁
排行榜
计数器 / 限流
热点商品 / 资讯 / 首页数据
List 类型按插入顺序
Sorted Set 按 score 排序
Redis 在课程项目中的位置
在后续的外卖平台项目中,Redis 承担的职责是缓存层:
#mermaid-svg-npqupGKOVXjhTmGo{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-npqupGKOVXjhTmGo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-npqupGKOVXjhTmGo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-npqupGKOVXjhTmGo .error-icon{fill:#552222;}#mermaid-svg-npqupGKOVXjhTmGo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-npqupGKOVXjhTmGo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-npqupGKOVXjhTmGo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-npqupGKOVXjhTmGo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-npqupGKOVXjhTmGo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-npqupGKOVXjhTmGo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-npqupGKOVXjhTmGo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-npqupGKOVXjhTmGo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-npqupGKOVXjhTmGo .marker.cross{stroke:#333333;}#mermaid-svg-npqupGKOVXjhTmGo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-npqupGKOVXjhTmGo p{margin:0;}#mermaid-svg-npqupGKOVXjhTmGo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-npqupGKOVXjhTmGo .cluster-label text{fill:#333;}#mermaid-svg-npqupGKOVXjhTmGo .cluster-label span{color:#333;}#mermaid-svg-npqupGKOVXjhTmGo .cluster-label span p{background-color:transparent;}#mermaid-svg-npqupGKOVXjhTmGo .label text,#mermaid-svg-npqupGKOVXjhTmGo span{fill:#333;color:#333;}#mermaid-svg-npqupGKOVXjhTmGo .node rect,#mermaid-svg-npqupGKOVXjhTmGo .node circle,#mermaid-svg-npqupGKOVXjhTmGo .node ellipse,#mermaid-svg-npqupGKOVXjhTmGo .node polygon,#mermaid-svg-npqupGKOVXjhTmGo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-npqupGKOVXjhTmGo .rough-node .label text,#mermaid-svg-npqupGKOVXjhTmGo .node .label text,#mermaid-svg-npqupGKOVXjhTmGo .image-shape .label,#mermaid-svg-npqupGKOVXjhTmGo .icon-shape .label{text-anchor:middle;}#mermaid-svg-npqupGKOVXjhTmGo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-npqupGKOVXjhTmGo .rough-node .label,#mermaid-svg-npqupGKOVXjhTmGo .node .label,#mermaid-svg-npqupGKOVXjhTmGo .image-shape .label,#mermaid-svg-npqupGKOVXjhTmGo .icon-shape .label{text-align:center;}#mermaid-svg-npqupGKOVXjhTmGo .node.clickable{cursor:pointer;}#mermaid-svg-npqupGKOVXjhTmGo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-npqupGKOVXjhTmGo .arrowheadPath{fill:#333333;}#mermaid-svg-npqupGKOVXjhTmGo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-npqupGKOVXjhTmGo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-npqupGKOVXjhTmGo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-npqupGKOVXjhTmGo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-npqupGKOVXjhTmGo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-npqupGKOVXjhTmGo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-npqupGKOVXjhTmGo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-npqupGKOVXjhTmGo .cluster text{fill:#333;}#mermaid-svg-npqupGKOVXjhTmGo .cluster span{color:#333;}#mermaid-svg-npqupGKOVXjhTmGo 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-npqupGKOVXjhTmGo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-npqupGKOVXjhTmGo rect.text{fill:none;stroke-width:0;}#mermaid-svg-npqupGKOVXjhTmGo .icon-shape,#mermaid-svg-npqupGKOVXjhTmGo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-npqupGKOVXjhTmGo .icon-shape p,#mermaid-svg-npqupGKOVXjhTmGo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-npqupGKOVXjhTmGo .icon-shape .label rect,#mermaid-svg-npqupGKOVXjhTmGo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-npqupGKOVXjhTmGo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-npqupGKOVXjhTmGo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-npqupGKOVXjhTmGo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 缓存命中
缓存未命中
移动端 / 管理端
Spring Boot 应用
查询请求
Redis
直接返回
MySQL
查询后写入 Redis
响应返回
具体而言,Redis 会被用于:
- 缓存短信验证码(设置过期时间,替代
Session) - 缓存菜品数据(按分类缓存,变更时清理)
- 缓存套餐数据(
Spring Cache注解方式)
项目目录结构
Redis 安装后的目录结构与本课程配套的 Java 客户端工程结构如下。
Linux 下 Redis 安装目录
txt
/usr/local/redis-4.0.0/
├── redis.conf # 核心配置文件
├── src/ # 编译产物目录
│ ├── redis-server # 服务端启动程序
│ ├── redis-cli # 命令行客户端
│ ├── redis-benchmark # 性能测试工具
│ └── redis-sentinel # 哨兵
├── utils/ # 工具脚本
└── dump.rdb # RDB 持久化文件(运行后生成)
Windows 下 Redis 目录
txt
Redis-x64-3.2.100/
├── redis.windows.conf # Windows 配置文件
├── redis-server.exe # 服务端
├── redis-cli.exe # 命令行客户端
└── redis.windows-service.conf
配套 Java 客户端工程
txt
代码和资料/瑞吉外卖/Redis课程/代码/
├── jedis_demo/ # Jedis 客户端示例
│ ├── pom.xml
│ └── src/test/java/com/itheima/test/
│ └── JedisTest.java
└── springdataredis_demo/ # Spring Data Redis 示例
├── pom.xml
└── src/
├── main/
│ ├── java/com/itheima/
│ │ ├── App.java
│ │ └── config/RedisConfig.java
│ └── resources/application.yml
└── test/java/com/itheima/test/
└── SpringDataRedisTest.java
完整可运行代码
引入 Redis 客户端依赖
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/>
</parent>
<groupId>com.itheima</groupId>
<artifactId>redis-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<!-- Spring Data Redis,底层默认使用 Lettuce 连接池 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml
yaml
spring:
redis:
host: 192.168.138.130
port: 6379
password: 123456
database: 0
Redis 启动类
java
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Redis 示例工程启动类。
* 引入 spring-boot-starter-data-redis 后,
* Spring Boot 会自动装配 RedisTemplate 与 StringRedisTemplate。
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
连通性验证程序
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.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
/**
* 验证 Redis 服务连通性,并演示最基础的字符串读写。
*/
@SpringBootTest
public class RedisConnectionTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 写入一个字符串并立即读回,验证 Redis 是否可用。
*/
@Test
public void testConnection() {
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
operations.set("city", "北京");
String value = operations.get("city");
System.out.println("读取到的值:" + value);
// 验证 Redis 是否生效:能读回写入的值即说明服务连通
if ("北京".equals(value)) {
System.out.println("Redis 连通性验证通过");
}
}
}
API 速览
| 概念 / API | 作用 |
|---|---|
redis-server |
Redis 服务端启动程序 |
redis-cli |
Redis 命令行客户端 |
redis-benchmark |
性能测试工具,用于压测 QPS |
RedisTemplate |
Spring Data Redis 提供的核心操作模板 |
StringRedisTemplate |
RedisTemplate 的字符串特化版本,默认 String 序列化 |
opsForValue() |
获取字符串类型操作接口 |
opsForHash() |
获取哈希类型操作接口 |
opsForList() |
获取列表类型操作接口 |
opsForSet() |
获取集合类型操作接口 |
opsForZSet() |
获取有序集合类型操作接口 |
QPS |
Queries Per Second,每秒查询次数 |
NoSQL |
Not Only SQL,非关系型数据库统称 |
官方文档
- Redis 官方网站:https://redis.io/
- Redis 官方文档:https://redis.io/documentation
- Redis 命令参考:https://redis.io/commands
- Redis 中文网:http://www.redis.cn/
总结
本文明确了 Redis 的三个定位层次:它是基于内存的键值对存储系统,官方测试 10W+ QPS;它是 NoSQL 这一类别 中的一种具体实现,而 NoSQL 与关系型数据库是互补关系而非取代关系;它的应用以缓存热点数据 为主,同时可承担任务队列、消息队列、分布式锁等职责。理解「内存有限 ⇒ 只存热点」这一约束,是后续所有 Redis 使用决策的出发点。