先聊点实在的。只要你做过后端开发,或者正在自学后端技术栈,“Redis”这个名字迟早会出现在你眼前。翻一下招聘要求,Java、Go、Python 后端岗基本都写着“熟悉 Redis 优先”;打开面试题库,Redis 相关问题的出现频率高得离谱;再看实际生产环境,只要系统流量稍微起来一点,Redis 几乎就是标配。它不是某个大厂内部才能用到的小众技术,而是已经落入“常规基础设施”范畴的通用组件。
这一篇是“Redis 学习笔记”系列的开头,我准备用最通俗的方式把 Redis 讲明白:它到底解决什么问题、凭什么这么快、怎么快速安装起来跑通第一个命令,以及初学阶段你最应该盯住的核心主线。不管你是刚接触后端的学生、想补基础经验的初级开发,还是准备深入优化系统的工程师,这一篇都值得你花十分钟读一遍。我不打算一上来堆概念,而是从一段真实场景聊起。
1. 为什么我们需要认识 Redis:先从一杯咖啡说起
1.1 一个扛不住的“小网站”
假设你写了个个人博客或者校园论坛,初期存储在 MySQL 里的数据也就几千条,读写都很快,压根感觉不到性能瓶颈。但某天你发了一篇爆款文章,用户同时涌进来,不少人反复刷新查看文章列表和详情,这时候数据库的查询压力就上来了。
MySQL 本身并不是不能扛并发,问题在于频繁的磁盘 I/O、行锁竞争还有重复查询都在浪费资源。说得直白点:一百个人同时查同一条热门文章,数据库就得把同一份数据从磁盘捞出来一百次。这个“重复劳动”既拖慢响应速度,也加重服务端压力。
这时候,你非常需要一层“快得多的缓存”挡在数据库前面,把那些高频访问的数据提前放在一个随手能拿到的地方。Redis 干的就是这个活儿。它把数据放在内存里,读写速度快到让数据库“望尘莫及”,一份热点数据只要被读一次,后续相同的请求就可以直接命中内存,压根碰不到数据库。这就是 Redis 最简单、最核心的定位:一层高速缓存。
1.2 Redis 到底是个什么东西
严格说,Redis 是一个基于内存的、支持多种数据结构的 NoSQL 键值存储系统。它名字里的“REmote Dictionary Server”翻译过来就是“远程字典服务器”,你可以粗暴理解为:它是一张超级大、超级快的 HashMap,外面允许很多台机器通过 TCP 协议来读写这张表。
为什么它快?最直接的原因就是内存。内存的随机访问延迟一般都在几十纳秒到一百多纳秒的级别,而磁盘的随机访问延迟往往要几毫秒甚至更高,这中间差着好几个数量级。再加上 Redis 本身用 C 语言编写、命令设计精简、对事件循环和内存分配做了大量优化,所以它在普通机器上都能轻松做到每秒十万甚至几十万次的 QPS(每秒查询次数)。
很多人喜欢拿 Redis 和关系型数据库、Memcached 做对比,简单梳理一下你就清楚了:
| 维度 | Redis | 传统关系型数据库(如 MySQL) | Memcached |
|---|---|---|---|
| 主要存储介质 | 内存(可持久化到磁盘) | 磁盘为主 | 内存 |
| 数据结构支持 | String、Hash、List、Set、ZSet 等 | 表结构、SQL 查询、事务 | 只支持简单 KV |
| 持久化 | RDB 快照 + AOF 日志 | 事务日志、Binlog 等 | 不支持 |
| 典型应用场景 | 缓存、分布式锁、排行榜、消息队列等 | 业务数据存储、复杂查询 | 纯缓存场景 |
| 单机吞吐量 | 极高,常达 10w+ QPS | 一般几千到几万 QPS | 极高 |
这个表不是让你背下来的,而是想说明一件事:Redis 不是一个“什么都能存的数据库”,它更像是一个能力很强的通用数据结构服务器。正因为数据结构丰富、底层又是内存操作,所以它不仅能做缓存,还能顺手做一堆别的有趣的事情,后面我会详细展开。
1.3 学习 Redis 能解决什么问题
对后端开发来说,Redis 几乎是躲不开的必修课。你写业务接口的时候,要考虑怎么降低数据库压力;你做登录认证,要处理 Session 和 Token 的存储;你要做并发控制,需要一把跨服务的锁;你要做排行榜、文章浏览量、在线状态,Redis 都能给出比数据库更优雅的方案。
对架构师和运维来说,Redis 的持久化策略选型、高可用方案(主从复制、哨兵模式、集群模式)、缓存一致性保障,都是生产环境必须反复权衡的问题。网上经常能看到“缓存穿透导致数据库被打爆”的案例,这些事故本质上都是对 Redis 的底层机制理解不够造成的。
对学生和初学者来说,Redis 是一个非常理想的“第二个数据库”。它命令简单、安装容易、可视化工具也多,你不需要理解太复杂的 SQL,学完基础命令就能做出“分布式登录态共享”“排行榜”“消息队列”这样看起来挺厉害的小项目,对建立自信和积累项目经验帮助特别大。
2. 初识 Redis:搞清楚那些让人上头的特性
2.1 五种基础数据结构与两种“隐藏款”
Redis 之所以特别,很大程度是因为它不是一个只认字符串的 Key-Value 仓库。它内部提供了五种基础数据结构,每种结构都有对应的使用场景。我先把最实用的部分列出来,再逐个拆。
| 数据结构 | 底层含义 | 典型使用场景 | 常用命令举例 |
|---|---|---|---|
| String | 字符串、数字、二进制串 | 缓存对象、计数器、分布式锁 | SET、GET、INCR、SETNX |
| Hash | 字段-值映射表 | 存储对象属性,如用户信息、商品信息 | HSET、HGET、HGETALL |
| List | 双向链表 | 消息队列、时间线、最新列表 | LPUSH、RPUSH、LPOP、LRANGE |
| Set | 无序字符串集合 | 去重、共同关注、抽奖、标签系统 | SADD、SISMEMBER、SINTER |
| ZSet(有序集合) | 带权重的有序集合 | 排行榜、延时队列、热搜榜 | ZADD、ZRANGE、ZSCORE |
实际开发里最常见的 String 可以存一个序列化后的 JSON 对象,也可以直接存数字做自增操作。Hash 比 String 更适合存“需要频繁修改部分字段”的对象,比如用户昵称和头像要独立更新时,用 Hash 就特别顺手,不用把整个缓存对象取出来再重写一遍。
List 的双向特性让它既能当“队列”(左进右出),也能当“栈”(左进左出)。Set 最典型的就是交集、并集、差集运算,比如“我关注的人里有哪些也关注了你”,一条 SINTER 命令就能搞定。ZSet 则是给每个元素绑定了一个分数,分数决定排序位置,排行榜就是它的主场。
除此之外,Redis 还提供了一些进阶的数据结构,比如 Bitmap(位图)、HyperLogLog(基数统计)、Geo(地理位置)、Stream(更完善的消息队列模型),以及通过模块支持的布隆过滤器。初学阶段不用急着全啃下来,先把五种基础结构用熟,后面遇到“UV 统计”“附近的人”“消息可靠投递”这些场景时,再逐个击破。
2.2 单线程模型:为什么单线程还能这么快
我见过不少刚接触 Redis 的人都会有个疑惑:“Redis 是单线程的?那它凭什么还能扛住这么高的并发?”这个问题的答案其实是理解 Redis 性能的一把钥匙。
首先要澄清一点:Redis 的命令执行核心确实主要是单线程的,也就是说,同一时刻只有一个命令在真正处理数据。但 Redis 的底层用了 IO 多路复用机制,能够同时监控成千上万个客户端连接,一旦哪个连接有请求数据进来,事件循环就会立刻处理它。因为内存操作本身极快,每个命令又极短,单线程处理它们根本不会成为瓶颈,反而避免了很多多线程编程的麻烦。
你可以把单线程模型类比成“一个人在多个窗口间快速接待客户”:窗口再多,接待员也只有一个,但他处理得足够快,而且不用考虑窗口之间的排队锁、资源抢占,整体效率反而更高。更妙的是,由于 Redis 单线程保证了命令执行的原子性,所以像 INCR、SETNX 这些命令天然就没有并发竞争问题,这为后面做分布式锁打下了非常好的基础。
有个细节容易被面试官问到:Redis 6.0 之后引入了多线程 IO,网络数据的读写部分会交给额外线程处理,但命令执行仍然是单线程的。也就是说“单线程执行命令”这个核心设计没有变,多线程只是把网络收发的耗时分摊出去。理解了这一点,你就能很自然地回答“Redis 6.0 多线程是怎么回事”。
2.3 持久化:内存数据库的数据安全感
不少人会问:内存里的数据,万一机器重启了,不就全没了吗?Redis 当然考虑到了这个问题,它提供了两种持久化方案,这也是生产环境必须做的功课。
RDB(Redis DataBase)是快照式持久化,简单说就是定期把内存里的全量数据“拍一张照片”保存到磁盘的 dump.rdb 文件里。它的优点是文件紧凑、加载速度快,非常适合做备份和灾难恢复;缺点是如果两次快照之间发生了数据变更,中间这部分数据就会丢失,因为快照不是每时每刻都在拍的。
AOF(Append Only File)则是日志型持久化,它会把每一条写命令按照追加的方式记录到文件里。你可以把它想象成记账本,每一笔流水都记下来,恢复数据时只要把命令从头到尾重新执行一遍。AOF 提供了多种刷盘策略,比如每秒刷盘、每修改就刷盘,数据安全性更高,但文件体积通常比 RDB 大,恢复速度也相对慢一些。
我习惯打个比方:RDB 像你定期给手机联系人备份到本地,恢复方便但可能漏掉最近新增的号码;AOF 像你随时用备忘录记录每个新号码,更全但记录文件很长。生产环境里最常见的做法是两者同时开启,RDB 做冷备份和快速启动,AOF 保证尽量少丢数据。等后面单独写持久化专题时,我再把 rewrite 机制、fsync 策略、混合持久化这些细节展开讲。
3. 上手实践:把你的第一个 Redis 跑起来
3.1 分平台安装指南:Linux、macOS、Windows、Docker
初学 Redis 最大的门槛不是命令,而是先把环境搞起来。我按不同平台给出最快可行的方案:
Linux 环境
如果你有云服务器或者本地虚拟机,用包管理器安装是最快的。Debian/Ubuntu 系执行:
sudo apt update sudo apt install redis-serverRedHat/CentOS 系可以这样:
sudo yum install redis安装完成后启动服务并验证:
sudo systemctl start redis-server redis-cli ping如果看到返回 PONG,就说明服务已经正常工作了。想改监听端口、密码等配置,通常编辑 /etc/redis/redis.conf 后重启服务即可。源码编译安装更灵活,能选择指定版本,但步骤多一点,我一般建议新手直接用包管理器,等需要定制版本时再上源码编译。
macOS 环境
macOS 上最舒服的方式是 Homebrew:
brew install redis brew services start redisbrew services 能帮你把 Redis 注册成后台服务,开机自启,日常开发非常省心。
Windows 环境
这里必须说实话:Redis 官方其实不原生支持 Windows。网上流传的 Windows 安装包多是一些第三方移植版本,版本普遍滞后,官方仓库不再维护 Windows 版本了。如果你只是本地想跑一下 Redis,我最推荐用 WSL 2(Windows 自带的 Linux 子系统)里安装 Redis,这样环境更接近生产;也可以直接用 Docker 跑一个 Redis 容器,下面马上讲到。
也有人保留着旧版 Windows 安装包,比如 5.0.14.1 之类,能在本地跑起来,但仅适合学习测试,不建议作为业务依赖。看到这里你应该明白:为什么简历上写 Linux 经验很重要,因为大量中间件根本不原生支持 Windows,早一点适应 Linux 环境对后续工作帮助很大。
Docker 环境
如果你机器上已经装了 Docker,这一条是所有人的通用解:
docker run -d --name redis-server -p 6379:6379 redis这一条命令会拉取官方 Redis 镜像(所谓 Redis 镜像就是现成的、包含 Redis 运行环境的 Docker 镜像文件),并启动一个映射到宿主机 6379 端口的容器。需要加密码的话,可以再加一个参数:
docker run -d --name redis-server -p 6379:6379 redis redis-server --requirepass 123456Docker 方案的好处太多了:不用操心系统兼容性、换版本只需要换镜像标签、删除容器对宿主机零污染。我自己做实验和写测试代码时,基本都用 Docker 来快速拉起整套 Redis 环境。
3.2 启动配置与第一个命令
Redis 启动后,默认监听 6379 端口。用客户端连上去,敲下第一组命令,你就算正式入门了:
redis-cli 127.0.0.1:6379> SET name "hello-redis" 127.0.0.1:6379> GET name 127.0.0.1:6379> PINGSET、GET 的语义一看就懂,PING 返回 PONG 表示服务存活。
聊一下几个初学者容易踩坑的配置项:
bind:默认可能只绑定了 127.0.0.1,意味着只有本机能访问。如果你要让其他机器连接,需要改成0.0.0.0或者指定内网 IP,但改完一定要配合密码和防火墙策略,否则等于把数据裸奔在网络上。protected-mode:Redis 默认开启保护模式,混用 bind 和密码时必须理解它的作用:当你绑定了公网地址但又没设密码时,Redis 会拒绝外部连接。这算是一种“默认安全”保护,不建议轻易关掉。requirepass:设置访问密码。连接后需要执行AUTH 密码才能执行命令,或者在连接时直接写redis-cli -a 密码。daemonize:决定 Redis 是否以后台守护进程方式运行。Windows、Docker 里的运行方式略有不同,但本地学习中我把daemonize yes改成后台运行,避免每次关掉终端服务就停了。dir和dbfilename:这两个配置决定 RDB 快照文件存哪里、叫什么名字,对后续做数据备份和迁移非常重要。
我给新手的建议是:初学阶段不要在 bind、protected-mode 上折腾太多,默认本机访问就够了;当你要部署到服务器上跑真实业务时,再认真设计网络暴露、防火墙规则和密码策略。
3.3 可视化客户端:redis-cli 之外的“图形化”选择
命令行虽然强大,但很多人初期看图识字效率更高,尤其想直观看看一个 Key 里存了多少条 List、Hash 里有哪些字段。这时候可视化客户端就能派上用场。
目前常用的有三款:
| 工具 | 特点 | 适合谁 |
|---|---|---|
| RedisInsight | Redis 官方出品的 GUI 工具,功能全面,界面现代 | 想用官方工具、看官方最佳实践的开发者 |
| Redis Desktop Manager(RDM) | 老牌经典,功能稳定,社区版免费 | 习惯传统界面、看中生态成熟度的人 |
| Another Redis Desktop Manager | 开源、轻量、跨平台,适配性不错 | 追求免费轻量、平时只需要基础 CRUD 的开发者 |
无论选哪一款,连接逻辑都差不多:填主机地址、端口、密码(如果有),有些工具还支持 SSH 隧道方式连接远程 Redis。不过我想提醒一句:可视化工具只是锦上添花,实际工作中排查问题、写脚本、看延时统计,最终还是要回到 redis-cli 和命令上。你可以把工具当辅助,但不要把“会用可视化工具”当成“会 Redis”。
4. 你以为 Redis 只是缓存?盘点几个高频应用场景
4.1 缓存:Redis 最广为人知的身份
读多写少的数据,比如商品详情、用户资料、配置项,非常适合放在 Redis 缓存里。经典的缓存策略是 Cache Aside:先查缓存,命中就直接返回;没命中再查数据库,把结果写回缓存,并设置过期时间。这个模式简单可靠,实际项目里九成以上缓存都是这么用的。
不过,“缓存”这两个字背后全是细节。比如“缓存穿透”:用户不断请求一个缓存和数据库里根本就不存在的数据,比如恶意用一个不存在的用户 ID 刷接口,导致每次请求都穿透缓存打到底层数据库;再比如“缓存击穿”:某个热点 Key 过期的一瞬间,大量请求同时冲进数据库;还有人喜欢说“缓存雪崩”:大量 Key 同一时间集中过期,数据库瞬间被打爆。这些词的高频出现,说明它们在生产环境里有多常见。处理手段很多,包括缓存空值、布隆过滤器、加互斥锁、过期时间加随机值等,但这些我打算放到后面“缓存治理”专题里细讲,你了解到有这些坑就已经值回票价了。
4.2 分布式锁:从单体到多实例的并发控制
单体应用里做同步,Java 有 synchronized、Lock;但服务一旦部署了多个实例,锁得让所有实例都能看到,这时候“分布式锁”就登场了。Redis 靠 SETNX 命令实现分布式锁是最经典的做法,核心原理就是:只有一个客户端能成功把 Key 设置进去,谁设置成功,谁就拿到了锁。
简单演示一下加锁逻辑:
# 加锁,px 表示过期时间,防止持锁实例挂掉导致死锁 SET lock:order 1 NX PX 30000 # 业务处理完成后释放锁 DEL lock:order这套方案看起来简单,但细节非常多:锁要设置过期时间防止死锁,释放锁时要判断是不是自己的锁(防止误删别人的锁),过期时间到了但业务还没执行完怎么办,这些都需要引入 Lua 脚本或 Redisson 这样的框架来兜底。我现在讲这个只是让你知道 Redis 还有这个用法,等后面专门讲分布式锁时再展开各种坑。
4.3 更多有趣姿势:计数器、排行榜、消息队列
Redis 能做的不止缓存和锁。
- 计数器:用
INCR article:read:1001就能做文章浏览量自增;INCR天然原子,不会因为并发导致计数少了。面试题里常出现的“Redis INCR 不准”本质是没用对,按 key 粒度各增各的,要做到全局总量正确需要换思路。 - 排行榜:ZSet 是榜单神器,用分数存热度值,
ZADD rank:hot 100 "article1",再通过ZREVRANGE rank:hot 0 9就能拿到 TOP 10。各大排行榜系统背后基本都有 ZSet 的影子。 - 简易消息队列:List 的左进右出 (
LPUSH+BRPOP) 就能实现简单的生产者-消费者模式,配合阻塞命令可以在没有现成 MQ(消息队列)的场景下先顶一阵。当然,更完整的可靠消息队列建议用 Redis Stream 或者专业的 MQ 产品。
这些玩法加在一起,你就能感受到 Redis 为什么被叫作“瑞士军刀”:它不是一个功能单一的缓存,而是一个灵活高效的内存数据结构服务。
5. 从入门到进阶:梳理一套靠谱的学习实操路线
5.1 先把地基打牢:命令、数据类型、持久化
我对学习顺序的建议是:先不要急着去看集群和高可用,先把单机版用熟。第一步,把五种基础数据结构的所有常用命令过一遍,尤其理解 Same Key 在不同数据类型下的行为差异;第二步,把 Redis 配置文件和持久化机制弄清楚,做一次“重启后数据能不能恢复”的实验;第三步,用一门你熟悉的语言(比如 Java 的 Spring Data Redis、Python 的 redis-py)写一个小项目,把缓存读写用起来。
我自己当初学的时候,就是先写了个带登录 Session 共享的小网站,把用户登录状态放进 Redis,才真正理解了 Key 过期时间、序列化和连接池这些概念。如果你第一次接触 Redis,我强烈建议你也用真实项目来带动学习,而不是对着命令表干背。
5.2 核心场景逐个深挖:缓存治理、分布式锁、高可用
基础打完后,就可以进入这个系列后续准备覆盖的内容:缓存穿透、缓存击穿、缓存雪崩怎么预防;分布式锁怎么实现才能保证安全可靠;主从复制、哨兵模式和集群模式到底解决什么问题,它们之间有什么区别。这些内容网上到处都有人写,但真正的价值在于你能不能讲清楚什么场景选什么方案,以及踩坑后怎么排查。比如 Redis 连接偶尔报 “command timed out” 超时异常,很多人第一反应是加超时时间,但真正原因可能是连接池耗尽、慢命令阻塞了事件循环,甚至网络层面抖动。这种经验不亲手排查一次,光看文档体会不出来。
5.3 高频面试题背后其实是同一套底层逻辑
Redis 相关的面试题很多,但核心基本都绕不开:Redis 为什么快?单线程模型有什么利弊?RDB 和 AOF 怎么选?缓存和数据库的一致性怎么解决?大 Key 怎么发现怎么处理?主从延迟怎么降低?热点 Key 怎么应对?
这几个问题表面看是不同知识点的考察,实际上都在考察你对“内存存储、单线程事件循环、网络模型、持久化策略”这几个底层概念的融会贯通程度。你只需要把原理真正吃透,遇到问题自然就不会只停留在“网上说这样干”的表层,而是能推导出当前场景下哪个方案更合理。
5.4 一个我坚持了很久的学习小习惯
最后分享一个我自己的经验,也算给这个系列开个题:我学 Redis 的时候,并没有一上来就背命令,而是每学一个特性都会问一句“没有 Redis 的时候这个问题是怎么解决的”。比如没有 Redis 缓存,数据库就多扛一些压力;没有分布式锁,就用数据库乐观锁或应用层锁;没有 ZSet,排行榜就得通过 SQL 反复排序。带着“解决什么问题”的眼光去学 Redis,你会发现每个设计背后都有合理的动机,学起来轻松得多,面试时说起话来也会更有底气。
下一篇我打算紧接着聊 Redis 的 String 和 Hash 类型到底怎么用才能发挥最大价值,包括对象缓存和序列化的坑。你如果刚起步,不妨先把这篇文章里的命令手动跑一遍,对于“初识 Redis”这个目标来说,你已经比大多数只会背概念的人走得靠前了。