《后端存储实战课》课程学习笔记(二)

创建和更新订单时,如何保证数据准确无误?

  • 订单系统是整个电商系统中最重要的一个子系统,订单数据也就是电商企业最重要的数据资产。
  • 一个合格的订单系统,最基本的要求是什么?数据不能错。
    • 首先,你的代码必须是正确没 Bug 的,如果说是因为代码 Bug 导致的数据错误,那谁也救不了你。
    • 然后,你要会正确地使用数据库的事务。比如,你在创建订单的时候,同时要在订单表和订单商品表中插入数据,那这些插入数据的 INSERT 必须在一个数据库事务中执行。

订单系统的核心功能和数据

  • 简单梳理一下一个订单系统必备的功能,它包含但远远不限于:
    • 创建订单;
    • 随着购物流程更新订单状态;
    • 查询订单,包括用订单数据生成各种报表。
  • 为了支撑这些必备功能,在数据库中,我们至少需要有这样几张表:
    • 订单主表:也叫订单表,保存订单的基本信息。
    • 订单商品表:保存订单中的商品信息。
    • 订单支付表:保存订单的支付和退款信息。
    • 订单优惠表:保存订单使用的所有优惠信息。
  • 这几个表之间的关系是这样的:订单主表和后面的几个子表都是一对多的关系,关联的外键就是订单主表的主键,也就是订单号。

如何避免重复下单?

  • 一个订单系统,提供创建订单的 HTTP 接口,用户在浏览器页面上点击“提交订单”按钮的时候,浏览器就会给订单系统发一个创建订单的请求,订单系统的后端服务,在收到请求之后,往数据库的订单表插入一条订单数据,创建订单成功。
  • 假如说,用户点击“创建订单”的按钮时手一抖,点了两下,浏览器发了两个 HTTP 请求,结果是什么?创建了两条一模一样的订单。这样肯定不行,需要做防重。
    • 解决办法是,让你的订单服务具备幂等性
      • 什么是幂等呢?一个幂等操作的特点是,其任意多次执行所产生的影响均与一次执行的影响相同。
      • 也就是说,一个幂等的方法,使用同样的参数,对它进行调用多次和调用一次,对系统产生的影响是一样的。
    • 我们可以利用数据库的“主键唯一约束”特性,在插入数据的时候带上主键,来解决创建订单服务的幂等性问题。
      在这里插入图片描述
    • 如果是因为重复订单导致插入订单表失败,订单服务不要把这个错误返回给前端页面。
      • 否则,就有可能出现这样的情况:用户点击创建订单按钮后,页面提示创建订单失败,而实际上订单却创建成功了。
      • 正确的做法是,遇到这种情况,订单服务直接返回订单创建成功就可以了。

如何解决 ABA 问题?

  • 订单系统各种更新订单的服务一样也要具备幂等性。
    • 这些更新订单服务,比如说支付、发货等等这些步骤中的更新订单操作,最终落到订单库上,都是对订单主表的 UPDATE 操作。
    • 数据库的更新操作,本身就具备天然的幂等性,比如说你把订单状态,从未支付更新成已支付,执行一次和重复执行多次,订单状态都是已支付,不用我们做任何额外的逻辑,这就是天然幂等。
    • 那在实现这些更新订单服务时,还有什么问题需要特别注意的吗?还真有,在并发环境下,你需要注意 ABA 问题。
      在这里插入图片描述
  • ABA 问题怎么解决?
    • 这里给你提供一个比较通用的解决方法。
    • 给你的订单主表增加一列,列名可以叫 version,也即是“版本号”的意思。
    • 每次查询订单的时候,版本号需要随着订单数据返回给页面。
      • 页面在更新数据的请求中,需要把这个版本号作为更新请求的参数,再带回给订单更新服务。
      • 订单服务在更新数据的时候,需要比较订单当前数据的版本号,是否和消息中的版本号一致,如果不一致就拒绝更新数据。
      • 如果版本号一致,还需要再更新数据的同时,把版本号 +1。
    • “比较版本号、更新数据和版本号 +1”,这个过程必须在同一个事务里面执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值