Java开发面试:高并发秒杀系统如何设计与优化

2024-06-21 21:18

本文主要是介绍Java开发面试:高并发秒杀系统如何设计与优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转载链接
如今处在一个大数据时代,应届生找工作面试高级Java开发工程师时,经常会被问一些和大数据相关的问题,比如大数据处理问题、高并发处理问题、数据优化问题等,笔者曾经遇到两个比较经典的问题,高并发秒杀系统的设计优化问题和大数据文件排序问题。在这里总结了高并发秒杀系统的设计和优化点。

面试官常问的问题有:

简单说一下秒杀系统的设计思路?

你怎么实现秒杀业务的?

你怎么保证秒杀成功的?

秒杀操作的策略是什么?

你使用的Redis有什么用?

你为什么使用Redis中间件?

你测试过你这个系统的抗压能力么?

你使用过什么方法来测试你的系统并发量?

你觉得你这个系统还可以再优化么?

你觉得你这个系统的瓶颈在哪里?还可以在哪些方向做进一步优化?

  很多面试官问的比较笼统,很少面试官问的比较具体,事先的这些问题,都要做好准备,笔者的准备思路是:功能模块划分=》秒杀策略=》自己的优化点=》工具测试抗压=》别人提供的优化方法和秒杀策略

1 秒杀系统特点
秒杀业务简单,卖家查询,买家下订单减库存。
秒杀时网站访问流量激增,出现峰值;
访问请求数量远大于实际需求量。
2 架构设计优化方案
1 秒杀系统架构设计优化
一个常规的秒杀系统从前到后,依次有:

              前端浏览器秒杀页面=》中间代理服务=》后端服务层=》数据库层根据这个流程,一般优化设计思路:将请求拦截在系统上游,降低下游压力。在一个并发量大,实际需求小的系统中,应当尽量在前端拦截无效流量,降低下游服务器和数据库的压力,不然很可能造成数据库读写锁冲突,甚至导致死锁,最终请求超时。 

整体设计思路和优化点:

限流:屏蔽掉无用的流量,允许少部分流量流向后端。

削峰:瞬时大流量峰值容易压垮系统,解决这个问题是重中之重。常用的消峰方法有异步处理、缓存和消息中间件等技术。

异步处理:秒杀系统是一个高并发系统,采用异步处理模式可以极大地提高系统并发量,其实异步处理就是削峰的一种实现方式。

内存缓存:秒杀系统最大的瓶颈一般都是数据库读写,由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到内存缓存,效率会有极大地提升。

可拓展:当然如果我们想支持更多用户,更大的并发,最好就将系统设计成弹性可拓展的,如果流量来了,拓展机器就好了。像淘宝、京东等双十一活动时会增加大量机器应对交易高峰。

消息队列:消息队列可以削峰,将拦截大量并发请求,这也是一个异步处理过程,后台业务根据自己的处理能力,从消息队列中主动的拉取请求消息进行业务处理。

充分利用缓存:利用缓存可极大提高系统读写速度。

2详细方案

2.1 前端方案
静态资源缓存:将活动页面上的所有可以静态的元素全部静态化,尽量减少动态元素;通过CDN缓存静态资源,来抗峰值。
禁止重复提交:用户提交之后按钮置灰,禁止重复提交
用户限流:在某一时间段内只允许用户提交一次请求,比如可以采取IP限流

2.2 中间代理层
可利用负载均衡(例如反响代理Nginx等)使用多个服务器并发处理请求,减小服务器压力。

2.3 后端方案
控制层(网关层)

        限制同一UserID访问频率:尽量拦截浏览器请求,但针对某些恶意攻击或其它插件,在服务端控制层需要针对同一个访问uid,限制访问频率。

服务层

当用户量非常大的时候,拦截流量后的请求访问量还是非常大,此时仍需进一步优化。

1.业务分离:将秒杀业务系统和其他业务分离,单独放在高配服务器上,可以集中资源对访问请求抗压。

