JPA使用乐观锁应对高并发

三世轮回 提交于 2020-07-27 11:43:37

高并发系统的挑战

在部署分布式系统时,我们通常把多个微服务部署在内网集群中,再用API网关聚合起来对外提供。为了做负载均衡,通常会对每个微服务都启动多个运行实例,通过注册中心去调用。

那么问题来了,因为有多个实例运行都是同一个应用,虽然微服务网关会把每一个请求只转发给一个实例,但当面对高并发时,但它们仍然可能同时操作同一个数据库表,这会不会引发什么问题呢?

悲观锁的问题

比如电商中常见的商品秒杀系统,在用户抢购商品过程中,会有大量并发请求,很可能同时读写一个包含商品剩余数量的表,这种一般要给数据库加锁,否则很容易出现商品超卖错卖的情况。

如果使用数据库自带的锁机制,也就是悲观锁,在写入的时候锁定数据库,其他修改请求到来时就必须等待锁释放,但这就使效率降下来了,而且高并发场景下可能有的请求一直抢不到锁,就会长时间卡在那导致请求失败,然后有大量重试,系统可能会发生连接数耗尽等异常。

乐观锁是个好东西

查阅资料发现乐观锁是个好东西,它是为数据库表增加一个标识数据版本的version字段来实现的,读取数据时把version字段一同读出,写入数据库时比对version字段就知道数据是否被更改过,如果version不相等就说明持有的是过期数据,不能写入,如果相等就可以写入,并把version加一。

乐观锁在写入数据库的时候,才会检查数据是否冲突,如果发现冲突了,就放弃写入,返回写入失败的信息,相比于悲观锁,这是一种轻量级的对数据的锁定方式,能够应对高并发需求。

给数据库添加乐观锁 说乐观锁是个好东西,首先得说 JPA 是个好东西,因为Spring Data JPA已经内置了乐观锁的实现,给数据库表添加乐观锁很简单,添加一个整型字段,并加入@Version注解就可以了,每次提交数据时JPA会自动检查版本。

@Entity  
@Table(name = "m_order")  
public class Order {  
...  
	@Version  
	private int version;  
...  
}  
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!