Redis页面优化

文章目录

    • 1.Redis页面缓存
        • 1.思路分析
        • 2.首先记录一下目前访问商品列表页的QPS
          • 1.线程组配置10000次请求
          • 2.请求配置
          • 3.开始压测
            • 1.压测第一次 平均QPS为612
            • 2.压测第二次 平均QPS为615
            • 3.压测第三次 平均QPS为617
        • 3.然后记录一下访问商品详情页的QPS
          • 1.线程组配置10000次请求
          • 2.请求配置
          • 3.开始压测
            • 1.压测第一次 平均QPS为633
            • 2.压测第二次 平均QPS为642
            • 3.压测第三次 平均QPS为641
        • 4.商品列表页Redis缓存优化
          • 1.GoodsController.java
          • 2.启动报错 Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource
          • 3.发现是produces写错了,将冒号换成分号
          • 4.重新启动测试
            • 1.登录后访问 http://localhost:9092/seckill/goods/toList
            • 2.此时如果在数据库中修改信息,在60s内是不会刷新的
        • 5.商品详情页Redis缓存优化
          • 1.GoodsController.java
          • 2.测试
            • 1.登录后访问详情页
            • 2.在Redis中也有了缓存
        • 6.压力测试
          • 1.清空Redis
          • 2.清空用户表
          • 3.启动应用,重新生成2000个用户
          • 4.对访问列表页进行压测
            • 1.发现平均QPS只有80,比直接走数据库还慢
            • 2.由于六台机器都开启了RDB和AOF的持久化策略,现在分别将其关闭,然后重启redis
            • 3.再次压测,还是80
            • 4.那么就可能是网络原因了,因为服务器都在北京,所以将服务部署到生产环境然后再进行压力测试
    • 2.生产环境的压力测试
        • 1.首先将GoodsController.java的从db查询商品列表打开
        • 2.部署上线
          • 1.激活环境为prod
          • 2.maven打包
          • 3.上传到服务器然后重新启动
        • 3.UserUtil.java 获取用户信息
          • 1.修改环境变量
          • 2.获取cookie
        • 4.准备压测
          • 1.http请求默认值
          • 2.http请求信息
          • 3.修改cookie的域
          • 4.开始压测5000次请求,QPS为55
        • 5.使用redis缓存页面来优化并重新部署
        • 6.再次压测,QPS为80,有所提升
        • 7.关于Redis缓存页面与DB的数据同步问题
    • 3.对象缓存问题解决
        • 1.问题分析
        • 2.具体实现
          • 1.UserService.java
          • 2.UserServiceImpl.java
          • 3.UserController.java
        • 3.测试
          • 1.登录一下,得到票据
          • 2.Redis中有该用户信息
          • 3.更新密码 http://localhost:9092/seckill/user/updatePassword?userTicket=4dfaea799a9b438ea96ef61f7da435e3&password=666666
          • 4.刷新Redis,用户信息被删除

1.Redis页面缓存

1.思路分析

image-20240510103830900

2.首先记录一下目前访问商品列表页的QPS
1.线程组配置10000次请求

image-20240510104150231

2.请求配置

image-20240510104243589

3.开始压测
1.压测第一次 平均QPS为612

image-20240510104745555

2.压测第二次 平均QPS为615

image-20240510104836407

3.压测第三次 平均QPS为617

image-20240510104913070

3.然后记录一下访问商品详情页的QPS
1.线程组配置10000次请求

image-20240510104150231

2.请求配置

image-20240510114304155

3.开始压测
1.压测第一次 平均QPS为633

image-20240510114342610

2.压测第二次 平均QPS为642

image-20240510114510495

3.压测第三次 平均QPS为641

image-20240510114551866

