java接口并发衡量_java 后端设计高并发接口总结

如何设置高并发接口

一、并发队列的选择

二、请求接口的合理设计

三、高并发下的数据安全

3.1 超发的原因

3.2 悲观锁思路

3.3 FIFO队列思路

3.4 乐观锁思路

一、并发队列的选择

Java的并发包提供了三个常用的并发队列实现,分别是:ArrayBlockingQueue、ConcurrentLinkedQueue 和 LinkedBlockingQueue 。

ArrayBlockingQueue是初始容量固定的阻塞队列,我们可以用来作为数据库模块成功竞拍的队列,比如有10个商品,那么我们就设定一个10大小的数组队列。

ConcurrentLinkedQueue使用的是CAS原语无锁队列实现,是一个异步队列,入队的速度很快,出队进行了加锁,性能稍慢。

LinkedBlockingQueue也是阻塞的队列,入队和出队都用了加锁,当队空的时候线程会暂时阻塞。

在请求预处理阶段,由于我们的系统入队需求要远大于出队需求,一般不会出现队空的情况,所以我们可以选择

ConcurrentLinkedQueue来作为我们的请求队列实现

二、请求接口的合理设计

一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。

通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上。这个后端接口,必须能够支持高并发请求,同时,非常重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果。为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点。仍然直接面向MySQL之类的存储是不合适的,如果有这种复杂业务的需求,都建议采用异步写入。当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以从页面中看到用户是否秒杀成功。但是,这种属于“偷懒”行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作”。

三、高并发下的数据安全

我们知道在多线程写入同一个文件的时候,会存现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一样的,结果和预期相同,就是线程安全的)。如果是MySQL数据库,可以使用它自带的锁机制很好的解决问题,但是,在大规模并发的场景中,是不推荐使用MySQL的。秒杀和抢购的场景中,还有另外一个问题,就是“超发”,如果在这方面控制不慎,会产生发送过多的情况。我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。

3.1 超发的原因

假设某个抢购场景中,我们一共只有100个商品,在最后一刻,我们已经消耗了99个商品,仅剩最后一个。这个时候,系统发来多个并发请求,这批请求读取到的商品余量都是99个,然后都通过了这一个余量判断,最终导致超发。(同文章前面说的场景),在下面的这个图中,就导致了并发用户B也“抢购成功”,多让一个人获得了商品。这种场景,在高并发的情况下非常容易出现。

57c4baf0ff913b46402bf4480fc3050e.png

3.2 悲观锁思路

解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。

悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。

28618ce0fd80dceb14b85879855e2d91.png

虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。

3.3 FIFO队列思路

那好,那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。

6844903974206701581

08087e191c94728fc3eba3ef1e76d73f.png

然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态。或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比。也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。

3.4 乐观锁思路

这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。

b83aa4baab80a2f2b4508e9b94b7513f.png

有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。

最后

欢迎大家有兴趣的可以关注我的公众号【java小瓜哥的分享平台】,文章都会在里面更新,还有各种java的资料都是免费分享的。

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

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

相关文章

两倍---C++

【问题描述】给定n个不同的正整数,你的任务是计算这些数里面有多少个数对满足:数对中一个数是另一个数的两倍,比如给定1 4 3 2 9 7 18 22,得到的答案是3,因为2是1的两倍,4是2的两倍,18是9的两倍…

java bitset_Java BitSet cardinality()方法与示例

