全国服务热线:15381151948    400-0571-731

用户名/手机号

密码

注册 忘记密码?
欢迎您,网博资源有着19年服务经验的老牌网络公司,在此欢迎您的加盟!
新闻中心
订单系统中并发问题与锁机制的探讨
来源: | 作者:webgotoo | 发布时间: 2019-08-22 | 576 | 分享到:
      问题的根源

      假设在订单管理系统开发计划中(以火车票订购系统为例),用户A和用户B必须预订从成都到北京的火车票,并且A和B都在不同的票务销售中查询某个车厢。 视窗。 下铺有空间。 当用户B果断地订购下铺时,用户A犹豫订购中间或底部。 当用户A决定订购下铺时,系统会提示已预留下铺,请重新选择上铺。 在这个系统场景中,让我们探讨火车票系统如何处理并发事件以及如何使用锁机制来避免重复预订。

      方案1:

      为了避免重复预订,大多数人会考虑去数据库检查商店是否已经在预订操作之前被预订,假设“商店”数据库表添加了标签字段FLAG(空闲:0;预订:  1),if如果报价的FLAG字段值为1,则保留不成功。 如果它为0,则保留成功并且FLAG设置为1.如果这种解决方案位于具有少量流量的系统中,则这种解决方案可能是可行的。 但是,当有大量的业务,特别是火车票的数量时,就会出现问题。 问题是当用户A和用户B同时订阅同一商店时,虽然它是“同时”的,但必须有一个数据库操作的序列。 假设A正在查询商店的FLAG,则值为0,准备就绪。 订阅设置为值1,而B已经成功订阅并将FLAG设置为1.因为A没有对FLAG = 1的即时查询,所以保留成功,并且FLAG设置为1。

      订单系统中并发问题与锁机制的探讨

      这导致重复预订。 在票务高峰期,使用这样的方案,重复预订是不可避免的。

      方案2:

      我们想过使用数据库的悲观锁来解决这个问题。 想象一下,如果用户A查询他想要预订的票证,则用户B根本找不到它。 只有A可以看到它。 是否有可能没有重复预订? 因为没有人在抢劫他。

      这可以这样实现:

      选择* from table where ...... for update skip locked,该语句是查询用户指定的票证信息,并锁定(for update),如果有记录被锁定,则自动跳转到下一个 记录(跳过锁定),所以谁首先查询可以慢慢考虑是否去顶部或底部。 但火车票系统是这样做的吗? 显然不是,因为用户体验太差了,机票实际上很多,但不明显的是它不能买。 这显然是不合理的。

      方案3:

      我们还考虑从订单管理系统程序级解决并发问题。 简单的方法是使用同步来处理它,但我们需要知道必须以群集模式部署大型系统。 同步只能解决单节点环境的并发问题。 要解决此问题,您仍必须依赖全局锁定机制。

      方案4

 

      既然又回到了在数据库上加锁,我们又想一下如果我们在查询时,使用乐观锁,但在预订之前使用悲观锁会怎样呢?例如我们查询时:select * from table where ……用户A、用户B都查询到了相同的票信息(中铺和下铺),用户A或用户B在预订时做一次悲观锁:select * from table where …… for update(只对预订的票做悲观锁)

 

      此时后者在预订时,无法获取该记录的锁,自然就无法预订,避免了重复预订的问题。在杭州众多开发公司中,向你推荐网博资源,为什么推荐网博资源呢?因为网博有着丰富的开发经验、资深的开发团队、丰富的开发案例,14年开发经验。系统开发网博资源