前言
redis 是目前使用最广泛的高性能内存数据库之一。本文从基础概念到安装部署、常用命令、高可用、持久化机制,再到性能优化,一文带你全面掌握 redis。
1. 关系型数据库 vs 非关系型数据库
关系型数据库(sql)
- 特点:表格模型(行+列)、使用 sql 语言、强事务 acid、纵向扩展(升级硬件)。
- 常见产品:mysql、oracle、postgresql。
- 场景示例:银行转账,必须保证两边同时成功,事务性要求强。
非关系型数据库(nosql)
- 特点:键值对/文档/图结构存储、无需固定表结构、高并发、高可扩展、横向扩展(增加节点)。
- 常见产品:redis、mongodb、hbase、memcached。
- 场景示例:微信聊天,一条消息可能是文字、图片、语音,不适合表格存储,更适合用文档型数据库。
2. redis 简介
- 定义:开源、c 语言编写、基于内存、支持持久化的键值数据库。
- 优势:
- 高性能:读取可达 11 万次/s,写入 8 万次/s。
- 支持多种数据结构:string、list、hash、set、sorted set。
- 支持持久化:rdb、aof。
- 主从复制,方便数据备份。
- 为什么快?
- 纯内存操作,避免磁盘 io。
- 单线程,避免锁开销。
- i/o 多路复用,高并发。
应用示例:
- 秒杀库存扣减、订单写入放在 redis,减轻数据库压力。
- 抖音热搜榜:用 sorted set 存储关键词和热度,实时排序。
3. redis 安装与部署
- 停防火墙、关闭 selinux。
- 安装依赖:
yum install -y gcc gcc-c++ make
。 - 下载并解压 redis 源码,执行
make && make prefix=/usr/local/redis install
。 - 使用
cd utils/install_server.sh
配置服务,按提示输入路径。 - 建立软链接
ln -s /usr/local/redis/bin/* /usr/local/bin/
方便全局使用。 - 常用控制命令:
/etc/init.d/redis_6379 start|stop|restart|status
- 修改
/etc/redis/6379.conf
:bind 127.0.0.1 192.168.x.x
:监听地址。port 6379
:默认端口。daemonize yes
:守护进程。logfile /var/log/redis_6379.log
:日志文件。
4. redis 常用命令
- 客户端工具:
redis-cli -h host -p port -a password
- 压力测试:
redis-benchmark -c 100 -n 100000
- 数据操作:
set key value get key exists key del key keys pattern rename oldkey newkey
- 多数据库:
- 默认 0~15 共 16 个库。
select n
切换库,move key n
移动数据。flushdb
清空当前库,flushall
清空所有库(慎用)。
5. redis 高可用
- 持久化:rdb/aof 将内存数据保存到磁盘,防止进程退出后丢失。
- 主从复制:一主多从,主写从读,实现负载均衡。
- 哨兵(sentinel):主机宕机自动切换到从机。
- 集群(cluster):多节点分片存储,解决单机容量限制和写入瓶颈。
6. 持久化机制
6.1 rdb 持久化
① 原理
rdb 是将 redis 某一时刻的内存数据快照(snapshot)保存到磁盘的二进制文件 dump.rdb
中。 redis 通过 fork
一个子进程把内存数据写入临时 rdb 文件,完成后再替换旧文件。
② 触发条件
- 手动触发:
save
:阻塞主进程直到完成,不推荐在线上使用。bgsave
:fork
子进程执行保存,主进程继续处理请求(推荐)。
- 自动触发: 在
redis.conf
里通过save m n
配置:
save 900 1 save 300 10 save 60 10000
- 其他触发:
- 从节点全量复制时,主节点会自动执行
bgsave
。 - 执行
shutdown
时如果没开启 aof,会自动做一次 rdb。
- 从节点全量复制时,主节点会自动执行
③ 执行流程
- 主进程检查是否已有持久化子进程在运行,若有则直接返回。
fork
子进程(此过程主进程短暂阻塞)。- 子进程把内存数据写入临时 rdb 文件。
- 写完后原子替换旧文件,发送完成信号给主进程。
- 主进程更新状态。
④ 启动加载
redis 启动时若开启 aof 优先加载 aof,否则加载 rdb 文件。载入期间 redis 会阻塞直至完成。
⑤ 优缺点
- 优点:文件紧凑、体积小、适合全量备份和传输;恢复速度快;对性能影响小。
- 缺点:无法做到实时持久化,可能丢失几分钟数据;
fork
阻塞和磁盘 io 压力。
6.2 aof 持久化
① 原理
aof(append only file)是把 redis 执行过的写/删除命令按 redis 协议格式追加到日志文件中。重启时 redis 重新执行 aof 文件中的命令恢复数据。查询类命令不会写入 aof。
② 开启 aof
默认关闭,需要在 redis.conf
开启:
appendonly yes appendfilename "appendonly.aof" appendfsync everysec
③ 执行流程
- 命令追加 (append):redis 先将命令追加到 aof 缓冲区
aof_buf
。 - 文件写入/同步 (write & fsync):
appendfsync always
:每条命令都 fsync,同步最安全但最慢。appendfsync no
:仅 write,由 os 决定何时刷盘,不安全但最快。appendfsync everysec
:每秒 fsync 一次(默认,性能与安全折中)。
- 文件重写 (rewrite):
- aof 文件越来越大时 redis 通过
bgrewriteaof
重写文件。 - 重写并不是读取旧 aof,而是把当前内存状态重新生成最少命令集写入新文件。
- 过期数据、无效命令不写入;多条命令可合并成一条,大幅压缩文件。
- aof 文件越来越大时 redis 通过
- 触发:
- 手动:
bgrewriteaof
。 - 自动:满足
auto-aof-rewrite-min-size
和auto-aof-rewrite-percentage
。 - 重写期间缓冲:redis 把新写命令同时追加到旧缓冲区和
aof_rewrite_buf
,确保新文件与当前状态一致。
- 手动:
④ 启动加载
redis 启动时若 aof 开启则优先加载 aof;aof 文件不存在时才加载 rdb。 若 aof 文件尾部不完整(如宕机),且 aof-load-truncated yes
,则忽略尾部继续启动。
⑤ 优缺点
- 优点:实时性更好(秒级持久化)、可读性强、兼容性好。
- 缺点:文件大、恢复速度慢、写磁盘频率高对性能影响更大,重写过程也有 fork 阻塞与 io 压力。
6.3 对比总结
特性 | rdb | aof |
---|---|---|
持久化方式 | 周期性快照 | 逐条命令日志 |
文件大小 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全 | 可能丢几分钟 | 丢失不超过 1 秒(默认) |
性能影响 | 小 | 大 |
实践建议:
- 对数据安全要求不高:仅 rdb。
- 对实时性要求高:开启 aof(默认 everysec)+定期 rdb 做全量备份。
- redis 4.0 以后支持混合持久化,结合两者优点。
7. 性能管理与优化
内存指标与碎片率
used_memory
:实际用来存储数据的内存。used_memory_rss
:进程占用的物理内存。- 内存碎片率 =
used_memory_rss / used_memory
:- ≈1:正常。
1.5:碎片较高,低峰期重启 redis 释放碎片。
- <1:内存不足可能触发 swap。
查看命令:
redis-cli info memory
优化建议
- 合理规划实例内存(单实例不超过物理内存 70%~80%)。
- 多用 hash 结构存储减少碎片。
- 给 key 设置过期时间:
set session:123 abcdef ex 3600
- 设置最大内存与淘汰策略:
maxmemory 2gb maxmemory-policy allkeys-lru
- 关闭或限制 swap。
内存淘汰策略
当数据量超过 maxmemory
时,redis 按策略回收空间:
策略 | 描述 |
---|---|
volatile-lru | 从有 ttl 的 key 中淘汰最少使用的 |
volatile-ttl | 从有 ttl 的 key 中淘汰最快过期的 |
volatile-random | 从有 ttl 的 key 中随机淘汰 |
allkeys-lru | 从所有 key 中淘汰最少使用的(最常用) |
allkeys-random | 从所有 key 中随机淘汰 |
noeviction | 不淘汰,内存不足时报错 |
实践建议:
- 缓存场景:
allkeys-lru
。 - 需要保留核心数据但允许部分丢失:
volatile-lru
。 - 严格要求数据不丢失:
noeviction
。
8. 常见缓存问题与解决方案
8.1 缓存穿透
现象:请求的 key 在缓存和数据库都不存在,大量请求直达数据库,造成压力。 原因:恶意攻击或查询不存在数据。
解决方案:
- 缓存空值:把不存在的数据也缓存一份空对象并设置较短 ttl。
- 布隆过滤器(bloom filter):在缓存前加过滤器,请求 key 不在过滤器中直接返回空,减少 db 查询。
- 参数校验:对明显非法参数直接拦截。
8.2 缓存击穿
现象:某个热点 key 正好过期瞬间,大量请求同时穿透到数据库。 原因:缓存数据过期瞬间并发请求落到 db。
解决方案:
- 热点数据不过期:为热点 key 设置长 ttl 或永不过期。
- 加互斥锁(mutex):第一个请求获得锁去 db,其余请求等待。
- 预加载/异步刷新:在数据快过期前提前刷新缓存。
- 过期时间随机化:在 ttl 上加随机值避免集中过期。
8.3 缓存雪崩
现象:大量缓存同时失效或 redis 宕机,所有请求涌入数据库。 原因:集中过期、缓存不可用、没有熔断限流。
解决方案:
- 过期时间分散:设置 ttl 时加上随机数,避免同一时刻大面积过期。
- 双缓存机制:在缓存失效前提前准备备用缓存,主缓存宕机时快速切换。
- 限流与熔断:在应用层限制请求速率,避免瞬时打爆数据库。
- redis 高可用:主从+哨兵或集群,减少缓存整体不可用风险。
8.4 综合实践建议
- 穿透 → 布隆过滤器 + 缓存空值。
- 击穿 → 热点 key 不过期 + 加锁或提前刷新。
- 雪崩 → ttl 随机 + 限流熔断 + 高可用部署。
结语
掌握 redis 的 rdb/aof 持久化原理、缓存问题与解决方案,不仅能保证数据安全,也能让你的系统在高并发场景下稳定运行。
到此这篇关于redis 配置与优化完全指南的文章就介绍到这了,更多相关redis 配置与优化内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论