java bitsetBitSet类cardinality()方法 (BitSet Class cardinality() method) cardinality() method is available in java.util package. cardinality()方法在java.util包中可用。 cardinality() method is used to return the cardinality (i.e. the number of bits is set t…

LeetCode: Merge k Sorted Lists

自己写的太复杂了,一开始想的是给开始的lists头们排序,然后从这个序列的第一个抽出来,然后再重新用二分法进行排序,不过这个方法large超时了,看了网上的发现还是用很土地方法用一个for循环从前两个开始merge到最后&…

JAVA 取得当前目录的路径

在写java程序时不可避免要获取文件的路径...总结一下,遗漏的随时补上 1.可以在servlet的init方法里 String path getServletContext().getRealPath("/"); 这将获取web项目的全路径 例如 :E:/eclipseM9/workspace/tree/ tree是我web项目的根目录 2.你也可以随时在任意…

golang mysql curd_Go 语言操作 MySQL 之 CURD 操作

本文转载于SegmentFault社区作者:Meng小羽MySQL 是目前开发中最常见的关系型数据库,使用 Go 语言进行操控数据库需要使用 Go 自带database/sql和驱动go-sql-driver/mysql来实现。创建好 Go 项目,需要引用驱动依赖:go get -u githu…

02.1-元素定位(find)

常用的一些方法 一、导包 from selenium import webdriver二、打开火狐(空白页) b webdriver.Firefox()三、跳转到指定的网站 b.get(https://www.baidu.com/)四、将浏览器页面最大化 b.maximize_window()五、通过F12可查看当前的贴吧为超链接形式 …

快速傅里叶变换(FFT)——按时间抽取DIT的基

目录【1】前言1、DIF计算量2、利用性质改善【2】公式推导1、N 到 2*N/2a、分解原序列b、分解后的DFT变换c、一系列化简操作之后d、蝶形信号流e、计算量总结2、N/2 到 2*N/4a、分解X2(k)序列b、蝶形信号流(2列)3、N/4 到 2*N/8a、蝶形信号流(3…

Python字符串| 带示例的format()方法

String.format()方法 (String.format() Method) format() method is used to format the string (in other words - we can say to achieve the functionality like printf() in C language). format()方法用于格式化字符串(换句话说,我们可以说实现了C语言中类似于…

PLSQL Developer使用技巧

1、PL/SQL Developer记住登陆密码在使用PL/SQL Developer时,为了工作方便希望PL/SQL Developer记住登录Oracle的用户名和密码;设置方法:PL/SQL Developer 7.1.2 ->tools->Preferences->Oracle->Logon History , “St…

3月份的总结

租房子找了个黑中介,各种扣钱,合租的违约了,押金不要了直接一走了之,水费我们承担,中介这会儿又把责任推得一干二净,还耍小聪明,非说我是两个人住的,各种费用要交两份。。。我一时气…

快速傅里叶变换(FFT)——按频率抽取DIF的基

目录【1】回顾DIT【2】算法原理【3】运算特点【1】回顾DIT https://blog.csdn.net/qq_42604176/article/details/105559756 【2】算法原理 设序列点数:N2^M,M为正整数。将输入序列按照前一半、后一半分开。(并非按照奇偶分) 由于&#xf…

02.2-元素定位(XPath)

XML路径语言用来确定XML文档中某部分位置的语言XPath用于在XML文档中通过元素和属性进行导航XPath遵守W3C标准XPath节点类型: 元素、属性、文本、命名空间、指令处理、注释、文档 通过路径表达式从XML文档中选取节点或节点设置 表达式结果说明/xxx选取根节点xxx/xx…

android ImageView 之 android:scaleTye=

原文:http://juliaailse.iteye.com/blog/1409317 1、scaleType“matrix” 是保持原图大小、从左上角的点开始,以矩阵形式绘图。 2、scaleType“fitXY” 是将原图进行横方向(即XY方向)的拉伸后绘制的。 3、scaleType“fitStart…

acquire方法_Python锁类| 带有示例的acquire()方法

acquire方法Python Lock.acquire()方法 (Python Lock.acquire() Method) acquire() is an inbuilt method of the Lock class of the threading module in Python. acquisition()是Python中线程模块的Lock类的内置方法。 This method is used to acquire a lock, either block…

VSS2008 安装silverlight3.0步骤

需要的Q我359273753 我是新手不知道在哪里上传附件 汗一个转载于:https://www.cnblogs.com/ganler1988/archive/2011/03/17/1987367.html

php字符串对象,PHP字符串到对象名称

好的我有一个字符串……$a_string "Product";我想在调用这样的对象时使用这个字符串:$this->$a_string->some_function();狄更斯如何动态调用该对象?(不要以为我在PHP 5心中)解决方法:所以你要使用的代码是:$a_string &quo…

莫比乌斯函数---C++

【问题描述】 莫比乌斯函数,数论函数,由德国数学家和天文学家莫比乌斯(Mobius,1790-1868)提出。梅滕斯(Mertens)首先使用μ(n)作为莫比乌斯函数的记号。而据说,高斯(Gauss)比莫比乌斯早三十年就曾考虑过这个函数。莫比乌斯函数在数…

Opencv——findContours函数再探(由轮廓联想连通域)

目录关于调参的一些思考分析图像的一些角度面积、周长、矩形度、圆形度、宽长比例1:找出汽车轮毂圆孔(从轮廓和连通域两个角度)例2:找出芯片中间正方形物体例3:桌面上橘色物体总结关于调参的一些思考 合理的参数设置&…

stl vector 函数_vector :: crend()函数以及C ++ STL中的示例

stl vector 函数C vector :: crend()函数 (C vector::crend() function) vector::crend() is a library function of "vector" header, it is used to get the first element of a vector from reverse ending, it returns a const reverse iterator pointing to th…

.Net DateTime.ToString 格式化输出 (转载)

原文 虽然 System.DateTime 本身已经具有了不少现成的格式化输出,例如: ToLongDateString, ToShortTimeString, ToUniversalTime 等,但是却远远不能满足我们实际的需要,这就要用到了 DateTime.ToString,就要提到 DateT…