缓存策略如何成为抵抗超高并发的开源武器?

摘要:大家好,我是冰河~~ 最近,有小伙伴私信我:冰哥,我最近出去面试,面试官问我如何设计缓存能让系统在百万级别流量下仍能平稳运行,我当时没回答上来。接着,面试官问我之前的项目是怎么使用缓存的,我说只是缓存了一些数据。当时确实想不到缓存还有哪些用
大家好,我是冰河~~ 最近,有小伙伴私信我:冰哥,我最近出去面试,面试官问我如何设计缓存能让系统在百万级别流量下仍能平稳运行,我当时没回答上来。接着,面试官问我之前的项目是怎么使用缓存的,我说只是缓存了一些数据。当时确实想不到缓存还有哪些用处,估计这次面试是挂了。冰哥,你可以给我讲讲互联网大厂项目是怎么设计和使用缓存的吗? 另外,本文缓存方案已经开源,开源地址如下,如果开源方案对你有点帮助或者启发,欢迎在代码仓库给个Star,让更过的小伙伴看到它,互相学习,一起进步。 GitHub:https://github.com/binghe001/spring-redis Gitee:https://gitee.com/binghe001/spring-redis GitCode:https://gitcode.net/binghe001/spring-redis 一、前言 通过这位小伙伴的自述,我们明显感受到这位小伙伴对缓存的认识还是停留在简单的存储数据上,没有对使用缓存背后的场景和实现逻辑进行深层次的思考。在互联网大厂项目中,缓存也是一种必不可少的组件,那使用缓存仅仅是为了缓存热点数据,提升读性能吗?如果你对缓存的认识只是停留在这里,那就未免太浅显了。 今天,我们就以高并发、大流量业务场景中最具代表性的 秒杀系统 为例,采用市面上大家都比较熟悉的技术,一起探究下 秒杀系统 背后是如何设计和使用缓存的。 二、秒杀系统缓存核心诉求 秒杀系统在承接瞬时高并发流量时,如果将流量直接打到数据库,那数据库很有可能因为扛不住瞬间的高并发流量而导致崩溃和宕机。所以,需要对秒杀系统进行极致的缓存设计,让大部分流量走缓存。同时,在设计缓存架构方案时,为了进一步提升性能,将采用 本地缓存+分布式缓存的混合型缓存 设计方案,让本地缓存抗大部分流量,分布式缓存次之,数据库再次之,如图1所示 并且针对秒杀系统这种瞬时并发量高的场景,在设计缓存时,需要注意的技巧:优先读取本地缓存数据,如果本地缓存失效,则读取分布式缓存数据,并且在同一时刻,只能有一个线程更新本地缓存,防止缓存击穿。没有获取到本地缓存更新机会的其他线程,需要立即返回而不是原地等待。如果分布式缓存失效时,在同一时刻,也只能有一个线程更新分布式缓存,防止缓存击穿。没有获取到分布式缓存更新机会的线程,也需要立即返回而不是原地等待。 另外,需要注意的是:我们提出了采用 本地缓存+分布式缓存的混合型缓存设计方案,后文会着重对这种设计进行说明。 三、秒杀系统缓存使用场景 秒杀系统属于典型的读多写少的高并发系统,应对这种场景的一个有效措施就是使用缓存,不管是单机JVM缓存还是以Redis为例的分布式缓存,其读写性能都会比数据库高得多。所以,在秒杀系统中,为了应对高并发、大流量的业务场景,缓存自然也就成为建设秒杀系统过程中必不可少的环节。 3.1 秒杀系统接口分析 在秒杀系统中,主要是对一些读数据的接口设计缓存策略,而在这些读数据的接口中,获取秒杀活动列表、获取秒杀活动详情、获取秒杀商品列表和获取秒杀商品详情的接口流量比其他接口高。尤其是获取秒杀商品列表和获取秒杀商品详情的接口QPS一般会高于获取秒杀活动列表和秒杀活动详情的接口,毕竟大部分用户在秒杀开始前就已经进入到秒杀详情页,当然这也不是绝对的,还是要看秒杀系统对于这些接口的设计。 3.2 秒杀系统缓存场景 尽管获取秒杀商品列表和获取秒杀商品详情的接口QPS一般会高于获取秒杀活动列表和秒杀活动详情的接口,但是我们在设计缓存时,需要对这些接口一视同仁,都要以严格的高标准来设计这些接口,不然稍有不慎,一个接口出现问题,就可能导致整场秒杀活动以失败告终。秒杀系统缓存的使用场景如图2所示。 所以,在秒杀系统中,会对获取秒杀活动列表、获取秒杀活动详情、获取秒杀商品列表和获取秒杀商品详情的接口设计缓存策略。 四、混合型缓存设计 总体来说,在设计秒杀系统的缓存过程中,会采用 本地缓存+分布式缓存的混合型缓存 设计方案。其中,本地缓存指的就是单机缓存,比如JVM内存缓存,单机Cache缓存。分布式缓存指的是以分布式的方式集中管理的缓存,比如Memcached、Redis等,如图3所示。 4.1 抗流量洪峰 良好的缓存设计不仅仅能够提升系统的总体性能,还能作为抗瞬时流量洪峰的有效防线。可以这么说,如果整个秒杀系统前置的流量管控、流量清洗和限流等是秒杀系统流量洪峰的第一道防线,则本地缓存就是抗流量洪峰的第二道防线,而分布式缓存就是第三道防线,如图4所示。 使用缓存能够抗一定的流量洪峰,经过前置的流量管控、流量清洗和限流等措施的第一道防线、本地缓存的第二道防线、分布式缓存的第三道防线,真正进入数据库的流量就会比较小了。
阅读全文