业务背景
随着国际火车票业务的高速发展,订单量快速增长,单数据库瓶颈层面的问题逐渐显露,常规的数据库优化已无法达到期望的效果。同时,原先的底层数据库设计,也存在一些历史遗留问题,比如存在部分无用字段、表通过自增主键关联和各个应用直连数据库等问题。
为此,经过讨论后,我们决定对订单库进行分库分表,同时对订单表进行重构,进而从根本上解决这些问题。
业务挑战
目标确定后,实践起来可不轻松,出现了很多的问题和挑战。这里列举一些典型问题,大致可以分为两大类:分库分表通用问题、具体业务关联问题。
分库分表通用问题
- 如何切分,垂直分还是水平分?分片的键,如何选取?
- 如何根据键值路由到对应库、对应表?
- 采用什么中间件,代理方式还是中间件的方式?
- 跨库操作等问题,如跨库事务和跨库关联?
- 数据扩容问题,后续如何进行扩容?
具体业务关联问题
- 各个应用直连数据如何解决?
- 如何进行平滑过渡?
- 历史数据如何恰当迁移?
方案选型
如何切分
切分方式,一般分为垂直分库、垂直分表、水平分库和水平分表四种,如何选择,一般是根据自己的业务需求决定。
我们的目标是要从根本上解决数据量大、单机性能问题等问题,垂直方式并不能满足需求,所以我们选取了水平分库+水平分表的切分方式。
分片键选取
一般是根据自己的实际业务,来选择字段来作为分片的键,同时可以结合考虑数据的热点问题 、分布问题。比如订单系统,不能根据国家字段进行分片,否则可能会出现某些国家很多的订单记录,某些国家几乎没有订单记录,进而数据分布不均。相对正确的方式,比如订单类系统,可以选择订单 ID;会员系统,可以选择会员 ID。
如何路由
选定了分片的键之后,接下来需要探讨的问题,就是如何路由到具体的数据库和具体的表。
- 映射路由
- 分组路由
- 哈希路由
- 分组哈希路由
在实践中,我们结合了前面的几种方式,借鉴了他们的优点不足,而采用了此种方式。因为分组方式,能很方便的进行扩容,解决了数据扩容问题;哈希方式,能解决分布相对均匀,无单点数据库热点问题。
选择 Apache ShardingSphere 的理由
在产品选型过程中,考虑了多款产品,也包括公司自己实现的产品,最终选择了 ShardingSphere,理由如下。
技术环境
- 我们团队是 Java 体系下的,对 Java 中间件有一些偏爱
- 更偏向于轻量级组件,可以深入研究的组件
- 可能会需要一些个性定制化
专业程度
- 取决于中间件由哪个团队进行维护,是否是名师打造,是否是行业标杆
- 更新迭代频率,最好是更新相对频繁,维护较积极的
- 流行度问题,偏向于流行度广、社区活跃的中间件
- 性能问题,性能能满足我们的要求
使用成本
- 学习成本、入门成本和定制改造成本
- 弱浸入性,对业务能较少浸入
- 现有技术栈下的迁移成本,我们当前技术栈是 SSM 体系下
运维成本
- 高可用、高稳定性
- 减少硬件资源,不希望再单独引入一个代理中间件,还要考虑运维成本
- 丰富的埋点、完善的监控