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
    @ResourceGoodsService goodsService;@Resourceprivate RedisTemplate redisTemplate;@Resourceprivate ThymeleafViewResolver thymeleafViewResolver;// 进入到商品首页-使用redis优化@RequestMapping(value = "/toList", produces = "text/html;charset=UTF-8")@ResponseBodypublic 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对象,用来存放modelWebContext context = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());// 2.渲染页面html = thymeleafViewResolver.getTemplateEngine().process("goodsList", context);// 3.判断html是否为空,不为空则存入redis中,设置过期时间为60sif (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")@ResponseBodypublic 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对象,用来存放modelWebContext context = new WebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap());// 2.渲染页面html = thymeleafViewResolver.getTemplateEngine().process("goodsDetail", context);// 3.判断html是否为空,不为空则存入redis中,设置过期时间为60sif (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
    @Overridepublic 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")@ResponseBodypublic 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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【人工智能】第三部分:ChatGPT的应用场景和挑战

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

Pyinstaller安装与使用

一、Pyinstaller简介 PyInstaller将Python应用程序冻结(打包)独立可执行文件中。它可以构建较小的可执行文件,它是完全多平台的,并且使用OS支持来加载动态库,从而确保完全兼容。 二、Pyinstaller安装 1、下载安装 首先安装“pip install pywin32” 其次“pip install …

亿发软件:信息化与数字化,相互交织的科技双引擎

在现代科技发展的浪潮中&#xff0c;信息化和数字化是两个频繁被提及的关键词。尽管它们在很多情况下被视为同义词&#xff0c;但其实两者有着本质的区别和相互影响的关系。究竟是信息化推动了数字化&#xff0c;还是数字化引领了信息化的进程&#xff1f;本文将深入探讨信息化…

C++第二十五弹---从零开始模拟STL中的list(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、函数补充 2、迭代器完善 3、const迭代器 总结 1、函数补充 拷贝构造 思路&#xff1a; 先构造一个头结点&#xff0c;然后将 lt 类中的元…

10.dockerfile自动构建镜像

dockerfile自动构建镜像 类似ansible剧本&#xff0c;大小几kb 手动做镜像&#xff1a;大小几百M 首先创建一个dockerfile的路径&#xff0c;便于在路径下存在多个路径每个路径下都是dockerfile命名的脚本 注释&#xff1a;文件必须为&#xff1a;dockerfile或者Dockerfile …

基于深度学习的中文标点预测模型-中文标点重建(Transformer模型)【已开源】

基于深度学习的中文标点预测模型-中文标点重建&#xff08;Transformer模型&#xff09;提供模型代码和训练好的模型 前言 目前关于使用深度学习对文本自动添加标点符号的研究并不多见&#xff0c;已知的开源项目也较少&#xff0c;而对该领域的详细介绍更是稀缺。然而&#x…

【vscode-快捷键 一键JSON格式化】

网上有很多JSON格式化工具&#xff0c;也有很多好用的在线json格式化工具。但是其实Vscode里面的可以直接格式化JSON&#xff0c;这里分享一个我常用的小插件 Prettify JSON 未格式化的JSON数据 召唤出命令行&#xff0c;输入prettify JSON 即可! ✿✿ヽ(▽)ノ✿

OpenAI模型规范概览

这是OpenAI对外分享的模型规范文档&#xff08;Model Spec&#xff09;&#xff0c;它定义了OpenAI希望在API接口和ChatGPT&#xff08;含GPT系列产品&#xff09;中模型的行为方式&#xff0c;这也是OpenAI超级对齐团队奉行的行为准则&#xff0c;希望能对国内做RLHF的同学有帮…

力扣爆刷第148天之贪心算法五连刷(区间合并)

力扣爆刷第148天之贪心算法五连刷&#xff08;区间合并&#xff09; 文章目录 力扣爆刷第148天之贪心算法五连刷&#xff08;区间合并&#xff09;一、406. 根据身高重建队列二、452. 用最少数量的箭引爆气球三、435. 无重叠区间四、763. 划分字母区间五、56. 合并区间六、738.…

安卓约束性布局学习

据说这个布局是为了解决各种布局过度前套导致代码复杂的问题的。 我想按照自己想实现的各种效果来逐步学习&#xff0c;那么直接拿微信主页来练手&#xff0c;用约束性布局实现微信首页吧。 先上图 先实现顶部搜索框加号按钮 先实现 在布局中添加一个组件&#xff0c;然后摆放…

【java】速度搭建一个springboot项目

使用软件&#xff1a;IDEA&#xff0c;mysql 使用框架&#xff1a;springboot mybatis-plus druid 坑点 使用IDEA搭建一个springboot项目的时候&#xff0c;需要考虑一下IDEA版本支持的JDK版本以及maven版本。否则再构建项目&#xff0c;引入pom的时候就会报错。 需要检查…

PostgreSQL基础(十):PostgreSQL的并发问题

文章目录 PostgreSQL的并发问题 一、事务的隔离级别 二、MVCC PostgreSQL的并发问题 一、事务的隔离级别 在不考虑隔离性的前提下&#xff0c;事务的并发可能会出现的问题&#xff1a; 脏读&#xff1a;读到了其他事务未提交的数据。&#xff08;必须避免这种情况&#xf…

docker命令 docker ps -l (latest)命令在 Docker 中用于列出最近一次创建的容器

文章目录 12345 1 docker ps -l 命令在 Docker 中用于列出最近一次创建的容器。具体来说&#xff1a; docker ps&#xff1a;这个命令用于列出当前正在运行的容器。-l 或 --latest&#xff1a;这个选项告诉 docker ps 命令只显示最近一次创建的容器&#xff0c;不论该容器当前…

OpenAI发表研究论文 介绍了一种逆向工程AI模型工作原理的方法

ChatGPT 开发商 OpenAI 构建人工智能的方法本周遭到了前员工的抨击&#xff0c;他们指责该公司利用可能有害的技术冒不必要的风险。今天&#xff0c;OpenAI 发布了一篇新的研究论文&#xff0c;目的显然是为了表明它在通过提高模型的可解释性来应对人工智能风险方面的认真态度。…

计算机组成原理(一)

冯诺依曼机器的特征&#xff1a; 指令和数据以同等的地位存储在存储器当中指令和数据都是二进制指令和数据都是保存在存储器当中的 存储字 每个存储单元中的数据&#xff0c;称为存储字 存储字长 存储单元能够存储的二进制数据的长度 在一个8位系统中&#xff0c;字长是…

【C++进阶】深入STL之list:模拟实现深入理解List与迭代器

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;初步了解 list &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STL之list &#x1f4d2;1. list…

计算机的存储规则

计算机中的数据只有三类&#xff1a;Text 文本&#xff0c;Image 图片&#xff0c;Sound 声音。 文本包括数字、字母和汉字等。 视频是图片和声音的组合。 在计算机中&#xff0c;任何数据都是以二进制的形式来存储的。 数字的存储&#xff1a;转换为二进制进行存储。 字符…

[线程与网络] 网络编程与通信原理(六):深入理解应用层http与https协议(网络编程与通信原理完结)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

【Java面试】九、微服务篇-SpringCloud(上)

文章目录 1、SpringCloud五大组件2、服务注册和发现2.1 Eurake2.2 Eurake和Nacos的区别 3、Ribbon负载均衡3.1 策略3.2 自定义负载均衡策略 4、服务雪崩与熔断降级4.1 服务雪崩4.2 服务降级4.3 服务熔断 5、服务限流5.1 Nginx限流5.2 网关限流 6、微服务监控7、面试 1、SpringC…