Day1.秒杀系统之多级缓存实现

缓存设计

在高并发的情况下,例如秒杀、抢票以及双11活动下单等场景,由于业务量巨大,同一时间打在服务器上的流量过大,就会导致超时响应的情况出现,严重的甚至还会致使服务器崩溃,这是任何一个开发者都不愿意见到的。

因此,在高性能的服务架构设计中,我们常使用缓存这一中间件来分担服务器的压力,最常见的就是使用Redis这一数据库了。不过,随着业务量的增大,仅仅使用Redis这种远程缓存可能还不够,所以这时候就需要在Web应用和Redis之间再增加一个本地缓存。以秒杀系统为例,先不考虑流量削峰及填谷的情况,当我们想要根据商品id查询其详情的时候,请求数据的流程图是下面这样的。

在这里插入图片描述

二级缓存的执行流程?

  • 浏览器发送请求,到达本地缓存,如果本地缓存中有数据,那么直接返回。
  • 如果本地缓存中无数据,请求到达Redis,Redis中若有数据,先将数据存放在本地缓存,然后再返回。
  • 如果Redis中无数据,那么将直接请求MySQL,MySQL将数据先写入二级缓存后,再将其返回给浏览器。

什么是本地缓存?

本地缓存是基于本机环境的缓存,它使用的是JVM内存,常见的实现有GuavaCaffeine,由于JVM内存是高度敏感的,所以我们一般都将那些经常被访问的热点数据存放在本地缓存中。

压力测试

我们可以使用Apache Jmeter工具来进行压力测试,本次测试在我的本机执行,线程组的配置如下,由于我是第一次使用Jmeter,所以参数设置方面还不是很理解,凑活着先用。

控制方法的代码如下所示,可以从缓存中查找商品详情,也可以从MySQL数据库中直接查找商品详情。

    @ResponseBody  
    @RequestMapping(path = "/detail/{id}", method = RequestMethod.GET)  
    public ResponseModel getDetail(@PathVariable("id") String id) {
     
//        Item item = itemService.getDetailInCache(id);  
        Item item = itemService.getDetailByID(id);  
        if (item == null) {
     
            return ResponseModel.createFailure(CommonErrorEnum.STOCK_NOT_EXISTS);  
        }  
        return ResponseModel.createSuccess(item);  
    }

无缓存时

在不使用任何缓存时,所有的流量打到MySQL服务器上,如下图所示,在全部15000次请求中,有386次失败,平均响应时间为744.5ms,TPS为2987.45。

使用Redis

下面我将展示使用Redis缓存时,服务器的性能能提高多少,这时我们查找商品详情先去Redis中找,Service层的代码如下所示,这里我对id做了一个校验,因为数据库中所有的id都是32位的,所以我希望传进来的查询字段也是32位的(其实应该在Controller层就校验的,but whatever)。

@Override
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值