简介:这份PPT面向后端开发、运维及缓存技术学习者,系统梳理Redis的核心知识体系,帮助读者在面试复习或项目选型时快速建立全局认知。内容涵盖Redis简介、配置文件详解、RDB与AOF两种持久化策略对比,以及key、String等常用命令的用法说明,并客观分析其读写性能优异、原子性、数据结构丰富等优点,以及在线扩容困难、宕机影响部分读写等局限。资源包共1个pptx文件,大小约1.59MB,以幻灯片形式呈现,结构清晰、便于课堂分享或自学翻阅。目前已有161人学习浏览,适合作为Redis入门与进阶的参考材料,帮助读者理解redis.conf关键配置项、持久化机制取舍及命令操作要点,为实际开发中的缓存设计与数据可靠性保障提供思路。
1. 从一份 Redis 分享 PPT 说起:为什么值得逐页拆一遍
很多人第一次接触 Redis,是在项目里被一句“加个缓存”推着走的。真到线上出问题,才发现自己连redis.conf里save和appendfsync的区别都说不清。这份《Redis分享.pptx》就是一份典型的内部技术分享材料,覆盖了简介、配置文件、RDB/AOF 持久化、五大基本数据结构的命令清单,以及事务和发布订阅。它不花哨,但把 Redis 从“会用”到“敢调”的那条线基本铺全了。
它适合三类人:刚接手缓存模块、需要快速补齐命令和配置认知的后端新手;准备做技术分享、想找一份结构清晰提纲的工程师;以及线上被持久化策略坑过、想回头系统梳理 RDB 与 AOF 取舍的老手。下面我不按 PPT 页码复述,而是按“能落地”的顺序,把它拆成可复现的操作和可避开的坑。
2. 配置文件与持久化:把 redis.conf 里那几个关键参数讲透
2.1 启动前先改哪几行:端口、守护进程与数据库数量
拿到一份 Redis 环境,第一件事不是敲命令,而是看redis.conf。这份 PPT 里列出的配置项不多,但每一项都直接影响你后面调试的手感。常见做法是先把下面这几项确认一遍,再启动服务。
# 查看当前生效的配置(不重启也能读) redis-cli CONFIG GET port redis-cli CONFIG GET databases redis-cli CONFIG GET daemonize # 运行时临时改(重启失效,仅用于验证) redis-cli CONFIG SET timeout 300port 6379是默认监听端口,改它通常是为了多实例共存或避开端口冲突。daemonize yes让 Redis 以守护进程方式跑在后台,生产环境基本都开;但如果你在容器里跑,很多基础镜像默认是no,靠前台进程维持容器生命周期,这时候硬改成yes反而会让容器一起退出。databases 16是默认库数量,编号 0 到 15,SELECT命令切换。注意:集群模式下只有 0 号库可用,这个限制在单机调试时很容易被忽略。
timeout 0表示客户端闲置多久后断开,0 是永不主动断开。这个值设太小,连接池里的空闲连接会被服务端单方面掐掉,客户端拿到的是“连接被重置”,排查起来相当玄学。tcp-backlog 511是 TCP 已完成连接队列长度,高并发场景下如果发现握手阶段丢连接,可以适当调大,但要配合系统somaxconn一起改。loglevel notice是默认日志级别,排查持久化问题时临时调到debug能看到 fork 和重写的细节。
2.2 RDB 快照:save 触发条件与 fork 的代价
RDB 是把某一时刻的全量数据写成一个二进制快照文件,默认叫dump.rdb。PPT 里给出的核心配置是save 60 1000,意思是 60 秒内有 1000 次写操作就触发一次快照。这个“次数”指的是写命令的累计变更数,不是读。
# 手动触发一次 RDB 快照(阻塞式,慎用) redis-cli SAVE # 后台触发快照(fork 子进程,不阻塞主进程) redis-cli BGSAVE # 查看最近一次快照是否成功 redis-cli LASTSAVEstop-writes-on-bgsave-error no这一项值得单独说。默认是yes,意思是后台快照失败就停止接收写请求。这个设计的初衷是防止你在持久化已经坏掉的情况下继续写数据,但副作用是:磁盘满了或者权限错了,Redis 会直接拒绝所有写操作,业务侧看到的是“突然不能写了”。我一般会在监控到位的前提下把它设成no,让写继续,同时告警去修磁盘,而不是让整个写入链路停摆。
rdbcompression yes控制是否对快照做 LZF 压缩,省磁盘但费一点 CPU,数据量大时建议保留。dbfilename dump.rdb是文件名,改它主要是为了多实例隔离。RDB 最大的代价在 fork:数据量到几个 G 时,fork 子进程那一下会明显卡顿,PPT 里也点出了“无法在毫秒级响应客户端请求”。所以save的触发频率不能太密,数据量大的实例更依赖从节点做备份。
2.3 AOF 追加日志:appendfsync 三档怎么选
AOF 记录的是每一条写命令,重启时重放。PPT 里appendonly yes是总开关,appendfsync有三档:always、everysec、no。这三档直接决定你丢数据的窗口。
# 开启 AOF(改配置文件后重启,或运行时切换) redis-cli CONFIG SET appendonly yes # 查看 AOF 当前状态 redis-cli INFO persistence | grep -E "aof_enabled|aof_last_bgrewrite_status"always每条命令都同步落盘,最安全但性能最差,QPS 会掉一个量级。everysec每秒同步一次,是默认推荐值,最多丢 1 秒数据,性能和安全平衡得最好。no交给操作系统决定何时刷盘,性能最好但丢多少完全不可控,生产环境基本不选。
no-appendfsync-on-rewrite no这一项容易被忽略。AOF 重写期间会有大量磁盘 IO,如果这项设成yes,重写时就不做 fsync,避免 IO 争抢,代价是重写期间的数据可能丢。auto-aof-rewrite-percentage 100和auto-aof-rewrite-min-size 64m是一对:当前 AOF 文件比上次重写后大一倍,且超过 64MB,才触发重写。只设百分比不设最小体积,小文件会频繁重写;只设体积不设百分比,文件会无限膨胀。
提示:RDB 和 AOF 可以同时开。重启时 Redis 优先用 AOF 恢复,因为它的数据更完整。但如果你只是拿 Redis 当纯缓存,两种都可以关,靠上游数据源兜底。
3. 五大基本数据结构的命令落地:从 key 管理到有序集合
3.1 key 的通用操作:过期、类型与遍历的边界
PPT 里 key 相关命令列得很全,但真正天天用的是EXPIRE、TTL和TYPE。缓存场景下,几乎每个 key 都该有过期时间,否则内存只涨不降。
# 设置 key 并在 60 秒后过期 redis-cli SET session:1001 "token-abc" EX 60 # 查看剩余生存时间(-1 永久,-2 已不存在) redis-cli TTL session:1001 # 移除过期时间,变成永久 key redis-cli PERSIST session:1001 # 查看 key 的值类型 redis-cli TYPE session:1001EXISTS返回 1 或 0,DEL可以一次删多个 key,不存在的会被忽略。RENAME在 key 不存在时会直接报错,这个和很多人的直觉相反。KEYS pattern是排查时的常用命令,但它是 O(N) 且会阻塞主线程,线上数据量上万就别用了,换成SCAN游标迭代。
# 用 SCAN 替代 KEYS,每次返回一批 redis-cli SCAN 0 MATCH "session:*" COUNT 100SCAN的COUNT只是提示,不保证每次返回这么多,也不保证不重复。要完整遍历得循环拿游标,直到游标回到 0。这是用复杂度换安全性的典型取舍。
3.2 String 与 Hash:计数器、批量读写和字段级操作
String 是最常用的类型,PPT 里INCR、DECR、INCRBY这几个命令是计数器场景的基石。INCR在 key 不存在时会先初始化为 0 再自增,所以不用担心空值报错。
# 计数器:文章阅读量 redis-cli INCR article:2001:views redis-cli INCRBY article:2001:views 10 # 批量设置与读取,减少往返 redis-cli MSET user:1:name "A" user:1:age "28" redis-cli MGET user:1:name user:1:age # 设置值同时带过期,原子操作 redis-cli SETEX captcha:13800000000 300 "839201"SETEX和先SET再EXPIRE的区别在于原子性,前者不会出现“值写进去了但过期没设上”的中间态。GETSET是设新值返回旧值,适合做“取走并重置”的逻辑。APPEND在 key 不存在时等同于SET,存在时追加到末尾,用来拼日志片段可以,但别拿它当字符串拼接的主力,长度不可控。
Hash 适合存对象,字段级读写比整个 String 序列化再反序列化省事。HSET和HMSET功能重叠,新版本里HSET已支持多字段,HMSET逐渐被替代。HINCRBY可以对单个字段做计数,比如给用户对象的积分字段自增。
# 存一个用户对象 redis-cli HSET user:1 name "A" age 28 score 100 # 只给 score 字段加 5 redis-cli HINCRBY user:1 score 5 # 取全部字段 redis-cli HGETALL user:1 # 判断字段是否存在 redis-cli HEXISTS user:1 emailHGETALL在字段很多时会一次性返回全部,大 Hash 上要慎用,可以改用HSCAN。HLEN拿字段数量,HDEL删字段,HKEYS和HVALS分别拿字段名和值,按需取,别习惯性全量拉。
3.3 List、Set 与 Sorted Set:队列、去重和排行榜
List 是双向链表,LPUSH从表头进,RPUSH从表尾进,配合LPOP/RPOP就是队列或栈。BLPOP/BRPOP是阻塞版本,列表空时连接挂起等,适合做简单的任务队列。
# 生产者从左边推 redis-cli LPUSH queue:tasks "task-1" "task-2" # 消费者从右边阻塞取,超时 5 秒 redis-cli BRPOP queue:tasks 5 # 保留列表前 100 条,其余裁掉 redis-cli LTRIM queue:tasks 0 99LTRIM是控制 List 长度的关键,日志类列表不裁剪迟早撑爆内存。LREM按 count 删值,count 正负零分别代表从头删、从尾删、全删,PPT 里写得很清楚,实际用的时候容易记反。
Set 是无序去重集合,SADD加成员,SISMEMBER判断存在,SINTER、SUNION、SDIFF做交并差。共同关注、标签去重这类场景直接用它。
# 两个用户的关注集合 redis-cli SADD follow:A "u1" "u2" "u3" redis-cli SADD follow:B "u2" "u3" "u4" # 共同关注(交集) redis-cli SINTER follow:A follow:B # 差集并存储 redis-cli SDIFFSTORE follow:A_only follow:A follow:BSorted Set 带分数,ZADD加成员和分数,ZRANGE按排名取,ZREVRANGE倒序。排行榜、延迟队列都靠它。
# 排行榜 redis-cli ZADD rank:score 100 "player:A" 85 "player:B" 92 "player:C" # 取前三名(从高到低) redis-cli ZREVRANGE rank:score 0 2 WITHSCORES # 按分数区间取 redis-cli ZRANGEBYSCORE rank:score 90 100ZRANGEBYSCORE的区间默认闭区间,要开区间就在分数前加(。ZINCRBY给成员加分,适合实时更新榜单。
4. 事务与发布订阅:原子性边界和消息模型的真实样子
4.1 MULTI/EXEC:它不是回滚,是排队执行
PPT 里事务部分列了MULTI、EXEC、DISCARD、WATCH、UNWATCH。这里有个高频误解:Redis 事务不支持回滚。如果队列里某条命令执行时报错(比如对 String 用了LPUSH),其他命令照样执行,不会整体撤销。
# 开启事务 redis-cli MULTI # 命令入队,返回 QUEUED redis-cli SET tx:key "1" redis-cli INCR tx:key # 执行 redis-cli EXECWATCH是乐观锁:在MULTI之前监视某个 key,如果EXEC之前这个 key 被别的客户端改了,整个事务被打断,EXEC返回 nil。这适合“读-改-写”的并发控制,但要注意WATCH必须在MULTI之前调用,且监视的 key 一旦被改就得重试整个流程。
# 乐观锁示例:库存扣减 redis-cli WATCH stock:1001 redis-cli GET stock:1001 # 假设读到 10,业务判断后 redis-cli MULTI redis-cli DECRBY stock:1001 1 redis-cli EXEC # 如果 EXEC 返回 nil,说明 stock:1001 被改过,需要重试DISCARD放弃事务,UNWATCH取消所有监视。事务里的命令是排队后一次性发送的,减少了网络往返,但别把它当成数据库事务来用。
4.2 发布订阅:没有持久化的广播
SUBSCRIBE订阅频道,PUBLISH发消息,PUBSUB CHANNELS看活跃频道,PUBSUB NUMSUB看某频道订阅者数。发布订阅是即时的,消息不落盘,订阅者掉线期间的消息直接丢失。
# 终端 A:订阅 redis-cli SUBSCRIBE news:tech # 终端 B:发布 redis-cli PUBLISH news:tech "hello" # 查看活跃频道 redis-cli PUBSUB CHANNELS "news:*" # 查看某频道订阅者数量 redis-cli PUBSUB NUMSUB news:techUNSUBSCRIBE退订,不指定频道就退全部。发布订阅适合做配置推送、轻量通知,但别拿它当可靠消息队列。需要可靠性得用 List 或 Stream,PPT 里没展开 Stream,但这是 Redis 5.0 之后消息场景的常见替代方案。
注意:发布订阅的订阅者如果处理慢,消息会在客户端缓冲区堆积,超过
client-output-buffer-limit pubsub限制会被强制断开。这个限制在redis.conf里默认是 32MB 硬限、8MB 软限持续 60 秒,大消息量场景要留意。
5. 避坑与排查:那些 PPT 不会写但线上一定会遇到的事
5.1 持久化相关:fork 卡顿、AOF 膨胀与恢复慢
现象:数据量到几个 G 后,每隔一段时间主线程出现几百毫秒到秒级的卡顿,监控上 QPS 掉坑。原因:RDB 的save触发或 AOF 重写触发 fork,fork 要复制页表,数据量越大越慢。解决:降低save触发频率,把备份压力转移到从节点;AOF 重写用auto-aof-rewrite-min-size控制最小体积,避免小文件频繁重写;数据量特别大时考虑关掉主节点 RDB,只靠从节点持久化。
现象:AOF 文件涨到几十 G,重启恢复要几十分钟。原因:auto-aof-rewrite-percentage设得太大,或者重写一直失败没告警。解决:把百分比调到 100 甚至更低,配合min-size控制;定期看INFO persistence里的aof_last_bgrewrite_status,失败要查磁盘和权限。
5.2 内存与 key 设计:大 key、热 key 和过期策略
现象:某个HGETALL或SMEMBERS一执行,Redis 就卡住,其他请求超时。原因:大 key,单个 Hash 或 Set 有几十万成员,全量读取阻塞主线程。解决:用HSCAN/SSCAN分批取;拆分大 key,按业务维度打散;上线前用redis-cli --bigkeys扫一遍。
现象:内存用满了,但DBSIZE不大,key 也没多少。原因:大量 key 没设过期,或者过期策略没配好,内存碎片率高。解决:缓存 key 一律带EXPIRE;maxmemory-policy按场景选,缓存用allkeys-lru,持久数据用noeviction并告警;定期看INFO memory里的mem_fragmentation_ratio。
5.3 主从与读写分离:数据不一致和故障切换的窗口
现象:刚写入的数据,从节点读不到,业务报“数据不存在”。原因:主从复制是异步的,写主读从天然有延迟。解决:对一致性敏感的读走主节点;或者用WAIT命令等指定数量的从节点确认,但会牺牲性能。
现象:主节点宕机,从节点升主,但部分数据丢了。原因:异步复制下,主节点没来得及同步给从节点的写操作会丢。解决:这是异步复制的固有代价,只能通过min-replicas-to-write限制主节点至少有几个从节点才接受写,缩小窗口,不能完全消除。
5.4 命令使用:KEYS、FLUSHALL 和事务误用
现象:线上执行KEYS *后,整个 Redis 卡死几秒。原因:KEYS是 O(N) 且阻塞,数据量大时就是灾难。解决:用SCAN替代;生产环境用rename-command把KEYS、FLUSHALL、FLUSHDB重命名或禁用。
现象:事务里一条命令报错,以为整个事务回滚了,结果其他命令生效了。原因:Redis 事务不回滚,只保证排队执行。解决:别把 Redis 事务当关系库事务;需要原子性的复杂逻辑用 Lua 脚本,脚本里的错误同样不回滚,但至少是整体发送。
5.5 连接与超时:连接池耗尽和 timeout 的坑
现象:业务侧报“连接池拿不到连接”,Redis 侧connected_clients很高但 QPS 不高。原因:客户端连接泄漏,或者timeout设太大导致空闲连接不释放。解决:客户端连接池设上限和空闲回收;服务端timeout设一个合理值(比如 300),让空闲连接被回收;看INFO clients里的blocked_clients,阻塞命令用多了也会占连接。
6. 进阶技巧:用 Lua 脚本和慢查询日志把问题摁在发生前
PPT 里没展开 Lua,但事务和发布订阅的边界讲完后,Lua 是自然要补的一环。Redis 执行 Lua 脚本是原子性的,脚本里的多条命令不会被其他请求打断,这比MULTI/EXEC更接近“原子操作”的语义。常见做法是把“判断+扣减”这类逻辑写成脚本,避免WATCH重试的复杂度。
-- stock_deduct.lua:库存扣减,返回剩余库存,不足返回 -1 -- KEYS[1] = 库存 key -- ARGV[1] = 扣减数量 local stock = tonumber(redis.call('GET', KEYS[1])) if stock == nil then return -1 end local deduct = tonumber(ARGV[1]) if stock < deduct then return -1 end redis.call('DECRBY', KEYS[1], deduct) return stock - deduct# 执行脚本 redis-cli --eval stock_deduct.lua stock:1001 , 1--eval后面跟脚本文件,stock:1001是KEYS,逗号后面的1是ARGV。脚本里所有 key 必须通过KEYS传,不能硬编码,否则集群模式下会报错。脚本执行时间要短,超过lua-time-limit(默认 5 秒)会开始报 BUSY,这时候只能SCRIPT KILL或等它跑完。
慢查询日志是另一个被低估的工具。slowlog-log-slower-than默认 10000 微秒,也就是 10 毫秒,超过就记录。slowlog-max-len控制保留条数。
# 查看慢查询 redis-cli SLOWLOG GET 10 # 重置慢查询日志 redis-cli SLOWLOG RESET # 运行时调整阈值(单位微秒,设 5000 即 5 毫秒) redis-cli CONFIG SET slowlog-log-slower-than 5000慢查询日志只记录命令执行时间,不包括网络传输和排队时间。所以看到慢查询,先看是不是大 key 全量操作,再看是不是KEYS、FLUSHALL这类危险命令。我一般会在新环境上线前把slowlog-log-slower-than调到 5000,跑一周看基线,再决定要不要放宽。
还有一个习惯:任何要上线的 Redis 实例,先跑一遍redis-cli --intrinsic-latency 100看基础延迟,再跑--latency看实时延迟。基线不清楚,后面出问题就没有参照。从那以后我每次接手新实例,都强制走一遍“配置核对 → 慢查询基线 → 大 key 扫描 → 持久化状态确认”这四步,少一步后面都可能翻车。希望帮到你。
本文还有配套的精品资源,点击获取