4.商品列表页Redis缓存优化
1.GoodsController.java
    @Resource
    GoodsService goodsService;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private ThymeleafViewResolver thymeleafViewResolver;

    // 进入到商品首页-使用redis优化
    @RequestMapping(value = "/toList", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String toList(Model model, User user, HttpServletRequest request, HttpServletResponse response) {
        // 判断是否有用户信息
        if (null == user) {
            return "login";
        }
        // 先从redis中获取页面,如果有则直接返回
        String html = (String) redisTemplate.opsForValue().get("goodsList");
        if (StringUtils.hasText(html)) {
            return html;
        }
        // 如果没有就从数据库中查询,然后存入redis中

        // ------------------------------db查询商品列表------------------------------
        // 查询商品列表
        model.addAttribute("goodsList", goodsService.findGoodsVo());
        // 将用户信息存入model中
        model.addAttribute("user", user);
        // ------------------------------db查询商品列表------------------------------

        // 渲染页面
        // 1.首先构建一个webContext对象,用来存放model
        WebContext context = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());
        // 2.渲染页面
        html = thymeleafViewResolver.getTemplateEngine().process("goodsList", context);
        // 3.判断html是否为空,不为空则存入redis中,设置过期时间为60s
        if (StringUtils.hasText(html)) {
            redisTemplate.opsForValue().set("goodsList", html, 180, TimeUnit.SECONDS);
        }
        return html;
    }
2.启动报错 Error creating bean with name ‘requestMappingHandlerMapping’ defined in class path resource

image-20240510112622807

3.发现是produces写错了,将冒号换成分号

image-20240510112644275

4.重新启动测试
1.登录后访问 http://localhost:9092/seckill/goods/toList

image-20240510113319062

2.此时如果在数据库中修改信息,在60s内是不会刷新的

image-20240510113453521

image-20240510113501947

5.商品详情页Redis缓存优化
1.GoodsController.java
    // 进入到商品详情页
    @RequestMapping(value = "/toDetail/{goodsId}", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String toDetail(Model model, User user, @PathVariable Long goodsId, HttpServletRequest request, HttpServletResponse response) {
        // 判断是否有用户信息
        if (null == user) {
            return "login";
        }
        // 先从redis中获取页面,如果有则直接返回
        String html = (String) redisTemplate.opsForValue().get("goodsDetail:" + goodsId);
        // 如果有则直接返回
        if (StringUtils.hasText(html)) {
            return html;
        }
        // 如果没有就从数据库中查询,然后存入redis中
        // ------------------------------db查询商品详情------------------------------
        // 查询商品详情
        GoodsVo goodsVoByGoodsId = goodsService.findGoodsVoByGoodsId(goodsId);
        model.addAttribute("goods", goodsVoByGoodsId);

        // secKillStatus:秒杀状态 0:未开始 1:进行中 2:已结束
        // remainSeconds:秒杀剩余时间 >0:未开始 0:进行中 -1:已结束
        // 获取该商品的秒杀开始时间和结束时间
        long startAt = goodsVoByGoodsId.getStartDate().getTime();
        long endAt = goodsVoByGoodsId.getEndDate().getTime();
        long now = System.currentTimeMillis();

        // 根据当前时间与秒杀开始时间和结束时间的比较,判断秒杀状态
        int secKillStatus = 0;
        int remainSeconds = 0;
        if (now < startAt) {
            // 秒杀未开始
            secKillStatus = 0;
            remainSeconds = (int) ((startAt - now) / 1000);
        } else if (now > endAt) {
            // 秒杀已结束
            secKillStatus = 2;
            remainSeconds = -1;
        } else {
            // 秒杀进行中
            secKillStatus = 1;
            remainSeconds = 0;
        }
        // 将秒杀状态和剩余时间存入model中,返回到前端
        model.addAttribute("secKillStatus", secKillStatus);
        model.addAttribute("remainSeconds", remainSeconds);
        // 将用户信息存入model中,返回到前端
        model.addAttribute("user", user);
        // ------------------------------db查询商品详情------------------------------

        // 渲染页面
        // 1.首先构建一个webContext对象,用来存放model
        WebContext context = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());
        // 2.渲染页面
        html = thymeleafViewResolver.getTemplateEngine().process("goodsDetail", context);
        // 3.判断html是否为空,不为空则存入redis中,设置过期时间为60s
        if (StringUtils.hasText(html)) {
            redisTemplate.opsForValue().set("goodsDetail:" + goodsId, html, 180, TimeUnit.SECONDS);
        }
        return html;
    }
