标签:href row select service 无法 次数 锁表 lis where
源码地址
有纰漏,错误,欢迎指正,谢谢
${ }
可以从csv文件中获取数据具体怎么用,百度
测试场景为:请求对应商品,减少对应库存;
并发量:秒级1w请求;
Controller就不写了,但是要测试,需要通过Request测试
Mapper:直接更新stock库存数量
int updateStock(ProductLock lock);
<update id="updateStock" parameterType="com.example.lock.entity.ProductLock">
update product_lock
set stock = stock-#{stock,jdbcType=INTEGER}
where id = #{id,jdbcType=INTEGER}
AND
stock > 0
</update>
Service:先查询到商品详情,判断库存是否充足,更新库存数量
@Transactional(rollbackFor = Exception.class)
public int updateStock(ProductLockDto dto) throws Exception{
int res=0;
ProductLock entity=productLockMapper.selectByPrimaryKey(dto.getId());
// 判断:要更新的库存 > 当前库存
if (entity!=null && entity.getStock().compareTo(dto.getStock())>=0){
entity.setStock(dto.getStock());
return productLockMapper.updateStock(entity);
}
return res;
}
通过JMeter测试(秒级1w并发量),出现问题:
修改表结构:
修改Mapper:
<update id="updateStock_2" parameterType="com.example.lock.entity.ProductLock">
update product_lock
set stock = stock-#{stock,jdbcType=INTEGER},version = version + 1
where
id = #{id,jdbcType=INTEGER}
AND
version = #{version,jdbcType=INTEGER}
AND
stock > 0
</update>
依然秒级并发1w请求测试:(1w个请求,每个请求减少库存数=2)
测试前数据:库存2w,version=0
测试数据后:库存18298,version=851
首先,真正请求通过,并修改了库存的请求数应该等于version的增量;
即:version * 2 = 减少库存数
(因为每个version修改,库存减少2)
851 * 2 = 1702
也就等于 20000 - 19298 = 1702
说明:后端数据修改是没有问题的;
但是:version修改次数,可以认为是成功响应请求次数:851个;
1w请求,响应了851个,不太象话;
在高并发写入的情况下,不应该使用乐观锁!,后面悲观锁效果更好
添加Mapper:
<!--悲观锁实现 for update 锁表-->
<select id="selectByIdNegative" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from product_lock
where id = #{id}
for update
</select>
<update id="updateStock_3" parameterType="com.example.lock.entity.ProductLock">
update product_lock
set stock = stock-#{stock,jdbcType=INTEGER},version = version+1
where
id = #{id,jdbcType=INTEGER}
AND
stock > 0
</update>
Service层:@Transactional注解,保证上面两个方法,是一个事务,才能实现for update
锁表
@Transactional(rollbackFor = Exception.class)
public int updateStock_3(ProductLockDto dto){
int res =0;
// select-for update 查询
ProductLock entity = productLockMapper.selectByIdNegative(dto.getId());
// 判断version字段,库存是否充足
if (entity!=null && entity.getStock().compareTo(dto.getStock())>=0){
entity.setStock(dto.getStock());
res = productLockMapper.updateStock_3(entity);
}
if (res > 0) {
log.info("减少库存=>{}",dto.getStock());
}
return res;
}
依然秒级并发1w请求测试:(1w个请求,每个请求减少库存数=2)
测试前数据:库存2w,version=0
测试数据后:库存356,version=9822
与之前一样:version*2 = 减少库存数
(因为每个version修改,库存减少2)
9822 * 2 = 19644
也就等于 20000 - 356 = 19644
说明:后端数据修改是没有问题的;
同样:并没有响应所有的请求,但是从version的修改次数看,
1w请求,响应了9822个请求,失败178个
标签:href row select service 无法 次数 锁表 lis where
原文地址:https://www.cnblogs.com/mussessein/p/12078074.html