首页 运维干货双十一谈如何从零开始搭建大型机票交易平台

双十一谈如何从零开始搭建大型机票交易平台

运维派隶属马哥教育旗下专业运维社区,是国内成立最早的IT运维技术社区,欢迎关注公众号:yunweipai
领取学习更多免费Linux云计算、Python、Docker、K8s教程关注公众号:马哥linux运维

导读:从无到有构建一个大型交易平台对工程师来说是很有挑战的事情。在构建过程中会碰见各种技术或者非技术的问题,作为一个工程师又该如何处理这些问题,这是所有工程师都需要考虑的问题。知名旅游网站负责交易平台技术的小雄哥总结了自己的亲身经历,通过在高可用架构群的分享,给出了他自己的答案。

高可用架构读者大家好,先做下简单的自我介绍,我叫小雄哥,国内某大型旅游网站的开发工程师,主要负责的是交易平台的技术开发和管理。

背景介绍

进公司的原因是被同学和其他高管同事拉过来凑局,成立孵化平台,当时正好缺少个技术负责搭平台,所以合伙人都是有目的性的,这点很重要。

当时的市场,仅有一个类似的对手,而我们的实力,没有技术平台,没有落地的需求,只有对机票事业部领导的承诺、模糊的想法IDEA,1个开发1个产品1个商务。

所以,大家首要目标就是:招开发、测试、商务、产品,快速落地。自然,我的任务就是:招人提升战斗力、学习业务、验证和实现idea系统落地。

所以本次分享大部分是基于这三点。

开发组织

开发组织的情况

开发组织情况

公司文化很重要,很重要,很重要。

业务负责人从内部借到异地的开发:1 个做过两年机票的,1 个酒店的,有幸得此两人帮我快速了解公司内部的技术平台。

之后,跟商务跑了家合作伙伴的公司,借到了 6 个 .net 的开发,其中 5 个人转做 Java,1 个人转去做产品,期间的借人过往就不描述了,很坎坷,非常感谢当时各位,大老远过来参与封闭开发。基本上大家都拧在了一起,这样开发资源不足的问题大致解决了,当然成本管理是公司领导考虑,这里就不细说明。

但是新问题来了,产品只有想法没出 PRD,开发这边:语言不一致,水平不一(产品和开发不具备 B 端经验)、技术团队落户深圳,人员稳定性隐患较大,人员投入困难,沟通不畅,向心力不足。

优先解决能力提升的问题,结合上图是解决的办法,是个循环渐进的过程,要坚持。

既然要做到坚持,就需要有约束有限制,以下是大家的约定。

开发组织约束

以上内容是组织管理的大部分内容。

下边就是时间管理部分:

时间管理

结合产品的想法,列出所有模块的泳道图、流程图,核对每一个状态机和操作的前驱后即。

进度汇报方面,采用的是每日晨会白板,每日早晚进度反馈群内分享,颜色标记进度等等方法。

对于预估错误和延期的处理方案是:小黑屋加班。回忆起来,上线前的几个月是没有周末的……

需求分析阶段

由于前期产品能力不足、给出好几十页的 PRD 和页面原型非常不好理解的前提下,帮助产品梳理需求,给出良好、干净的建议,也成功前期需求分解的重要工作,因为要确立开发方向,结果变成了现在的较为合理的样子。

PRD 和原型转换成流程图:

PRD和原型转换成流程图

原型转换成流程图 原型转换成流程图

转换成:

状态机

等等类似各图。模块流程的原型完了,进入状态机:

时序图

状态机是采用无向图的数据结构,根据交易流和状态流向的模拟,给予产品 case 或形态有个很好的回归。

还有我们开发最熟悉的,时序图输出:

核心模块流图

抱着这样探索摸透的态度,我们开发梳理了这些,是为了保证模块负责人都能事前知道流程和技术功能。根据这样具体的PRD,大家均能很大的明白业务到底要做什么,流程是什么。

