防止订单重复提交
解决办法是,让你的订单服务具备幂等性 。一个幂等操作的特点是其任意多次执行结果与一次执行结果相同。对于创建订单的幂等操作来说就是无论发送多少次创建订单的请求,数据库只有一条订单记录。
具体做法是利用表的主键自带唯一特性的约束,插入订单记录的时候,先由订单系统生成一个全局唯一的订单号,提交订单的时候将订单号作为订单表的主键。这样就保证重复提交的订单,由于INSERT语句的主键是同一个订单号,只有一次INSERT语句执行成功。重复提交订单导致插入订单表失败,考虑到用户体验,订单服务也不要把错误返回给前端页面。
为了更好理解,把幂等创建订单的流程,绘制成时序图以供参考:
除了创建订单外,更新订单同样也有幂等的问题,可以利用数据库天然幂等的特性,例如UPDATE多次更新和一次更新结果一致。
如何解决ABA问题?
现实情况中可能由于网络时延导致出现响应丢失,这个时候会出现ABA问题。
ABA问题可以通过下面这张时序图来说明:
通用的解决办法是给订单表增加一列,列名可以叫version。每次查询订单,版本号也随订单的数据返回给页面。页面更新数据的请求中,需要把这个订单号作为更新请求的参数,带给订单服务。
具体作用是更新数据的时候,需要比较订单当前数据版本号是否和更新请求消息中所带版本号是否一致,如果不一致就拒绝更新数据。如果一致,才可以更新数据,同时把版本号+1。比较版本号、更新数据和版本号+1必须在同一个事务中进行。
具体SQL语句:
// An highlighted block
UPDATE orders set tracking_number = 666, version = version + 1
WHERE id = 1234 and version = 8;
有了版本号之后的情况如下面这个时序图: