架构-订单系统设计


订单系统设计


幂等

一件事情做几次结果都一样(防止用户提交两次订单)
唯一性索引:生成订单ID的操作提前到核对订单页面并在页面携带此ID,提交订单时直接使用此ID

ABA问题(使用版本号):
如用户修改订单详情,物品颜色(更新订单信息的ABA问题):

  • 红色,修改成功,网络响应失败(触发重试)
  • 绿色,用户修改成功
  • 红色,重试成功
    用户想要的是第二次修改的绿色,最后结果确是红色

使用版本号解决这个问题:update db时检查 version 有没有发生变化

读写分离

我的订单中,每个用户的订单都不同,所以不能用 redis 缓存数据,只能用读写分离优化查询速度
存在主从同步时数据暂时的不一致情况,可以插入支付成功页面,几秒后跳转详情页面,然后从读库查询
在要求较高的业务场景下可以在同一事务中,在写库写完就在写库读然后返回给前端

分库分表

能少拆就少拆,能不拆就不拆,降低维护复杂度
在MySQL中,如果一行存1kb的数据,那么一张表可以在不影响性能的情况下,大概存储2100条数据

数据量大:分表
并发量大:分库

分表分片策略

按时间或按ID取模等

  • 根据orderid mod缺陷:无法根据userid查询该用户下的所有订单
    • 解决方案:根据 orderid 和 userid 后几位拼接一个新的 orderid(基因法),然后 mod 取模
      • 缺陷:无法根据店铺ID查询该店铺下的所有订单
        • 解决方案 - 数据冗余:订单数据同步到其他存储,比如ES,Hadoop或MySQL(以店铺ID作为分片键的只读订单库)等

实现方案

  • Sharding-JDBC(推荐使用)
  • 代理方式(MyCat,好久不更新了):使用起来最简单
    • 缺陷:性能损失较大,需要两次请求
  • 历史订单归档(数据迁移,根据热尾效应,只保留近3个月的数据,提高提高表的查询速度)
    • 定时任务:MySQL -> MongoDB
      • 循环批量插入(mysql delete,mongodb insert)
      • 数据库负载很大,MySQL可以按ID范围删除(每次2000条),每次循环休眠一个随机数,让MySQL完成页面合并,降低负载
      • 碎片优化负载很大,建议晚上迁移,一晚上迁移不完,可以暂停,第二天晚上继续迁移
      • 迁移前做好备份
    • 数据一致性:需要事务,但不需要分布式事务
      • 获取上一次成功的最大ID,以它为起始ID:只需保证某一边有数据就可以

文章作者: 钱不寒
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 钱不寒 !
  目录