老弟第一次学 Redis,被坑惨了!小白可懂的保姆级 Redis 教程

2025-12-04 0 173

你是小阿巴刚入职的程序员。

这天,产品经理找到你:阿巴阿巴,用户吐槽咱们网站首页加载太慢,快优化

你打开监控一看,好家伙!每秒有上万个用户在访问首页,每次都要查询 MySQL 数据库来获取热门文章。

虽然你运用毕生所学优化了数据库查询,但它还是扛不住这么高的并发。

你急得满头大汗:数据库快撑不住了,怎么办啊?

这时,你的导师 —— 号称 “后端之狗” 的鱼皮路过,淡定地说了 3 个字:Redis(瑞迪斯)。

你一脸懵:Redis?那是啥?

⭐️ 推荐观看本文对应视频:bilibili.com/video/BV1a1…

第一阶段:认识 Redis

鱼皮:Redis 的全称是 Remote Dictionary Server(远程字典服务器),是一个 基于内存的 K/V 存储系统

你:远程?字典?K/V?这些都是什么啊?

鱼皮:你可以把 Redis 当成一个数据库,服务器可以通过网络远程操作它写入和读取数据。K/V 就是 Key-Value 键值对,数据就像字典一样保存。

你可以通过 Key 快速查询到对应的 Value。而且因为数据存在内存中,Redis 的读写速度有时比 MySQL 快 100 倍!

你眼前一亮:那我赶紧装一个试试!

机智如你,直接打开 官网 下载了 Redis 服务器,并且成功安装运行。

但是怎么操作 Redis 呢?

鱼皮:可以使用官方提供的命令行工具 Redis CLI 连接并操作 Redis。

打开终端输入下列命令:

redis-cli -h 127.0.0.1 -p 6379

连上之后,咱们试试最基础的操作,利用 SET 命令保存一个键值对:

SET name \"xiaoaba\"

然后通过键读取到值:

GET name

你刚敲完命令,屏幕立刻返回 \”小阿巴\”。

你大为震惊:秒回!这也太快了!

鱼皮:你刚刚保存的值是 Redis 的 String 字符串 类型,只是最简单的一种。

你:还有其他类型?

鱼皮:当然,Redis 能存的东西可多着呢~ 它有 5 种基本数据结构,适用于不同场景:

1)String 字符串:存简单的值,比如用户名、计数器

SET username:1 \"鱼皮\"
GET username:1

2)Hash 哈希表:存对象,比如用户信息 {name: \"小阿巴\", age: 18}

HSET user:1001 name \"小阿巴\" age 18
HGET user:1001 name

3)List 列表:存有序数据,比如最新的 10 条评论

LPUSH comments \"太棒了!\" \"学到了\"
LRANGE comments 0 -1

4)Set 集合:存不重复的数据,比如点赞用户列表

SADD post:1:likes user1 user2 user3
SMEMBERS post:1:likes

5)SortedSet 有序集合:存需要排序且不重复的数据,比如游戏排行榜

ZADD leaderboard 100 \"玩家A\" 95 \"玩家B\" 90 \"玩家C\"
ZRANGE leaderboard 0 -1 WITHSCORES

你感叹道:这用法也太多了,我要背这些命令吗?

鱼皮:千万别背!用的时候去查 Redis 官方的命令手册 就行。

而且想偷懒的话,推荐你装个 Redis 官方的可视化工具 Redis Insight,能像操作 Excel 一样操作 Redis,数据一目了然。

你:哇,确实方便多了!但是我怎么用 Java 代码操作 Redis 呢?

鱼皮:主流编程语言都有操作 Redis 的客户端 SDK。

对于 Java 开发者,可以选择 Jedis、Lettuce、Spring Data Redis 和 Redisson,它们封装了很多操作 Redis 的方法,几行代码就能搞定。

时间充足的话,建议你看看某马的 Redis 教程来系统学习,我当年也看过,讲的很好,先把基础篇和实战篇看完就够了。

你:得咧,我这就看!

第二阶段:实战应用

半个月后,你已经看了不少教程,准备解决热门文章查询太慢的问题。

你实现了经典的缓存逻辑:第一次查询时,先从 Redis 中查找,如果没有找到,再从 MySQL 数据库中查询,然后将结果存入 Redis 中,并设置过期时间。后续相同的查询就能直接从 Redis 返回结果。

示例代码:

public List<ArticlegetHotArticles() {
   // 1. 先从 Redis 查询
   String cacheKey = \"hot_articles\";
   String cachedData = redisTemplate.opsForValue().get(cacheKey);
   if (cachedData != null) {
       // 缓存命中,直接返回
       return JSON.parseArray(cachedData, Article.class);
  }
   // 2. 缓存未命中,查询数据库
   List<Article> articles = articleMapper.selectHotArticles();
   // 3. 将结果存入 Redis,设置 10 分钟过期
   redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(articles), 10TimeUnit.MINUTES);
   return articles;
}

使用 Redis 后,查询速度从 3 秒缩短到了 0.3 秒,产品经理看你的眼神都变了,你很是得意。