2.采用消息队列缓存请求:将大流量请求写到消息队列缓存,利用服务器根据自己的处理能力主动到消息缓存队列中抓取任务处理请求,数据库层订阅消息减库存,减库存成功的请求返回秒杀成功,失败的返回秒杀结束。

3.利用缓存应对读请求:对于读多写少业务,大部分请求是查询请求,所以可以读写分离,利用缓存分担数据库压力。

4.利用缓存应对写请求:缓存也是可以应对写请求的,可把数据库中的库存数据转移到Redis缓存中,所有减库存操作都在Redis中进行,然后再通过后台进程把Redis中的用户秒杀请求同步到数据库中。

2.4 数据库层
数据库层是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担“能力范围内”的访问请求。所以,上面通过在服务层引入队列和缓存,让最底层的数据库高枕无忧。

   如果不使用缓存来作为中间缓冲而是直接访问数据库的话,可以对数据库进行优化,减少数据库压力。对于秒杀系统,直接访问数据库的话,存在一个【事务竞争优化】问题,可使用存储过程(或者触发器)等技术绑定操作,整个事务在MySQL端完成,把整个热点执行放在一个过程当中一次性完成,可以屏蔽掉网络延迟时间,减少行级锁持有时间,提高事务并发访问速度。

2.5 其他秒杀策略
减少硬件开销的策略 :

   策略1:消息队列缓存请求,按照队列模型取任务执行,秒杀完毕即终止到秒杀结束页面。策略2:使用数组为并发请求随机分配秒杀状态(成功和失败),然后将分配到失败状态的请求派发到秒杀失败的页面,分到成功状态的用户在慢慢的按顺序执行秒杀操作;(如果处理失败了可以利用日志来查找具体秒杀失败的商品和用户,执行补救措施或者从其他用户中拿取一个来执行秒杀操作)策略3:类似于策略2,不过是用数组为用户分配秒杀资格,将大流量的用户限制为小流量的用户,得到秒杀资格的去执行秒杀,得不到秒杀资格的跳到秒杀失败页面。 

(分配状态或分配秒杀资格的策略:(数组状态密度不同,由前到后逐渐稀疏,可以让先到的在前面随机分配,后到的在后面随机分配)根据先到的时间)

3 案例:利用消息中间件和Redis缓存实现
Redis是一个分布式缓存系统,支持多种数据结构,可利用Redis轻松实现一个强大的秒杀系统。

   我们可以采用Redis 最简单的key-value数据结构,用一个原子类型的变量值(AtomicInteger)作为key,把用户id作为value,库存数量便是原子变量的最大值。对于每个用户的秒杀,我们使用 RPUSH key value插入秒杀请求, 当插入的秒杀请求数达到上限时,停止所有后续插入。然后我们可以再启动多个工作线程,使用 LPOP key 读取秒杀成功者的用户id,然后再操作数据库做最终的下订单减库存操作。当然,上面Redis也可以替换成消息中间件如ActiveMQ、RabbitMQ等,也可以将缓存和消息中间件 组合起来,缓存系统负责接收记录用户请求,消息中间件负责将缓存中的请求同步到数据库。

(1)使用Redis中间件缓存动态资源的好处?

   提高访问速度,减少对数据库的链接的打开、关闭,

(2)为什么不用JVM内存而使用Redis作为缓存呢?

  JVM 内存较小,隔一段时间会自动进行垃圾回收。JVM和业务程序绑定在一起了,如果程序出错,JVM也会停止,这样就导致缓存数据丢失。如果使用Redis,除了缓存比较大之外,还实现了缓存数据和业务程序的分离,即使运行程序出现错误,也不会影响缓存。

3 压力测试
使用JMeter 压测工具

下载、安装、进入C:/JMeter/bin下面的jmeter.bat批处理文件来启动JMeter的可视化界面,

进入测试计划添加线程组: 设置线程数,循环次数,添加HTTP默认请求,服务器名称,IP,以及自己设定的携带参数

添加监听器,存放测试结果:聚合报告,可以表格查询、图形结果、树结果

点击运行-》启动。

并发量:50W-100W 100W-500W

这篇关于Java开发面试:高并发秒杀系统如何设计与优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082360

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template