当然弄了这么多,缺点也很明显,就是时间长了,重构多了,这些图和表需要人维护。

推荐大家选择时序图,首先描述对象之间发送消息的时间顺序显示多个对象之间的动态协作。它可以表示用例的行为顺序,当执行一个用例行为时,时序图中的每条消息对应了一个类操作或状态机中引起转换的触发事件。

下面介绍,各大核心模块流图:

我用字母和数字的组合,代表了当时上线的路径。

上线的路径

上线路径

约票,最简单的模块,为什么要拿出来,因为当时我们的思路是跟滴滴打车学的,有采购叫单,供应来应。

类似各模块的流图都要在前期需求分析阶段出来,且模块负责人和对应开发都要熟知。

下面介绍,数据建模:

数据建模

有了这样结构的好处:

  • 结合状态机和操作,再根据交易流和数据流向的模拟,给予产品形态更好的回归,确保业务上无阻塞问题
  • 各模块互不干涉,从事务上给予更好的保证。

从数据量上,要有足够的分析,预估上线的一个月内,日票量 1500 左右 即:15 * 7875 = 118125 条(数据库记录)。

产生一条主单订单时,会增加:1 条订单记录,5 条工单,20 条工单回复,10 条状态变更,5 条支付和解冻记录,4 条航班,9 条乘机人,约 45 条左右。.

与主订单同比,子单约 40 条左右。每百主订单会产生 5% 售后子单,即百条订单 = 105 * 45 = 4725 (数据库记录) 。假定按出票率 60% 计算的话,百张票记录 = 4725 / 0.6 = 7875,可保证 5 – 6 年的 150% 增长。

根据这个实际的业务量级考虑,所以我只做了分库没有分表。

以上的内容是是需求分析阶段,大概两周左右。

架构设计阶段

到这个阶段的时候,要分析要做的这个平台的愿景是什么?这里要结合公司对 B 端平台的期望,最后重点是稳定、可靠、安全、灵活。

架构设计阶段

由于发现有个老的运行比较久的政策管理和搜索模块可以“借”来重构,那么只需要考虑的其他几个模块了,售前、售后、工单、运营平台等。

找其他技术同学讨论几轮后,结合平台期望,也最终确定了系统结构是怎样的。

系统结构

因业务情况稍微解释下,上边的深蓝色是入口和出口,左边的黑色是公共技术,采用 dubbo 的 RPC(此处有坑),DAO 用的是 MyBatis,绿色部分代表其他部门提供支持。

这个系统结构,也是结合平台期望来的,这个完了就要考虑工程结构了。

工程结构

从上到下,从左到右。采用复用的设计模式,个人认为较为合理的工程结构,也是目前我们工程制定的迭代任务制定的。

整体上完事了,下面到各模块的了,由于是业务独特性,这里插播下机票内部的业务流程。

先有供应商录入航线和价格的东西,业内叫政策,录入完了,采购商就能搜索到,选择适合的下单,支付和出票,这是售前,采购商拿到供应商提供的票号就可以让 C 端用户去做飞机了。

售后,就是退改签、工单等,也是各大平台的收入来源,与本次分享无关,不细说了。

机票搜索

下面介绍,搜索报价结构类图:

报价结构类图

简单描述上图,采购商查询机票价格的条件是:出发目的地、时间之类的,业内叫 av。这部分信息通过 OMS 同步模块将从代理商录入的政策中航班等信息作为索引放到 Solr 里,匹配到了能取到政策 ID,再去 Redis 里取政策详情,找到反馈给采购商,当然其中有一些处理航司交互的东西。

生单系统

下面介绍,生单结构类图:

生单结构类图

生单结构类图

简单描述下,搜索出报价,中间有个确认过程叫核价,就是最后看看是不是机票会变价,有变价是否接受。之后就进入生单。不同平台的理解不一样,有的平台把支付之后叫生单。