2.测试
1.登录后访问详情页

image-20240510115537167

2.在Redis中也有了缓存

image-20240510115506347

6.压力测试
1.清空Redis

image-20240510131337298

2.清空用户表

image-20240510131408927

3.启动应用,重新生成2000个用户

image-20240510131906293

4.对访问列表页进行压测
1.发现平均QPS只有80,比直接走数据库还慢

image-20240510133226209

2.由于六台机器都开启了RDB和AOF的持久化策略,现在分别将其关闭,然后重启redis

image-20240510134438566

3.再次压测,还是80

image-20240510135137575

4.那么就可能是网络原因了,因为服务器都在北京,所以将服务部署到生产环境然后再进行压力测试

2.生产环境的压力测试

1.首先将GoodsController.java的从db查询商品列表打开

image-20240510140806413

2.部署上线
1.激活环境为prod

image-20240510141002410

2.maven打包

image-20240510141329259

3.上传到服务器然后重新启动

image-20240510141219305

image-20240510141322995

3.UserUtil.java 获取用户信息
1.修改环境变量

image-20240510141454701

2.获取cookie

image-20240510141645300

4.准备压测
1.http请求默认值

image-20240510141746474

2.http请求信息

image-20240510141913477

3.修改cookie的域

image-20240510142730644

4.开始压测5000次请求,QPS为55

image-20240510144422400

5.使用redis缓存页面来优化并重新部署

image-20240510144638573

6.再次压测,QPS为80,有所提升

image-20240510145440390

7.关于Redis缓存页面与DB的数据同步问题

image-20240510150344168

3.对象缓存问题解决

1.问题分析

在校验用户是否登录时,会根据cookie在Redis中查询用户信息,但是如果在DB中的用户信息更改了,那么就会发生数据不一致的问题

2.具体实现
1.UserService.java
    /**
     * 更新密码
     * @param userTicket
     * @param password
     * @param request
     * @param response
     * @return
     */
    public RespBean updatePassword(String userTicket, String password, HttpServletRequest request, HttpServletResponse response);
2.UserServiceImpl.java
    @Override
    public RespBean updatePassword(String userTicket, String password, HttpServletRequest request, HttpServletResponse response) {
        // 根据ticket获取用户
        User user = getUserByCookie(userTicket, request, response);
        if (null == user) {
            throw new GlobalException(RespBeanEnum.MOBILE_NOT_EXIST);
        }
        // 更新密码
        user.setPassword(MD5Util.inputPassToDBPass(password, user.getSlat()));
        int result = userMapper.updateById(user);
        if (1 == result) {
            // 删除redis中的用户信息
            redisTemplate.delete("user:" + userTicket);
            return RespBean.success();
        }
        return RespBean.error(RespBeanEnum.PASSWORD_UPDATE_FAIL);
    }
3.UserController.java
    // 更新密码
    @RequestMapping("/updatePassword")
    @ResponseBody
    public RespBean updatePassword(String userTicket, String password, HttpServletRequest request, HttpServletResponse response) {
        return userService.updatePassword(userTicket, password, request, response);
    }
3.测试
1.登录一下,得到票据

image-20240510154410627

2.Redis中有该用户信息

image-20240510154635876

3.更新密码 http://localhost:9092/seckill/user/updatePassword?userTicket=4dfaea799a9b438ea96ef61f7da435e3&password=666666

image-20240510154823197

4.刷新Redis,用户信息被删除

image-20240510154850757

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/679048.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据泄露怎么防?企业文件加密来帮忙

在数字化时代&#xff0c;数据泄露事件频发&#xff0c;给企业带来了前所未有的安全挑战。企业的核心数据、商业机密、客户信息等一旦泄露&#xff0c;不仅会导致经济损失&#xff0c;还会损害企业的声誉和客户信任。因此&#xff0c;如何有效防止数据泄露&#xff0c;成为了企…