鱼皮:不错,不过 Redis 的作用可不仅仅是缓存,你还能用它继续优化项目么?比如之前用户反馈的登录态失效问题。

你想了想:Redis 的本质是 存储系统,也就是说,可以利用 Redis 来存储多个服务器间需要共享的数据。公司有 2 台服务器,用户第一次登录时,Session 存在服务器 A 本地;刷新页面后,请求被分配到服务器 B,就找不到 Session 了,导致丢失登录态。那我就把需要共享的 Session 数据存到 Redis 中,这样无论请求分配到哪台服务器,都能从 Redis 里拿到 Session。

鱼皮欣慰地点了点头:不错,这就是典型的 分布式 Session 问题。

类似的,分布式锁也可以利用 Redis 实现,让多个服务器都从 Redis 去获取锁资源,谁先拿到锁,谁就能操作,其他人排队等待。

你:确实,那 Redis 还有其他应用场景么?

鱼皮:那可太多了,Redis 除了 5 种基本数据结构外,还提供了很多 “高级” 数据结构,专门解决特定场景的问题。

  • GEO:存地理位置坐标,实现附近的人、附近的餐厅功能
  • Bitmap:用 1 个 bit 表示一个状态,节约内存,实现用户签到、在线状态统计
  • HyperLogLog:适用于大规模统计 UV(独立访客数),虽然存在误差,但内存占用只有 12 KB
  • 布隆过滤器:快速判断数据是否存在,可用来防止无效查询打到数据库
  • Stream:消息队列功能,可以实现异步任务,比如用户下单后异步发送短信通知(但更推荐用专业的消息队列)

鱼皮:对了,还有更高级的玩法,Redis 支持编写 Lua 脚本 保证多个操作的原子性,确保要么全部成功,要么全部失败,避免数据不一致的问题。

你:这些听起来好高级,感觉学不完了……

鱼皮:想什么呢,肯定学不完啊!

Redis 是在持续更新的,去看看 官方文档,你会发现更多数据结构,比如适用于 AI 应用开发的 向量存储。不过别担心,可以等实际开发中遇到对应场景再学。

Redis 是实战型技术,光看不练等于白学,一定要多动手实践。

你:好,那我就先给 公司网站 的更多查询也加上缓存吧~

第三阶段:常见问题和解决方案

一个月后的某天,凌晨 3 点,你被电话吵醒了。

运维小哥急切地说:阿巴阿巴,网站挂了!数据库查询一直超时,你快看看!

你很是疑惑:都用 Redis 缓存了,还能超时?

你赶紧去公司看了下日志,发现原来有恶意用户在疯狂查询一个不存在的文章 ID,每次 Redis 缓存中都查不到,请求就直接打到了 MySQL 数据库上!

鱼皮这时也赶到了公司:这就是经典的 缓存穿透 问题,恶意请求故意查询不存在的数据,绕过缓存,直接攻击数据库。

你汗流浃背了:那怎么办?

鱼皮:最简单的方法是,即使数据库查询结果为空,仍将这个空结果缓存到 Redis 中,并设置一个较短的过期时间。后续相同请求会直接命中缓存的空值,避免访问数据库。

你恍然大悟,赶紧写代码补充了缓存空值的逻辑。

public Article getArticleById(Long id) {
   String cacheKey = \"article:\" + id;
   String cachedData = redisTemplate.opsForValue().get(cacheKey);
   if (cachedData != null) {
       // 如果是空值标识,直接返回 null
       if (\"__NULL__\".equals(cachedData)) {
           return null;
      }
       return JSON.parseObject(cachedData, Article.class);
  }  
   // 查询数据库
   Article article = articleMapper.selectById(id);
   if (article != null) {
       // 存储正常数据,10 分钟过期
       redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(article), 10, TimeUnit.MINUTES);
  } else {
       // 存储空值标识,2 分钟过期
       redisTemplate.opsForValue().set(cacheKey, \"NULL\"2, TimeUnit.MINUTES);
  }  
   return article;
}

鱼皮提醒道:缓存穿透只是其中一个问题,实际项目中还会遇到 缓存击穿缓存雪崩

1)缓存击穿:热门数据突然过期,大量请求同时涌向数据库。可以用互斥锁,让请求排队一个一个来,第一个请求负责查数据库并重建缓存,其他请求等缓存重建完成后再查询。

2)缓存雪崩:大量缓存同时过期,数据库瞬间压力巨大。解决方法是给过期时间加上随机值,避免同时失效。

你感慨道:Redis 的坑还真不少!

鱼皮:这就是为什么要学习 Redis 的最佳实践,比如合理设计缓存键名、设置合适的过期时间、选择正确的数据结构等等。

鱼皮:不过这才刚开始呢,你以后还会遇到缓存和数据库的数据不一致、查询 Redis 阻塞、内存爆满等问题,都是需要学习的,以后我再给你讲吧。

你:那如果 Redis 本身也扛不住高并发怎么办?

鱼皮:那就搭建 多级缓存,比如服务器本地内存缓存 => Redis 分布式缓存 => 数据库,层层过滤。用户请求先查本地缓存,没有再查 Redis,还没有才查数据库。每一层都能拦截一部分请求,大大减少 Redis 的压力。

