Redis 学习笔记(第一期):概述、安装配置与核心理论
本笔记为 Redis 系列第一期,涵盖:Redis 简介、优势、核心特性(单线程、epoll)、缓存实现原理(旁路缓存、穿透/击穿/雪崩)、Pipeline 流水线、安装部署(源码和 YUM)、配置文件详解、动态配置与慢查询。所有代码和命令均已加以整理和注释。
一、Redis 简介
1.1 什么是 Redis?
Redis(REmote DIctionary Server)是完全开源的、遵守 BSD 协议的高性能 key-value 数据库。它与其他 key-value 缓存产品相比,有三个显著特点:
- 支持持久化:可将内存中的数据保存到磁盘,重启后重新加载使用。
- 丰富的数据结构:不仅支持简单的 string,还支持 list、set、zset(有序集合)、hash 等。
- 支持数据备份:即 master-slave 模式的数据复制。
1.2 Redis 优势
| 优势 | 说明 |
|---|---|
| 性能极高 | 可达 10 万 ~ 100 万+ QPS,微秒级响应;MySQL 通常几千~几万 QPS,毫秒级响应 |
| 丰富的数据类型 | 支持二进制安全的 Strings、Lists、Hashes、Sets 及 Ordered Sets |
| 原子性 | 所有操作都是原子性的(要么成功执行,要么完全不执行);多个操作也支持事务(MULTI/EXEC) |
| 丰富的特性 | 支持 publish/subscribe、通知、key 过期、Lua 脚本、事务、pipeline 等 |
| 简单 | 单机核心代码只有约 23000 行,不依赖外部库,使用简单 |
1.3 与其他 key-value 存储的不同
- 数据结构更复杂,支持对数据结构的原子性操作。
- 数据在内存中操作,非常快,同时磁盘格式紧凑,以追加方式产生,无需随机访问。
- 适合做内部复杂性强的功能,同时保持简单透明的编程模型。
1.4 常见应用场景
| 场景 | 说明 | 实现方式 |
|---|---|---|
| 热点数据缓存 | 商品详情、用户信息 | Cache-Aside 模式,设置 TTL,空值缓存防穿透 |
| 分布式锁 | 协同操作共享资源 | SET key value NX PX 30000,Lua 脚本解锁 |
| 计数器与限流 | 阅读量、访问频率 | INCR 原子递增,结合过期时间实现限流 |
| 排行榜系统 | 积分榜、销量榜 | ZADD 添加分数,ZRANGE / ZREVRANGE 排序 |
| 分布式会话 | 多服务实例会话共享 | 将 session 存入 Redis,设置过期时间 |
| 消息队列 | 异步解耦、削峰填谷 | List(LPUSH/BRPOP)或 Pub/Sub |
| 位图应用 | 签到、活跃用户统计 | SETBIT / GETBIT,节省空间 |
| 地理信息存储 | 附近的人、店铺 | GEO 数据结构(GEOADD / GEORADIUS) |
二、Redis 核心特性详解
2.1 单线程模型(6.0 版本前)
Redis 使用单线程处理客户端请求,原因如下:
- 操作主要在内存中,比访问硬盘快得多。
- Redis 核心功能比数据库简单(无复杂约束、查询优化等)。
- 单线程避免了线程竞争开销,每个操作短平快。
- 网络 IO 使用了 epoll(IO 多路复用),可同时监听多个 socket,只在活跃时处理。
类比(教材中的"买饭"故事):
- 单线程 = 一个人依次去买三份饭(总时间长)。
- 多线程 = 三个人同时去买(时间缩短,但系统开销大)。
- IO 多路复用 = 一个人分别告诉三个摊位"好了叫我",然后同时等待通知(只需一个线程,等待时间接近多线程)。
注意 :Redis 6.0 后引入多线程处理网络 IO,但命令执行仍是单线程。早期版本(3.0 以后)也有其他辅助线程(如
fsync、close file descriptor),但核心命令处理是单线程。
2.2 epoll 原理
epoll 是 Linux 提供的 IO 多路复用 API,基于事件通知/回调机制。相比 select(需要主动轮询),epoll 效率更高,是服务器开发的主流方案。
2.3 缓存实现过程
计算机系统中的三层存储结构:CPU 缓存 → 内存(Redis) → 磁盘(数据库)。
两个特征:
- 缓存是快速子系统,避免每次从慢速子系统存取。
- 缓存容量小于后端系统,不可能存放所有数据。
2.3.1 缓存处理请求的两种情况
- 缓存命中:数据在 Redis 中 → 直接读取,速度快。
- 缓存缺失:数据不在 Redis 中 → 从数据库读取,并更新缓存(可能影响性能)。
2.3.2 旁路缓存
Redis 是一个独立软件,应用程序需要显式增加缓存操作代码。因此称为旁路缓存(Side Cache)。
需要增加的代码:
- 读取数据时先调用
GET。 - 缓存缺失时连接数据库读取,再
SET写入缓存。 - 更新数据时更新数据库并删除/更新缓存。
2.3.3 缓存的类型
| 类型 | 特点 | 写操作 | 数据可靠性 |
|---|---|---|---|
| 只读缓存 | 读请求先查缓存,写请求直接发往数据库,并删除缓存中对应数据 | 数据库 | 高(数据在数据库) |
| 读写缓存 | 读写都先操作缓存,再同步或异步写回数据库 | 缓存 | 取决于同步策略 |
- 同步直写:同时写缓存和数据库,保证数据可靠,响应稍慢。
- 异步写回:先写缓存,淘汰时再写回数据库,响应快,但可能丢数据。
2.3.4 缓存穿透、击穿、雪崩
| 问题 | 定义 | 通俗理解 | 解决方案 |
|---|---|---|---|
| 穿透 | 查询不存在的数据,缓存和数据库中都没有,每次请求直达数据库 | 假身份证过检票口,次次查后台 | 接口校验、缓存空值(短 TTL)、布隆过滤器 |
| 击穿 | 热点 key 过期,大量并发请求同时打到数据库 | VIP 通道关闭,万人挤门 | 加锁排队、设置永不过时(配合主动更新) |
| 雪崩 | 大面积 key 同时过期或 Redis 宕机,所有请求涌向数据库 | 所有闸机同时坏,大门被挤爆 | 过期时间加随机值、高可用集群、限流熔断、多级缓存 |
2.4 Pipeline 流水线
Redis 执行一条命令需 4 个过程:发送命令 → 命令排队 → 命令执行 → 返回结果。整个过程称为 RTT(Round Trip Time)。
- 未使用 Pipeline:执行 n 条命令需要 n 次 RTT。
- 使用 Pipeline:将一组命令打包,通过一次 RTT 发送给 Redis,再按顺序返回结果。
性能对比(教材实验数据):
| 网络环境 | 非 Pipeline | Pipeline | 提升倍数 |
|---|---|---|---|
| 本机 (0.17ms) | 573 ms | 134 ms | 约 4.3 倍 |
| 内网服务器 (0.41ms) | 1610 ms | 240 ms | 约 6.7 倍 |
| 异地机房 (7ms) | 80000 ms | 1104 ms | 约 72 倍 |
结论:网络延迟越大,Pipeline 提升越明显。注意:Pipeline 不是原子操作,且需要客户端和服务端支持。
三、Redis 安装与配置
3.1 CentOS 7 源码编译安装
bash
# 安装依赖
yum install tcl gcc gcc-c++ -y
# 解压安装包
tar zxvf redis-6.2.14.tar.gz -C /usr/local/
# 编译安装
cd /usr/local/redis-6.2.14/
make && make install
# 启动(后台运行)
redis-server redis.conf &
# 查看端口
netstat -antp | grep 6379
# 客户端连接
redis-cli
127.0.0.1:6379> ping
PONG
3.2 CentOS 8 / CentOS Stream 8 YUM 安装
bash
# 查看可用版本
dnf info redis
# 安装
dnf install -y redis
# 启动并设置开机自启
systemctl enable redis --now
# 查看进程和端口
pstree -p | grep redis
ss -tunlp | grep 6379
# 测试
redis-cli ping
PONG
3.3 开启多实例
bash
# 启动另一个端口实例
redis-server --port 6380 &
ss -ntl | grep 6380
# 连接
redis-cli -p 6380
127.0.0.1:6380> ping
PONG
四、Redis 配置文件详解(核心参数)
路径:
/etc/redis.conf(YUM 安装)或redis-6.2.14/redis.conf(源码)
| 参数 | 默认值 | 说明 |
|---|---|---|
bind |
127.0.0.1 | 监听地址;若需远程访问,改为 0.0.0.0(需配合密码) |
protected-mode |
yes | 保护模式;无密码且绑定了外网 IP 时,限制外网访问 |
port |
6379 | 监听端口(趣味来源:手机键盘 MERZ → 6379) |
tcp-backlog |
511 | TCP 连接全队列长度,高并发调大 |
timeout |
0 | 客户端空闲超时(0 表示永不关闭) |
tcp-keepalive |
300 | 每 300 秒发送 keepalive 探测包 |
daemonize |
no | 是否守护进程(yes 后台运行,no 前台) |
pidfile |
/var/run/redis_6379.pid | PID 文件路径 |
loglevel |
notice | 日志级别(debug/verbose/notice/warning) |
logfile |
"" | 日志文件路径,空表示标准输出 |
databases |
16 | 逻辑数据库数量(0-15) |
save |
900 1 300 10 60 10000 | RDB 触发条件(时间/写操作数) |
stop-writes-on-bgsave-error |
yes | RDB 失败后是否拒绝写入 |
rdbcompression |
yes | 是否压缩 RDB 文件(LZF) |
rdbchecksum |
yes | 是否添加 CRC64 校验和 |
dbfilename |
dump.rdb | RDB 文件名 |
dir |
/var/lib/redis | 工作目录(RDB、AOF 存放处) |
requirepass |
(空) | 客户端密码(生产必设) |
maxclients |
10000 | 最大客户端连接数 |
appendonly |
no | 是否开启 AOF 持久化 |
appendfilename |
"appendonly.aof" | AOF 文件名 |
appendfsync |
everysec | AOF 同步策略(always/everysec/no) |
slowlog-log-slower-than |
10000(微秒) | 慢查询阈值 |
slowlog-max-len |
128 | 慢查询最大记录条数 |
五、动态配置与慢查询
5.1 CONFIG 命令
CONFIG 命令可以在不重启 Redis 的情况下动态修改配置(但部分参数不支持,且修改后不会持久化到配置文件)。
bash
# 查看所有配置
CONFIG GET *
# 查看指定配置
CONFIG GET requirepass
CONFIG GET bind
# 设置配置(示例:设置密码)
CONFIG SET requirepass 123456
# 设置最大内存(字节或单位)
CONFIG SET maxmemory 1G
注意:Redis 5 不支持动态修改端口;Redis 6.2.14 支持动态修改 bind。
5.2 慢查询日志
慢查询发生在命令执行阶段(不包括网络和排队时间)。配置 slowlog-log-slower-than 阈值(微秒),超过则记录。
bash
# 修改阈值和最大记录数(配置文件或动态)
vim /etc/redis.conf
slowlog-log-slower-than 1 # 超过 1 微秒即记录(测试用)
slowlog-max-len 1024
# 重启或动态应用
CONFIG SET slowlog-log-slower-than 1
CONFIG SET slowlog-max-len 1024
# 查看慢日志
SLOWLOG LEN
SLOWLOG GET
SLOWLOG GET 2 # 获取最近 2 条
# 清空慢日志
SLOWLOG RESET
慢日志输出示例:
text
1) (integer) 5 # 日志唯一 ID
2) (integer) 1770892970 # Unix 时间戳
3) (integer) 3 # 执行耗时(微秒)
4) 1) "SLOWLOG" # 执行的命令
2) "LEN"
5) "127.0.0.1:56406" # 客户端 IP 和端口
6) "" # 客户端名称
六、常见错误与排查(第一期)
| 错误现象 | 可能原因 | 解决方法 |
|---|---|---|
远程连接失败 Connection refused |
bind 127.0.0.1 或防火墙阻止 |
修改 bind 0.0.0.0,关闭防火墙或开放 6379 端口 |
DENIED Redis is running in protected mode |
未设置密码 + bind 外网 IP | 设置 requirepass 或 bind 127.0.0.1 |
MISCONF Redis is configured to save RDB snapshots |
磁盘空间不足或权限问题 | 检查磁盘,确保 dir 目录可写 |
ERR Unsupported CONFIG parameter: port |
Redis 5 不支持动态修改端口 | 升级到 Redis 6.2+ 或修改配置文件重启 |
| 慢查询日志不记录 | 阈值设置过大或未开启 | 设置 slowlog-log-slower-than 为较小值(如 10000) |
七、本期知识点一览表
| 类别 | 知识点 | 关键命令/配置 |
|---|---|---|
| 基础概念 | Redis 三个特点 | 持久化、多种数据结构、主从备份 |
| 单线程原因 | 内存操作、无竞争、epoll | |
| IO 多路复用 | epoll(事件通知) | |
| 缓存 | 旁路缓存 | 应用程序显式调用 GET/SET |
| 缓存穿透/击穿/雪崩 | 解决方案:空值缓存、布隆过滤器、随机过期时间 | |
| Pipeline | 批量命令减少 RTT | 性能提升数倍(依赖网络延迟) |
| 安装 | 源码编译 | make && make install,redis-server |
| YUM 安装 | dnf install redis,systemctl enable redis |
|
| 多实例 | redis-server --port 6380 |
|
| 配置 | 核心参数 | bind, port, requirepass, save, appendonly 等 |
| 动态配置 | CONFIG SET/GET | 运行时修改,不持久化 |
| 慢查询 | 阈值、日志 | slowlog-log-slower-than,SLOWLOG GET |
下一期预告:Redis 核心数据类型与消息队列(string、list、set、zset、hash 完整命令演示,排行榜、共同好友、消息队列实战)。