如何利用Varjo混合现实技术改变飞机维修训练方式

自2017年以来&#xff0c;总部位于休斯顿的HTX实验室一直在推进混合现实技术&#xff0c;与美国空军密切合作&#xff0c;通过其EMPACT平台提供可扩展的沉浸式飞机维护虚拟现实培训。 虚拟和混合现实对维修训练的好处&#xff1a; l 实践技能&#xff1a;提供一个非常接近真实场…

ECharts 图形化看板 模板(简单实用)

目录 一、官网 二、模板 ①定义请求​编辑 ② 将请求统一管理&#xff0c;别的页面引用多个请求时更便于导入。​编辑 ③最终模板 三、执行效果 四、后端代码 4.1 controller 4.2 xml 4.3 测试接口 一、官网 获取 ECharts - 入门篇 - 使用手册 - Apache ECharts 二、…

视频号上怎么卖货?需要直播,还有粉丝吗?一篇文章带你了解!

大家好&#xff0c;我是电商糖果 关于在视频号上卖货&#xff0c;这是大家最常提起的话题。 大家之所以对视频号卖货感兴趣&#xff0c;主要原因还是抖音卖货火起来了。 而视频号是和抖音处于同一个赛道&#xff0c;这两年也在往电商方向发力。 所以大家对视频号推出电商平…

四川景源畅信:抖音做直播有哪些人气品类?

随着互联网科技的飞速发展&#xff0c;抖音作为新兴的社交媒体平台&#xff0c;已经成为了人们日常生活中不可或缺的一部分。而在抖音平台上&#xff0c;直播功能更是吸引了大量的用户和观众。那么&#xff0c;在抖音上做直播有哪些人气品类呢?接下来&#xff0c;就让我们一起…

会计电子档案系统方案

会计电子档案系统方案是指建立一个以电子方式存储和管理会计档案的系统。该方案具体包括以下几个方面&#xff1a; 1. 系统架构设计&#xff1a;确定系统的组成以及各个组件之间的关联和交互方式。包括数据库设计、系统服务器和客户端的部署等。 2. 电子档案管理&#xff1a;建…

网工内推 | 上市公司网工,Base广东,思科DE/IE认证优先

01 广州赛意信息科技股份有限公司 &#x1f537;招聘岗位&#xff1a;技术架构师 &#x1f537;职责描述&#xff1a; 1、设计、开发和维护工业数据库及其架构&#xff0c;包括数据采集、存储、处理和分析的工具和系统。 2、开发和维护数据管道和工作流程&#xff0c;确保数据…

麒麟系统 安装xrdp 远程桌面方法记录

一、安装环境 麒麟V10 2107 ft2000 麒麟V10 2107 x86_64 二、安装准备 使用《Kylin-Desktop-V10-Release-2107-arm64.iso》镜像 做好U盘启动系统后&#xff0c;需要安装一个远程桌面工具&#xff0c;可以多用户在windows上使用远程桌面访问麒麟系统。 目前在linux系统上较…

RS485 数据不通 debug 调试记录

最近调试一颗 TI 的rs485 收发器芯片 &#xff1a;SN65HVD72DR &#xff0c;遇到到点麻烦&#xff0c;既不能收&#xff0c;也不能发送。 先上图 &#xff1a; PINTYPEDESCRIPTIONNAMENUMBERA6Bus I/ODriver output or receiver input (complementary to B)B7Bus I/ODriver out…

AMD硬刚英伟达Nvidia、英特尔Intel

AMD在2024年台北Computex展会上&#xff0c;由公司董事长兼CEO苏姿丰博士发布了最新AI芯片MI325X&#xff0c;并宣称该芯片相比于NVIDIA的H200&#xff0c;在计算速度上快30%。此番发布突显了AMD在AI加速器领域对NVIDIA的强劲挑战姿态&#xff0c;并规划了每年更新一代AI芯片的…

GNU Radio实现OFDM Radar

