目录
页面级高并发秒杀优化(Redis缓存+静态化分离)
重点:手动渲染商品列表做页面缓存
重点:页面静态化(利用浏览器的缓存) 即前后端分离
非编程的优化,静态资源优化
重点:秒杀接口第一次优化
服务级高并发秒杀优化(RabbitMQ+接口优化)
重点:秒杀接口第二次优化
图形验证码及恶意防刷
重点:接口地址隐藏
重点:接口防刷限流(同一ip一秒钟访问多少次)
秒杀压测-Jmeter压力测试
基于spring boot高性能高并发秒杀系统方案及优化(第一部分:初步方案+分布式会话+参数效验解析)
项目源码:https://github.com/yingyingqiqi/flash
这是电商系统的一个模块,主要涉及秒杀这个应用场景,但是,里面的知识却超越了秒杀,涉及到高并发、高性能的系统构建(缓存+异步+限流)
闲扯:这篇文章是对慕课网“Java秒杀系统方案优化 高性能高并发实战”课程的学习总结,以及自己的一些看法和改良,很久之前看的课程了,现在二刷,并加上一些示意图,方便自己或者他人理解秒杀涉及到的技术。
文章整体思路介绍:
1.完成一些基础的工具类开发,分布式会话、原生redis的API集成、参数的效验及解析、秒杀的初步构想。
2.秒杀的优化,各种加缓存、异步化、防刷限流。
3.这篇文章不讲代码的实现,主要讲思路,给出示意图,方便理解。
技术栈:spring+ spring boot+ mybatis+ +redis+ rabbitmq+ 前端技术知识
秒杀未优化前示意图
1.一句话讲清楚瓶颈:无缘无故,时时刻刻请求数据库,数据库并发是很小的。
使用不同层级和粒度的缓存对系统做优化改造,比如:对服务端手动渲染商品列表做页面缓存,对商品详情静态化来利用客户端浏览器的缓存,对热点数据做对象级的缓存
1.第一部分已经介绍了,页面时通过thymeleaf构建视图(你可以理解为jsp),thymeleaf是spring推荐使用
2.手动渲染视图,将渲染结果存入redis中。用户请求时,直接返回redis中的html
3.当页面需要显示用户信息的时候,这种方式是不适合的。
1.页面静态化,也称前后端分离,服务端配置,用户请求,服务器响应时,不返回数据,只返回html纯页面。
2.此纯html页面,通过Ajax向服务端第二次请求,获取所需数据。
1.此次优化,主要解决超卖问题,并没有涉及很深入的优化
将通过预减库存减少透穿到DB的请求,通过异步处理和排队机制缓解数据库的压力,降低应用接口负载,主要包括内存标记,Redis做库存预判,消息队列异步写库,秒杀接口优化。
1.系统初始化,把商品库存数量加载到redis,建立内存标记(hashMap),减少redis访问(网络请求延时)。
2.redis预减库存,库存不足,直接返回失败,减少用户请求向下访问。
3.建立消息队列,请求入队,秒杀实际操作延迟执行,即异步写库,直接返回提示(排队等待)。
4.请求出队,减少库存,生成订单,订单存入redis中,等待轮询结果。
5.前端发送Ajax请求轮询秒杀结果。(类似12306买票,排队中)
隐藏秒杀地址,实现图形验证码,接口限流防刷,列表页和详情页防刷,秒杀操作防刷,验证码防刷等。
1.第一次请求服务端获取一串随机字符(每个用户唯一60秒失效),url拼上字符才是实际地址。
2.接口地址的隐藏,类似接口防止重放攻击,实际地址中带入一串字符,请求到达服务端,验证字符。
3.可以设计的再复杂一点,随机字符只可以使用一次,请求第一次到达后失效。
1.使用springMVC的HandlerInterceptorAdapter拦截器,实现抽象类preHandler方法
2.这里优化第一部分的参数解析器,对于获取user用户信息的步骤。利用ThreadLocal (线程安全的容器)存储user用户信息。
3.通过拦截器,拦截使用AccessLimit注解的方法,并获取注解的数据,检查访问次数是否超出限制,没超限制放行此方法。
压力测试神器-JMeter,由于单机部署,mysql,redis,jdk等都在一部机器上。大致压测结果为(5000个用户10次请求):
QPS 商品列表 秒杀接口
优化前 920 950
优化后 2540 2103