Redis是一个开源的基于内存的键值数据库,因为读写速度极快、支持多种数据结构而被广泛使用。它诞生于意大利工程师 Salvatore Sanfilippo 之手,最初是为了解决高并发场景下的数据访问瓶颈。如今,Redis已经成为后端系统里缓存、计数器、排行榜、消息队列等场景的标配组件。这篇文章会把Redis入门必须掌握的知识点系统梳理一遍,并把常见的疑问集中解答,帮助你快速建立完整的知识体系。

一、Redis是什么,为什么要用它
要理解Redis的定位,可以先从传统关系型数据库的瓶颈说起。MySQL这类数据库把数据存在磁盘上,每次查询都要经历磁盘IO,在高并发场景下响应速度就成了瓶颈。而Redis把数据放在内存中,内存的读写速度比磁盘快几个数量级,单机环境下Redis每秒可以处理十万次级别的读写请求。
Redis不仅仅是一个简单的缓存。它支持字符串、哈希、列表、集合、有序集合五种基本数据类型,还支持发布订阅、Lua脚本、事务、流水线等高级特性。基于这些能力,Redis可以胜任缓存、分布式锁、排行榜、点赞计数、消息队列等多种业务场景。
安装Redis也非常简单,以Linux为例,下载源码后执行编译即可:
# 下载并编译安装 wget https://download.redis.io/releases/redis-7.2.tar.gz tar xzf redis-7.2.tar.gz cd redis-7.2 make # 启动服务 src/redis-server # 另开终端连接客户端 src/redis-cli 127.0.0.1:6379> ping PONG
看到返回PONG就说明Redis服务已经正常运行了。安装完成后就可以开始学习基本命令了。
二、五种基本数据类型及使用场景
Redis的核心设计就是围绕数据结构展开的,不同的数据类型对应不同的底层实现和适用场景,选对类型是用好Redis的第一步。
第一种是字符串String,这是最简单的类型,可以存字符串、整数甚至二进制数据。常用于缓存序列化后的JSON对象、计数器、分布式锁等。常用的命令有SET、GET、INCR、DECR。其中INCR是原子操作,多个客户端并发执行也不会出现计数错乱,因此非常适合做限流计数、商品库存扣减。
第二种是哈希Hash,相当于一个键下面存了一张小地图,适合存储对象。比如存储用户信息时,可以用HSET user:1001 name zhangsan age 25,这样修改单个字段时不需要把整个对象读出来再写回去,节省了网络开销和序列化成本。
第三种是列表List,是一个双向链表结构,支持从两端插入和弹出元素,可以用来做简单的消息队列、最新消息列表。使用LPUSH配合BRPOP可以实现阻塞式消费。
第四种是集合Set,存储不重复的元素,支持交集、并集、差集运算。典型场景是共同好友、标签去重、抽奖去重。例如用SINTER求两个用户兴趣标签的交集就可以做推荐。
第五种是有序集合ZSet,每个元素带一个分数,按分数排序。这是做排行榜的最佳选择,ZADD rank 100 player1加入成员,ZREVRANGE rank 0 9就能直接取出分数前十名,非常方便。
SET token:abc123 "user_session" EX 3600 # 存字符串并设置3600秒过期 INCR article:8001:views # 文章阅读量自增 HSET user:1001 name zhangsan age 25 # 存储用户对象的字段 LPUSH msg:queue "order_created" # 队列入队 BRPOP msg:queue 0 # 阻塞式出队 SADD tags:1001 "java" "redis" # 添加标签 ZADD rank 100 player1 # 排行榜加入成员 ZREVRANGE rank 0 2 WITHSCORES # 取前三名及分数
三、持久化机制:RDB与AOF怎么选
虽然Redis是内存数据库,但它支持把数据持久化到磁盘,防止重启后数据丢失。持久化有两种方式,理解它们的原理对生产环境配置非常重要。
RDB是快照方式,Redis会在指定的时间间隔内把内存中的全部数据生成一份快照文件dump.rdb。它的优点是文件紧凑、恢复速度快,缺点是两次快照之间的数据如果宕机就会丢失。可以通过save 900 1这样的配置项指定触发条件,也可以手动执行BGSAVE命令在后台生成快照,不影响主线程服务。
AOF是追加日志方式,把每一条写命令追加到日志文件末尾,重启时通过重放日志恢复数据。AOF有三个同步策略:appendfsync always是每条命令都刷盘,最安全但性能最差;appendfsync everysec是每秒刷盘一次,是性能和安全性的折中,也是推荐配置;appendfsync no是交给操作系统决定,性能最好但可能丢失较多数据。AOF文件会越来越大,Redis提供了AOF重写机制,把日志压缩成恢复当前数据所需的最小命令集合。
实际生产中通常两种方式同时开启,用AOF保证数据尽量不丢,用RDB做定期备份。如果只做纯缓存、数据丢了可以从数据库重建,那么甚至可以关闭持久化换取更高的性能。
四、过期删除与内存淘汰策略
给key设置过期时间用EXPIRE命令或在SET时加EX参数。但很多人不清楚Redis是怎么删除过期key的。Redis采用惰性删除加定期删除的组合策略:惰性删除是指访问某个key时才检查它是否过期,过期则删除;定期删除是Redis每隔一段时间随机抽取一批设置了过期时间的key检查,清理其中已过期的。这个组合在性能和内存占用之间取得了平衡。
当内存达到maxmemory上限时,就会触发内存淘汰。Redis提供了八种淘汰策略,常用的有:noeviction默认策略,内存满后写入报错;allkeys-lru对所有key按最近最少使用淘汰,适合做缓存;volatile-lru只对设置了过期时间的key做LRU淘汰;还有allkeys-lfu按访问频率淘汰,适合热点数据明显的场景。如果Redis单纯用作缓存,推荐配置allkeys-lru或allkeys-lfu。
五、缓存三大经典问题及应对方案
使用Redis做缓存层时,有三个绕不开的经典问题,面试和实战中都很常见。
第一个是缓存穿透,指查询一个数据库中根本不存在的数据,请求绕过缓存直接打到数据库,恶意攻击时危害极大。解决方案有两种:一是缓存空值,查不到就往Redis写一个空标记并设置较短的过期时间;二是使用布隆过滤器,在缓存之前加一层判断,不存在的数据直接拦截。
第二个是缓存击穿,指某个热点key过期的瞬间,大量并发请求同时打到数据库。解决方案是使用互斥锁,只允许一个线程去数据库查询并回写缓存,其他线程等待;或者对热点数据设置永不过期,由后台异步更新。
第三个是缓存雪崩,指大量key在同一时间集中过期,或者Redis服务整体宕机,导致数据库瞬间承受巨大压力。应对办法是把过期时间加上随机值打散过期时间点,搭建Redis集群保证高可用,并且在应用层做限流降级保护数据库。
六、新手常见问题与避坑指南
第一个常见问题是键的设计不规范。建议使用冒号分隔的命名规范,例如user:1001:profile,这样语义清晰也便于按前缀批量管理。
第二个是大key问题。如果一个String类型的value达到几MB,或者一个集合元素达到几十万,操作时会阻塞Redis单线程,造成其他请求排队。要避免把大对象整个塞进Redis,大列表应该拆分成多个小key分批处理。
第三个是误以为Redis事务和MySQL事务一样。Redis的MULTI和EXEC只保证命令顺序执行,不具备回滚能力,命令出错时其他命令依然会继续执行。如果需要原子操作,优先使用Lua脚本。
第四个是单线程理解误区。Redis的核心命令执行是单线程的,因此单个命令必须快,但网络IO在较新版本中已经由IO多线程处理。这也解释了为什么要避免KEYS *这类阻塞命令在生产环境使用,需要模糊查询时应该改用SCAN游标遍历。
掌握以上这些内容,Redis的基础就打得比较扎实了。建议在学习过程中多动手敲命令,用redis-cli实际操作每一种数据类型,再结合自己项目中的缓存场景去思考方案选型,理解会比单纯看文章深刻得多。