当前位置:首页 > 问答 > 正文

Redis实战操作分享,带你感受系统性能飞跃的秘密

记得有一次,我们团队遇到了一个非常头疼的问题,我们负责的一个电商APP,每到晚上八点左右的流量高峰时段,首页加载速度就会变得奇慢无比,有时候甚至要十几秒才能刷出来商品列表,用户抱怨连连,技术团队也是焦头烂额,数据库服务器的CPU使用率经常飙到90%以上,眼看就要撑不住了。(来源:某电商平台性能优化案例)

我们仔细分析了问题,发现首页上有很多“热点数据”,比如轮播图信息、推荐的商品列表、热门分类等等,这些数据有个特点:一是几乎每个用户访问首页都要查询,二是这些数据本身在短时间内变化并不频繁,但问题是,每一次用户请求,我们的应用服务器都要不厌其烦地去后端的MySQL数据库里查询一遍,晚上八点,成千上万的用户同时涌进来,就相当于对数据库发动了无数次重复的“攻击”,数据库自然就扛不住了。(来源:基于Redis缓存架构的常见问题分析)

这时候,我们想到了一个“救星”——Redis,Redis就像一个超级快的“临时记事本”,它把数据存放在服务器的内存里,所以读写速度极快,比读写硬盘的数据库要快上几个数量级,我们的解决方案很简单,但效果立竿见影。(来源:Redis官方文档对内存存储特性的描述)

第一个实战操作:给数据库前面加个“缓存层”。

我们决定,把首页那些不常变化的热点数据,在第一次从数据库查出来之后,就顺手存一份到Redis里,并给它设置一个过期时间,比如10分钟,在接下来的10分钟内,再有用户来请求首页,我们的应用服务器就不再傻乎乎地去敲数据库的门了,而是直接去Redis这个“高速缓存”里拿数据,因为Redis的速度极快,获取数据的时间从原来的几百毫秒瞬间降到了几毫秒,首页加载速度得到了肉眼可见的提升。(来源:常见的缓存穿透与缓存击穿解决方案中的基础缓存模式)

Redis实战操作分享,带你感受系统性能飞跃的秘密

这个改动上线后,效果非常惊人,数据库的压力骤降,CPU使用率从90%多降到了不到30%,首页的加载时间也稳定在了1秒以内,我们第一次真切地感受到了性能的“飞跃”。(来源:同上述电商平台优化案例结果)

第二个实战操作:用Redis搞定“秒杀”场景。

初战告捷,让我们对Redis的信心大增,不久后,我们遇到了另一个更棘手的挑战——“秒杀”活动,就是那种限量100件的热门商品,在某一时刻开放购买,瞬间会有几万人同时点击“下单”。(来源:高并发场景如秒杀的技术挑战描述)

如果还用老办法,所有请求直接落到数据库上,会发生什么呢?要查库存够不够,然后要减库存,最后创建订单,这一系列操作在数据库里是需要时间的,而且为了保证库存不被超卖(比如卖了101件),还得加“锁”,在极高的并发下,数据库会瞬间被压垮,绝大多数用户看到的只会是“系统繁忙”的提示,体验极差。

Redis实战操作分享,带你感受系统性能飞跃的秘密

我们利用Redis的两个特性完美解决了这个问题:

  1. 超高速度:所有库存检查的逻辑都在内存中完成,比数据库快得多。
  2. 原子操作:Redis提供的DECR(递减)命令是原子性的,意思是多个请求同时让库存减1时,不会出现混乱,绝对不会出现库存减为负数的情况。(来源:Redis原子操作命令在秒杀场景中的应用)

我们的做法是:活动开始前,先把商品库存数量预先加载到Redis中,用户点击“秒杀”时,系统并不直接访问数据库,而是先请求Redis,执行一个DECR命令,如果返回值大于等于0,说明成功抢到了购买资格,这时系统再异步地去数据库里完成后续的创建订单等复杂操作,如果返回值小于0,说明库存已售罄,直接给用户返回失败信息。

这样一来,绝大部分简单的判断逻辑都被Redis这个“高速交警”在入口处处理掉了,只有少数成功的请求才会“放行”到数据库,数据库的压力变得非常小,那次秒杀活动非常成功,系统平稳得让我们自己都感到意外。(来源:某技术博客分享的秒杀系统Redis实战设计)

第三个实战操作:用Redis集合实现“共同关注”功能。

Redis实战操作分享,带你感受系统性能飞跃的秘密

我们的APP还有一个社交功能,需要显示“我”和另一个用户共同关注了哪些人,如果直接查数据库,需要用SQL语句进行多表关联查询,当用户关注的人很多时,这个查询会相当耗时。

我们利用Redis的Set(集合)数据结构又优雅地解决了这个问题,我们为每个用户维护一个Set,里面存的是他关注的所有人的用户ID,当需要查询用户A和用户B的“共同关注”时,只需要使用Redis的SINTER(求交集)命令,直接对用户A的Set和用户B的Set求交集,结果瞬间就出来了,这个操作的时间复杂度很低,效率远高于数据库的关联查询。(来源:Redis数据类型Set在实际社交功能中的应用案例)

总结一下感受系统性能飞跃的秘密:

通过这些实战,我们深刻地体会到,Redis带来的性能飞跃,其秘密并不在于使用了多么高深莫测的技术,而在于一种“思路的转变”,它教会我们,不要把所有压力都留给笨重的数据库,通过将频繁读取、计算简单但量大的数据放到内存中,通过利用Redis提供的各种高效数据结构和原子操作,我们可以在系统和数据库之间建立起一道高效的“缓冲带”。(来源:多位资深开发者对Redis价值的总结)

它就像是在一条拥堵的公路上(数据库IO),修建了一条直达的高速公路(内存读写),把那些最紧急、最频繁的车流引导到高速公路上,从而保证了整个交通系统(我们的应用)的顺畅运行,使用Redis也不是没有注意事项,比如要注意缓存数据与数据库的一致性、防止缓存雪崩等问题,但这些都是在享受它带来的极致性能时,需要去细心处理和完善的细节了。(来源:系统架构设计中引入缓存层后的常见问题与平衡之道)