业务上锁的应用

业务场景

针对一个赔付工单(由底下小二发起),当金额数量大于必定值之后,针对这笔工单就会有层层审批(风控),先YY一个审批流「TL审批」--->「主管审批」--->「财务审批」.这里就会存在3种权限「一审权限」「二审权限」「终审权限」,当这笔工单被小二提交之后就会给小二对应的TL建立一个审批任务,在主管的界面就能够看到相应的审批任务,主管能够点击经过或者拒绝数据库

实现

1.查询任务,判断当前角色是否有权限操做该笔任务,任务没有完结等一系列校验
    2.驱动状态机更新工单状态
    3.完结任务

异常场景

场景一
  1. 操做:主管疯狂点击经过按钮3次(前提是按钮点击一次不会灰显,就算灰显也能够经过模拟请求来实现)
  2. 异常状况:三个点击线程都运行完1,而后线程1驱动状态机(经过 + 当前状态:待TL审批)获得的结果是待主管审批,紧接着线程2驱动状态机(经过 + 当前状态:待主管审批)获得的结果是待财务审批,而后线程3再运行驱动状态机(经过 + 当前状态:待财务审批)获得的结果是出帐成功(不考虑屡次完结任务会出现异常)
  3. 异常分析:在该场景中,只要角色拥有「一审权限」就能够经过漏洞直接把该订单审核出帐
  4. 解决方案:线程

    • 细化状态机中的每一个审核操做
      1.查询任务,查询该笔任务对应当前操做类型(TL审批OR主管审批OR财务审批)
      ---这里不单单是「经过」操做,判断当前角色是否有对应操做权限
      2.根据当前操做类型+当前状态驱动状态机
      3.完结任务
    • 在查询任务以前加一个全局锁,针对这笔工单进行全局锁定(更加优雅)

场景二

  1. 操做:一个角色同时拥有一审权限和二审权限,当他打开一个工单要进行一审,可是其它主管已经执行了一审的动做,而且更新了一些信息.由于该角色页面没有刷新获取不到更新的信息,而后点击了经过按钮
  2. 异常状况:点击经过按钮就至关于进行了二审,会形成该角色获取不到最新信息而产生误判
  3. 解决方案:在场景一增长一个全局锁的前提下,能够给页面传递一个工单modifyTime,在全局锁里面判断modifyTime是否一致,若是不一致说明该笔工单已经被更新了,能够给用户相应的提醒

其它

  1. 在业务中整个状态机的流转都是肯定的,因此为了保证状态流转正确,因此在更新数据库状态的时候,须要带上关于状态的乐观锁UPDATE XXX SET status = XXX WHERE id = XXX AND from_status = XXX
  2. 若是使用的是全局锁,那么每一个操做工单的地方都须要加上相应的全局锁
相关文章
相关标签/搜索