还有 缓存预热,比如大促活动前,提前把热门商品数据加载到 Redis 中,避免活动开始时大量请求同时打到数据库。

第四阶段:高级特性和生产部署

用了一段时间 Redis 后,你开始有点飘了。

你对着新来的实习生阿坤炫耀:Redis 我闭着眼睛都能写!什么缓存、分布式锁、多级缓存,我都搞定过!

结果第二天,老板黑着脸找到你:昨晚机房断电重启后,很多用户反馈自己的学习进度丢失了,怎么回事?!

你这才意识到问题的严重性:Redis 数据存储在内存,断电不就没了吗?

鱼皮及时出现:看来你对 Redis 的理解还停留在玩具阶段啊,生产环境的 Redis 可不是这么简单!我来问你几个问题。

第一问:怎么防止数据丢失?

你支支吾吾:做…… 做备份?

没想到,旁边的阿坤突然鸡叫起来:可以利用 Redis 提供的 2 种持久化方案!

1)RDB 快照:定期把内存数据完整保存到硬盘,像拍照一样,恢复快但可能丢失最新数据。

2)AOF 日志:把每个写操作都记录下来,像记日记,数据更安全但恢复较慢(需要重新执行所有写操作)。

第二问:Redis 服务器挂了怎么办?

你挠头:重启?

鱼皮摇头:用户等得起吗?

阿坤又鸡叫起来:要部署 主从集群,主节点负责写数据,从节点实时同步主节点的数据。这样即使主节点挂了,从节点立刻顶上,用户毫无感知。

第三问:主节点挂了,谁来决定哪个从节点升级?

你无言以对,但是那阿坤竟从容不迫:用 哨兵机制,哨兵就像监工,可以实时监控 Redis 集群健康状态。发现主节点挂了,自动选择一个从节点升级为新主节点,实现自动故障转移。

第四问:数据量太大,单台 Redis 存不下怎么办?

你眼前一亮,终于等到自己会的问题了,抢答道:删除数据!

阿坤用看流浪狗的眼神看了你一眼,回答道:首先 Redis 自身有多种淘汰策略,会自动删除不常用的数据。

还可以搭建 分片集群,把数据按照某种规则分散到多台 Redis 上,每台只存一部分。Redis 使用 哈希槽 机制来分配数据,既能存储更多数据,又能承受更高并发。

鱼皮拍了拍阿坤的肩膀:小伙子年轻有为啊!

你羞愧地抬不起头:我以为自己已经掌握了 Redis,原来只是学了个皮毛……

鱼皮:这些都是 Redis 在生产环境必须考虑的问题,大厂的 Redis 集群动辄几十上百个节点,就是为了保证 高可用、高性能、高可扩展性。小阿巴,你还要好好跟阿坤学习啊。

第五阶段:深入底层原理

被鱼皮连环拷问后,你主动找到阿坤:我想深入学习 Redis,不能只停留在会用的层面,请问你是怎么学习底层原理的呀?

阿坤有些惊讶:咦?你不背八股文的么?去 面试刷题网站 刷刷题就好了呀!

你震惊了:现在的校招生,竟然恐怖如斯!

鱼皮:阿坤你别逗他了,其实我们可以带着问题学习。比如你知道 Redis 为什么这么快 吗?

你想了想:因为数据存在内存里?

鱼皮:这只是表面原因。深层次的原因有很多:

  1. 高效的数据结构:Redis 底层使用了动态字符串、跳表、压缩列表等经过优化的数据结构
  2. 单线程模型:避免了多线程的上下文切换开销
  3. IO 多路复用:一个线程就能同时处理成千上万个连接
  4. 内存管理:有完善的内存淘汰策略,比如 LRU 算法

你惊讶:单线程还能这么快?

鱼皮:对!这就是 Redis 设计的巧妙之处。从这些问题出发,去阅读相关的文章,或者直接像阿坤说的刷一刷 Redis 面试题,就能快速学会很多核心知识点。

如果想系统学习,可以看看《Redis 设计与实现》这本书,讲得很透彻;甚至可以看看 Redis 的开源代码。

要记住,学习底层原理不是为了炫技,而是为了更好地使用 Redis,遇到问题时能够快速定位和解决。

你:好的,我这就去学!

结尾

若干年后,你已经成为了公司的 Redis 专家。

不仅能熟练使用 Redis 解决各种业务问题,搭个 Redis 集群架构也是手拿把掐的。

你也像鱼皮当时一样,耐心地给新人分享学习 Redis 的经验,让他们谨记鱼皮的教诲 “Redis 是实战型技术,一定要多动手实践”。

再次遇到鱼皮是在一条昏暗的小巷,此时的他年过 35,灰头土脸。你什么都没说,只是给他点了个赞,投了 2 个币,不打扰,是你的温柔。

更多

编程学习交流:编程导航 简历快速制作:老鱼简历 ️ 面试刷题神器:面试鸭

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 开发教程 老弟第一次学 Redis,被坑惨了!小白可懂的保姆级 Redis 教程 https://www.zuozi.net/3306.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务