关于订单重复提交的问题

问题:

  1. 如何用户防止订单重复提交?
  2. 如何防止用户第一次提价网络错误导致多次提交?

分析:

  1. 问题属于幂等问题&安全问题
  2. 订单根据是否有 前期业务流水号/订单号 分为两种: 全新订单(类似商城订单) / 三方订单(类似支付订单,支付订单会以第三方业务唯一流水号作支撑)

解决:

  1. 全新订单
    全新订单的重复提交既是幂等问题,也是安全问题。解决方案可以与安全问题,即与CSRF(跨站请求伪造)问题合并处理。
    统一解决访问为,用户在访问提交页面或试算接口时,生成用户唯一或随机Token(建议用户唯一Token,随机Token在后续处理上可能会需要额外处理)与请求一起返回,Token临时放于缓存中,缓存必须为一主(多从)缓存(即,单一Key必须对应单一主,一主可以进行分布式存储)。
    用户在提交订单时,附带Token至请求中,服务端读取主缓存(若读从缓存,会存在主从同步时间差,导致结果存在二义性)。若缓存Key存在,删除缓存,并进行后续业务操作;若不存在,返回订单已提交的提示。
    若订单提交要求第二次提交时必须返回订单创建成功结果,则可以在保存订单时,将缓存Key存于数据库中,与订单进行关联,并将关联信息存于缓存中。后续请求过来时,若第一缓存Key不存在,则以关联缓存/数据库数据为准。

  2. 三方订单
    三方订单要求对方请求中必须根据业务方放置唯一流水号。数据库表根据业务渠道和流水号建唯一联合索引,并建立联合索引的分布式缓存。
    请求优先读取缓存和数据库,若缓存或数据库存在,直接根据创建完成的订单返回结果。若不存在,进行业务处理,此处可以加分布式悲观锁。若加分布式悲观锁,加锁之后,重复读取数据,防止订单已处理。若无分布式锁,则根据数据库唯一索引进行数据操作的防重。