由于不同航司,不同 GDS 标准,不同处理路径,所以生单流程是均不一样的。所以设计模式采用的是链式,这个比较成熟,当有新的流程,只需要在绿色加上对应的 handler,写逻辑添加到 BizHandleBuilder 里,做好规则即可,结合图二进行理解。

支付系统

下面介绍,另外一个核心模块,支付类图:

支付类图

简单描述下,生单之后,采购和供应都觉得 ok,采购商要支付。

B 端系统一般要支持这么几个功能:支持二次或改签支付、灵活处理各种错误、支持中断支付、继续支付机制、明细查看和导出、管理员权限支付、用户级别锁定、支持作废正在支付中单子、营收和立减、财付通支付宝三方等。

要消化这些功能,所以要设计出:便于扩展,继承指令参数拼接类,添加支付类型等抽象思想:

我这边设计,采用蓝色模块表示将支付流程统一处理,绿色代表指令执行拼接流程统一处理,橘黄色表示扩展部分,一般都是逻辑核心的地方。

比如,如果订单要支持三次支付,那么就可以多了一个 OrderThirdPayService。比如有个支付接口要适配,就要做个新的 XXX 实现指令拼接流程管理就好。

这里给公司的支付中心点个赞,无论多晚,他们都有人都在陪着联调。

以上列举了两、三个核心模块介绍,其他核心模块都类似设计。

模块设计的原则

简约的理解,模块设计是要求这样的,遵循依赖倒置单一原则。

模块设计原则

至少三层结构,遵循依赖倒置,且实现 service 都有各种方法提供,这也是给合作方很好的支持,想有各种方法都有。缺点是代码冗余。

异步化设计

下面就是边边角角的了,异步化的设计:

异步化设计

自己写的,很基础的,原因是为了都能看懂,也方便扩展,仍然是橘黄色的部分,随便一个开发扩展使用都可以。当然是业务不出错,对于难以保证数据的准确性,安全性不高,上下文 context switch 开销,占用本地还更多的资源等缺点,不 care。只要可以并列处理一些工作,从而减少一些不必要的等待时间,从能灵活满足业务需要就行。

关于其他的架构设计,统一处理要求:

架构设计

简单描述下说明下,因为是第一版,而且人员技术水平不太高的情况,所以,很多处理都是秉着简易、好懂出发的。

  • 接口设计:这里也考虑了复用机制,比如:订单搜索和订单导出,都是根据条件查询给出结果的。利用了OOP根据不同订单类型,来走不同路径。
  • 依赖倒置:接口高层次的模块不依赖于低层次的模块实现。
  • 事务回滚: Service和Dao之间加一层 daohandle @Transactional xxxDaoHandle,这里很有学问,由于表设计的很散,所以在这里遇到很多问题。
  • 文件存储处理:比较好用的是因为路径、文件夹可配,听说 FastHFS 也不错,也打算后续对比下。
  • 本地缓存:采用 CacheBuilder 限制队列,减低 Redis 压力,响应时间优于 Redis。有过期时间。

按照这个架构设计,我们实现大概 2 个月左右的时间。

发布之后

按照以上的需求和架构发布后,基本上较稳定成长,期间也有外界的冲击着,比如:孵化项目不被看好,中途人员流失,市场变动需要调整优先级,公司整合等等问题,总之,你是负责人,问题抗住并要处理它。

希望这份分享能对大家有所帮助,如有问题可以在本文留言,也可以加讲师微信 cpp_wazi 继续交流。

文章出处:高可用架构(订阅号ID:ArchNotes)

高可用架构

本文链接:https://www.yunweipai.com/10146.html

网友评论comments

发表回复

您的电子邮箱地址不会被公开。

暂无评论

Copyright © 2012-2022 YUNWEIPAI.COM - 运维派 京ICP备16064699号-6
扫二维码
扫二维码
返回顶部