文章目录
一、方案背景
订单系统是存在于各行各业的一个很基础、核心的业务系统。随着互联网的发展,订单系统的管理方案也在不断变化,订单数据规模的膨胀、用户对数据的重视,以及新的技术等都会影响订单管理方案。
1.1 考虑因素
-
数据量: 订单的特点是只增不减,随着时间推移,订单量会越来越多;
-
多维查询分析: 能够灵活的支持不同角色用户多种维护的查询和分析;
-
性能: 订单管理服务需要只能高并发、低延迟;
1.2 数据特点
订单数据具有明显的时间属性,主要呈现出两个特点:
- 特点1:时间越久的订单被访问到的概率越低;
- 特点2:订单规模随着时间推移不断变大,GB、TB,甚至PB等;
二、方案演进
技术架构不是设计出来的,是演化出来的。订单管理方案也是随着业务和技术的发展,不断演化的,如下图所示。按照技术架构特点,大致分为三类:
- MySQL架构:通过扩展库表数量来提升读写能力和存储容量;
- MySQL + NoSQL架构:MySQL提供事务能力,NoSQL保障海量数据的存储和多维查询分析能力;
- NewSQL架构:期待成熟的产品出现,兼容MySQL、NoSQL二者优势;
说明: 订单是个性化的数据,每个用户的订单数据都不同,不适合使用缓存;
三、MySQL架构
3.1 单库单表
最简单的订单管理方案,适用于创业初期,便于商业模型的快速落地验证;
3.2 读写分离
解决问题: 单库性能达到极限,成为系统性能瓶颈点;
核心思想:增加从库,单点写入,多点读取(提升读性能)。目前主流方案都是走代理,比如阿里云的RDS,因为对用户完全透明,主从复制、主从切换,以及读写分离等工作由DBA来维护,如下图所示:
主从同步延时问题: 正常情况下,主从同步延时都是在1ms以内。但是,当网络抖动或者数据库负载过高时,主从延时可能会变大,导致主从数据出现暂时不一致的情况。这种问题有三种解决方案:
- 忽略。如果业务可接受暂时的延时,则直接忽略;
- 产品流程上规避,尽量避免写操作后立即查询最新数据的情况。比如,订单支付完成后,会跳出支付成功页,而不是自动跳转到订单页;
- 强制读主库。
3.3 垂直拆分
随着业务发展,订单表字段越来越多,职责不清晰,维护麻烦。将相同功能的字段为一组进行拆分,职责清晰,容易维护和扩展。
3.4 数据归档/冷热分离
解决问题: 单库数据量过多导致读写性能下降(RT变高);
核心思想:利用订单“长尾效应”的特点,将历史数据迁移到其它库(冷库),为热库瘦身,从而提升性能,如下图所示:
注意点:
- 不要一次性删除大量数据(大事务,容易造成卡顿),建议按照主键顺序分批次批量删除;
- 这种方案需要产品设计上区分历史数据,比如前几年淘宝的“三个月前订单”选项;
3.5 分库分表
解决问题: 支持更高的并发量和数据量,解决单库性能和数据量的瓶颈;
核心思想: 数据分片,关键是分片key和分片算法。目前主流的方案有两种:路由表和哈希。
方案1:路由表
路由表存储key与数据存储位置的映射关系, 每次查询数据时,先查询路由表获取数据位置,然后再查询数据,如下图所示。
- 优点:分片灵活,可随意更改。比如,当出现热点分片时只需要更新路由表重新分片,当需要扩容时只需要增加路由信息。
- 缺点:路由表为单表,且需要二次查询。
方案2:哈希
哈希算法本身很简单,在订单场景下需要考虑的是,分库分表的key是什么,如何同时满足用户侧和商家侧的查询需求。比如,如果按照订单id分库分表,用户的订单列表和商家的订单列表则需要全表扫描,用户id和商家id也是同理。
整体思路: 订单数据一式两份,分为用户库和商家库(只读)。对于用户库,按照订单id分库分表,用户id的某几位信息加入到订单id中(“因子分表法”,见订单号设计),同时满足用户id和订单id维度的查询;对于商家库,按照商家id对订单重哈希路由,如下图所示:
-
建立单独的商家库,是为了物理上隔离商户查询对用户的影响;
-
商家库只读是为了单点写入,方便维护数据的一致性;
-
如果允许商家订单数据,则商家库只维护商家与订单的映射关系(路由表);
容量评估 -
分库数量 = 峰值并发量 / 单库的IOPS;
-
分表数量 = 数据量 / 单表容量(阿里Java开发规范的建议值:单表行数超过 500 万行或者单表容量超过 2GB);
四、MySQL + NoSQL架构
4.1 MySQL + ES
解决问题: 分库分表的查询能力有限,无法支持复杂灵活的查询;
核心思想: 引入ES,建立热点查询到订单ID的映射关系,用于支持复杂的查询条件。复杂查询通过ES获取对应的订单ID,再从数据库从库查询获得订单,如下图所示:
注意点
- 不要将订单及其扩展字段全量同步到ES,会影响检索效率,只同步有强搜索需求的字段;
- 建议将订单及其关联表聚合成一张宽表,提升ES查询时的效率;
4.2 MySQL + ES + HBase
解决问题: 解决订单详情查询时间长问题(需要去订单表及其关联表多次查询);
核心思想: 引入HBase,将订单及其关联表全量字段导入HBase,RowKey为订单id,如下图所示:
五、未来预期: NewSQL
当前关系型数据库仍是主流的原因就在于其事务特性,NoSQL由于其高性能、高扩展和高存储量特性,成了目前技术方案的标配之一,以上所有的订单存储方案归纳起来就是MySQL + NoSQL的组合,未来NewSQL如果真正的能做到NewSQL = MySQL + NoSQL,订单的管理方案势必会被极大的简化,期待。
参考