JavaWeb 并发:FOR UPDATE 实战,监测并解决。
2015-03-22 13:04
218 查看
Writer:BYSocket(泥沙砖瓦浆木匠)
微博:BYSocket
豆瓣:BYSocket
针对并发,老生常谈了。目前一个通用的做法有两种:锁机制:1.悲观锁;2.乐观锁。
但是这篇我主要用于记录我这次处理的经历,另外希望能看的大神,大牛,技师者,学长,兄长,大哥们能在评论中发表自己的看法和解决技巧等。
一个表,暂且叫 wallet,其中3个字段是 金额。初始值为0,如下图所示:
然后我们写了一个极为简单的Controller,并写了下面的Service代码:
?
就简单的通过主键读取到一个对象,注意这个对象是没加锁的。也就是说,所对应的SQL如下:
?
我这边是MyBiatis,大家应该看得懂的。然后一个增加1 一个减少2 一个增加 3。
我用了Web应用压力测试工具:Boom。https://github.com/rakyll/boom Go编写的HTTP(S)负载生成器,ApacheBench(AB)的替代工具。Boom是一个微型程序,能够对Web应用程序进行负载测试。它类似于
Apache Bench ,但在不同的平台上有更好的可用性,安装使用也比较简单。
简单使用方式如下:
?
所以我就如图进行压力测试,可见这个小工具还挺美的,这里我连接数1000,并发数100:
可见后台程序报错了。什么错误呢?
?
原来并发导致update死表了。数据库的数据不用看了肯定是错误的。
先补一下其知识:利用select * for update 可以锁表/锁行。自然锁表的压力远大于锁行。所以我们采用锁行。什么时候锁表呢?
假设有个表单products ,里面有id跟name二个栏位,id是主键。
例1: (明确指定主键,并且有此笔资料,row lock)
SELECT * FROM wallet WHERE id=’3′ FOR UPDATE;
例2: (明确指定主键,若查无此笔资料,无lock)
SELECT * FROM wallet WHERE id=’-1′ FOR UPDATE;
例2: (无主键,table lock)
SELECT * FROM wallet WHERE name=’Mouse’ FOR UPDATE;
例3: (主键不明确,table lock)
SELECT * FROM wallet WHERE id<>’3′ FOR UPDATE;
例4: (主键不明确,table lock)
SELECT * FROM wallet WHERE id LIKE ‘3’ FOR UPDATE;
因此我们更新了下Service层的Mapper方法:
?
所对应的SQL如下:
?
自然大家可以看到,我这边加了锁,是通过主键锁行。
按着上面的测试连接数1000,并发数100,控制台没报错。
数据库结果也是很不错。
按着上面的测试连接数5000,并发数350,控制台还是没报错。
数据库结果却是很出错了!!!
少update了很多值。为什么呢?
然后我用jvisualvm 小工具检测。多测了几次,发现连接数5000,并发数350,并发数上升。有一个图的值始终不变。如图:
发现图中 tomcat的守护线程一直在200左右。后来我去找了下tomcat的server.xml发现了,使用了默认,大概就是200左右。
所以就配置了一下,大致配置方法有两种如下:
第1种方式:配置Connector
maxThreads:tomcat可用于请求处理的最大线程数
minSpareThreads:tomcat初始线程数,即最小空闲线程数
maxSpareThreads:tomcat最大空闲线程数,超过的会被关闭
acceptCount:当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理
?
第2种方式:配置Executor和Connector
name:线程池的名字
class:线程池的类名
namePrefix:线程池中线程的命名前缀
maxThreads:线程池的最大线程数
minSpareThreads:线程池的最小空闲线程数
maxIdleTime:超过最小空闲线程数时,多的线程会等待这个时间长度,然后关闭
threadPriority:线程优先级
?
maxThreads:线程池的最大线程数,直接配置1000,然后用连接数10000,并发数800测试。轻松见图:
感谢帮助我的人。希望有大牛在此讨论相关。小生感激不尽。
微博:BYSocket
豆瓣:BYSocket
一、前言
针对并发,老生常谈了。目前一个通用的做法有两种:锁机制:1.悲观锁;2.乐观锁。但是这篇我主要用于记录我这次处理的经历,另外希望能看的大神,大牛,技师者,学长,兄长,大哥们能在评论中发表自己的看法和解决技巧等。
二、故事是这样的
一个表,暂且叫 wallet,其中3个字段是 金额。初始值为0,如下图所示:然后我们写了一个极为简单的Controller,并写了下面的Service代码:
?
?
三、测试是这样
我用了Web应用压力测试工具:Boom。https://github.com/rakyll/boom Go编写的HTTP(S)负载生成器,ApacheBench(AB)的替代工具。Boom是一个微型程序,能够对Web应用程序进行负载测试。它类似于Apache Bench ,但在不同的平台上有更好的可用性,安装使用也比较简单。
简单使用方式如下:
?
可见后台程序报错了。什么错误呢?
?
四、FOR UPDATE的使用
先补一下其知识:利用select * for update 可以锁表/锁行。自然锁表的压力远大于锁行。所以我们采用锁行。什么时候锁表呢?假设有个表单products ,里面有id跟name二个栏位,id是主键。
例1: (明确指定主键,并且有此笔资料,row lock)
SELECT * FROM wallet WHERE id=’3′ FOR UPDATE;
例2: (明确指定主键,若查无此笔资料,无lock)
SELECT * FROM wallet WHERE id=’-1′ FOR UPDATE;
例2: (无主键,table lock)
SELECT * FROM wallet WHERE name=’Mouse’ FOR UPDATE;
例3: (主键不明确,table lock)
SELECT * FROM wallet WHERE id<>’3′ FOR UPDATE;
例4: (主键不明确,table lock)
SELECT * FROM wallet WHERE id LIKE ‘3’ FOR UPDATE;
因此我们更新了下Service层的Mapper方法:
?
?
按着上面的测试连接数1000,并发数100,控制台没报错。
数据库结果也是很不错。
五、加大压力
按着上面的测试连接数5000,并发数350,控制台还是没报错。数据库结果却是很出错了!!!
少update了很多值。为什么呢?
六、jvisualvm 小工具检测,发现Tomcat线程连接数默认不够
然后我用jvisualvm 小工具检测。多测了几次,发现连接数5000,并发数350,并发数上升。有一个图的值始终不变。如图:发现图中 tomcat的守护线程一直在200左右。后来我去找了下tomcat的server.xml发现了,使用了默认,大概就是200左右。
所以就配置了一下,大致配置方法有两种如下:
第1种方式:配置Connector
maxThreads:tomcat可用于请求处理的最大线程数
minSpareThreads:tomcat初始线程数,即最小空闲线程数
maxSpareThreads:tomcat最大空闲线程数,超过的会被关闭
acceptCount:当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理
?
name:线程池的名字
class:线程池的类名
namePrefix:线程池中线程的命名前缀
maxThreads:线程池的最大线程数
minSpareThreads:线程池的最小空闲线程数
maxIdleTime:超过最小空闲线程数时,多的线程会等待这个时间长度,然后关闭
threadPriority:线程优先级
?
七、总结
感谢帮助我的人。希望有大牛在此讨论相关。小生感激不尽。
相关文章推荐
- JavaWeb 并发:FOR UPDATE 实战,监测并解决。 - 泥沙砖瓦浆木匠
- JavaWeb 并发:FOR UPDATE 实战,监测并解决。
- JavaWeb 并发:FOR UPDATE 实战,监测并解决。
- java web解决瞬间高并发的策略
- Java高并发,主要的解决方法就是锁,原子量。如果是web的话,就是缓存(类似hashmap,减少与数据库的交流)
- Java Web Servlet.init() for servlet springMVC threw exception解决
- WEB工程(JAVA链接)数据库UPDATE传值时中文乱码解决
- 解决update-alternatives: error: no alternatives for mozilla-javaplugin.so.
- 关于sql server的纪录修改冲突解决和oracle的for update 的并发锁定测试
- JAVA MyEclipse(3)---解决MyEclipse安装maven的问题:Unable to update index for central
- JAVAWEB开发之Hibernate详解(三)——Hibernate的检索方式、抓取策略以及利用二级缓存进行优化、解决数据库事务并发问题
- JAVAWEB开发之Hibernate详解(三)——Hibernate的检索方式、抓取策略以及利用二级缓存进行优化、解决数据库事务并发问题
- mysql并发insert deadlock分析以及解决,无delete/update/for update
- 【Javaweb】于Eclipse for JavaEE中编译一个项目Tomcat下的webapps却没有的解决方法
- 关于sql server的纪录修改冲突解决和oracle的for update 的并发锁定测试
- Python Programming with the Java(TM) Class Libraries: A Tutorial for Building Web and Enterprise App
- Zend Studio for Eclipse的java.lang.NullPointerException错误的解决方法
- Zend Studio for Eclipse的java.lang.NullPointerException错误的解决方法
- Web网站缓存文件并发问题解决方案
- weborb for java 安装记录