文章目录 前言一、GNU Radio Radar Toolbox编译及安装二、ofdm radar 原理讲解三、GNU Radio 实现 OFDM Radar1、官方提供的 grc①、grc 图②、运行结果 2、修改后的便于后续可实现探测和通信的 grc①、grc 图②、运行结果 四、资源自取 前言 本文使用 GNU Radio 搭建 OFDM Ra…

Day09 系统设置模块设计

​ 当前章节完成后的效果图 一.系统设置模块设计 系统设置,分别3个功能点,个性化(用于更改主题颜色),系统设置,关于更多 其中个性化的颜色内容样式,主要是从 Material Design Themes UI 简称 md、提供的demo里复制代码过来使用的。 接下来,对设置模块里面左侧导航栏(个性…

lua vm 三: 栈与函数调用

lua vm 运行过程中&#xff0c;栈是一个重要的数据结构。 栈是一个很巧妙的设计&#xff0c;它同时能满足 lua、c 函数运行的需要&#xff0c;也能实现 lua 与 c 函数的互相调用。 1. 栈 1.1 栈的数据结构 一个操作系统线程中&#xff0c;可以运行多个 lua vm&#xff0c;lua…

异常概述

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在程序运行过程中&#xff0c;经常会遇到各种各样的错误&#xff0c;这些错误统称为“异常”。这些异常有的是由于开发者将关键字敲错导致的&#xf…

《QT从基础到进阶·四十二》QT运行后项目图标,exe图标问题,VS加载.pro文件问题

1、QT图标有时候不能正常显示&#xff0c;不管是加到qrc还是用绝对路径&#xff0c;都无法正常显示&#xff0c;之前是可以的&#xff0c;具体原因目前还不太清楚&#xff0c;我在VS项目——vcpkg——use vcpkg把否改为是就可以了 2、出现无法定位程序输入点的报错&#xff0c…

408数据结构-图的存储与基本操作 自学知识点整理

前置知识&#xff1a;图的基本概念 图的存储必须完整、准确地反映顶点集和边集的信息。根据不同图的结构和算法&#xff0c;采用不同的存储方式将对程序的效率产生相当大的影响&#xff0c;因此选取的存储结构应适合于待求解的问题。 图的存储 邻接矩阵法 所谓邻接矩阵存储&a…

CSS(盒子模型,定位,浮动,扩展)

CSS 盒子模型&#xff1a;外边距&#xff1a;内边距&#xff1a;水平居中&#xff1a; 定位&#xff1a;相对定位&#xff1a;绝对定位&#xff1a;固定定位&#xff1a; 浮动&#xff1a;扩展&#xff1a; 盒子模型&#xff1a; 盒子模型(Box Model) 规定了元素框处理元素内容…

免费,Scratch蓝桥杯比赛历年真题--第15届蓝桥杯STEMA真题-2024年3月份(含答案解析和代码)

第15届蓝桥杯STEMA真题-2024年3月份 一、单选题 答案&#xff1a;D 解析&#xff1a;y坐标正值表示上&#xff0c;负值表示下&#xff0c;故答案为D。 答案&#xff1a;C 解析&#xff1a;18<25为真&#xff0c;或关系表示一真即为真&#xff0c;故答案为C。 答案&#xff…

【Linux】常用基本指令汇总

前言&#xff1a; 本章将介绍Linux操作系统常用的基本指令&#xff0c;另外&#xff0c;使用这些指令编辑一个shell脚本&#xff0c;方便大家理解使用。 目录 常用指令whoamipwdls关于iNode的解释验证标识文件的方式 cdtouchmkdir&#xff08;重要&#xff09;treemdir指令 &a…

radsystems教程的基本使用之时间字段范围检索

前言&#xff1a; 根据之前的文章&#xff0c;我相信大部分人都能够做到&#xff0c;页面的数据展示&#xff0c;基本的查询功能。我们知道的是这个数值范围检索是非常容易实现的&#xff0c;但是这个时间字段范围检索并不是很如愿。 细心的朋友会发现每次用Date Fied这个组件…