文 / 极氪汽车APP技术团队
背景介绍
极氪汽车是吉利控股集团旗下高端纯电汽车新品牌,是以智能化、数字化、数据驱动的智能出行科技公司,秉承用户型企业理念,聚焦智能电动出行前瞻技术的研发,构建科技生态圈与用户生态圈,以“共创极致体验的出行生活”为使命,从产品创新、用户体验创新到商业模式创新,致力于为用户带来极致的出行体验。
极氪APP是极氪与用户建立连接的重要桥梁,极氪APP不仅提供买车、用车的基本服务,还推出线上社区、订阅出行、好物商城、极氪生活等多元化创新业务,实现了极氪产品的全生命周期管理以及用户旅程全场景覆盖。
随着极氪汽车销量的节节攀升,新车型发布的频次加快,极氪APP的基础架构面临着巨大挑战。为了更好的服务客户,极氪积极拥抱云原生技术,充分利用云的能力加速基础架构升级。容器化、微服务的改造大大提升了业务迭代效率。在此次数智化改造的过程中,阿里云瑶池旗下的云原生数据库PolarDB分布式版(PolarDB for Xscale)凭借一体化的分布式架构,在业务扩展性、支持水平拆分方面发挥着重要作用。
会员终端面临的挑战
▶︎更强的平台扩展性
随着极氪汽车在销售市场的热卖,一台车的卖出意味着会员数的增加,带来的数据量、访问量也在指数增长,经估算,预计未来3年内,极氪手机终端会员数据量将突破20T。同时APP中涉及的远程控车、在线地图、3C商城等与其他互联网行业类似,也会面临流量洪峰的困扰,在遇到旺季销售活动、新车型发布、突发热点事件等情况,APP面临着高并发大流量压力,传统的集中式的业务设计与存储方案已无法满足业务需求。
▶︎ 更高的开发效率
终端的用户数在增加,同时终端覆盖的使用场景也在不断增加,越来越多的功能等待发布上线,对迭代频率的要求越来越高,但由于APP服务端缺少全链路灰度发布能力,为了保障业务稳定性,每次发布只能选择在凌晨的业务低峰期进行,开发、运维、测试同学苦不堪言,急需实现随时发版无损发布能力。
▶︎ 数据一致性保证
作为会员终端APP来说,社区、咨询等传统社交内容已不足以满足个性化需求,在终端APP中加入定制化场景也是提高用户粘性、增加用户活跃度的一种形式。比如极氪为会员设计的“极分”机制,会员可以通过各种途径获得“极分”,“极分”又可以在极氪商城中直接抵扣现金消费,对用户来说“极分”就是实实在在的资产。为了管理好这些资产数据,对终端APP的交易一致性提出了要求。
▶︎ 更稳定性的平台
终端APP作为直接面向用户的窗口,它的稳定性直接影响着品牌口碑。一旦终端APP出现故障长时间不可用,不仅影响了企业品牌形象,更有可能成为社交媒体的舆论焦点,对企业口碑是致命打击。业务快速迭代、数据量指数增长,都在对整个系统的稳定性提出更高的要求。
会员终端的架构组件
会员终端APP目前已经完成了云原生架构升级,以阿里云为IaaS平台为底座,向下封装了30+款云产品,形成了自动化运维和云平台交互的新界面。容器化、微服务化的改造也大大提升了APP的灵活性和开发运维效率。
APP支撑了官网、iOS、安卓、鸿蒙、小程序等多种类型终端的接入, 网关由mPaas接入到slb透传至微服务网关,API Gateway与集成网关负责第三方系统集成。在服务中台提供基本的会员服务同时又可与外部业务集成提供多样增值服务。底层存储按数据结构的不同由不同引擎进行支撑,关系型数据主要以MySQL和PolarDB分布式版为主。
数据库对架构的支撑
极氪APP不仅提供了基本的买车、用车服务,还额外提供了诸如社区、在线商城、会员权益、极氪小游戏等增值服务,APP所关联的数据类型丰富多样,背后支撑的数据库产品也相当丰富,包含MySQL、Redis、HBase、MongoDB等。一些非关系型数据如论坛帖、点赞、关注都存储在HBase上,MongoDB则主要用于支撑极氪小游戏等文档数据。HBase、MongoDB都已经是分布式架构,然而我们最核心的关系型数据如订单、会员消费、极分体系,却还在用集中式数据库MySQL来支持。在追求扩展性、开发效率的今天,这的的确确是需要改变的一点。于是,借助极氪云原生改造契机,我们在关系型数据库层面进行了分布式探索,锁定的产品就是PolarDB分布式版。
PolarDB分布式版如何解决我们的问题
分区模式AUTO
最初吸引我们,让我们彻底放弃分库分表方案的便是PolarDB for Xscale 2.0版的分区模式,官网叫AUTO模式。极氪APP中不同模块数据增长幅度是有区别的。即便是同一个业务模块下,不同的功能表对存储和访问的需求也是不一样的。分库分表的方案容易限制设计上的灵活性,为了满足未来的扩展性,需要在前期做些冗余设计。这并不符合我们对扩展性、弹性的理解。
以极分系统为例,极分系统里包括了用户权益、极分发放与消费以及极致体系(会员、勋章、等级等)。极分的发放和消费无遗是数据量最大的部分,需要记录每位会员的极分从哪里来、消费到哪里去,会员何时何地从哪个渠道获得极分,又在何时何地通过哪个渠道消费了极分,消费的极分还要按获取顺序做到顺序消费。整条链路数据都要求清晰保存。这些数据正在以日增10GB的速度增长,在这同一个模块里,极分的明细数据肯定是远大于发放跟消费,所以我们为不同的表设计了不同的拆分细度。未来随着业务的发展,我们可以按表为单位进行扩展。
另外还有一部分业务数据,比如会员勋章、消费渠道等这部分数据跟会员增长关系不大,属于相对静态数据,本身也不具备分布式的需求,我们将其以单表形式存储。
全局二级索引
表按不同维度查询,是业务最基本的诉求,和大部分的分布式数据库一样,最佳实践经验会建议我们在SQL中带上拆分键,这给一些场景造成了困扰:比如消费明细场景中,早期为了设计简单我们使用了自增列位主键,好处是当迁往分布式数据库时,不用担心数据倾斜,但带来另一个问题,比如在查询极分消费明细的场景中,自增列并没有意义,用户ID才是我们所需要的信息。
虽然SQL中不带拆分键,PolarDB分布式版本也都是支持的,但我们担心业务规模增长后,同一时间需要查询的并发增加,手机端的反馈会明显下降。阿里云的同学推荐了全局二级索引能力,原理上他会帮我们构建一个独立的索引表,将我们需要查询维度的数据通通存在索引表上,这些数据已我们需要的维度进行拆分,当我们需要通过用户ID进行查询时,数据库自己帮我们从索引表上获取数据。不仅保障了非拆分键查询的RT和扩展性,整个过程对我们业务侧完全透明,就像用单机数据库的索引一样去使用就可以。
MySQL兼容之Sequence
按照运维的规定,每张表都需要有主键,当我们表遇到设计不出主键的时候,我们会用自增列来替代,这习惯应该和大部分企业一样。在绝大部分场景下,它并没有实质的业务意义。但在某些场景下有它的功能,在极分消费场景中,当用户消费一定金额的极分时,我们需要按极分的获取顺序进行抵扣,先获取的极分先消费。大部分渠道都是通过获取时间来解决,但我们也担心有部分渠道可能还在依赖自增列的取值来判断极分的先后顺序。排查和修改都会带来额外的工作量,所幸PolarDB分布式版提供了New Sequene的能力,它可以像单机数据库一样,不仅能提供分布式性能,同时还保证了连续且递增,并且使用接口也和单机保持一致,在同类产品中着实罕见,帮我们排除掉业务上最后一个顾虑。据阿里云同学介绍,目前New sequence已经是PolarDB分布式版默认的能力,不需要额外配置,对业务完全透明。
广播表
切换到分布式数据库时,我们另一个担心的问题是关联查询,数据被打散到不同节点上之后,表之间的Join是否会受到限制。在极氪APP场景里,每个模块之间相对独立,基本不会出现太复杂的大表和大表之间的关联,更常见的是同一个模块内,大表和小表的关联,比如勋章查询、渠道明细查询等都是典型的分区表和单表的关联查询:
一开始压测时,性能是很差的,通过执行计划可以看到,这条SQL是medal跟medal_content两张小表做关联后,再从medal_flow分区表内取出相应数据在CN层做Hash Join,链路太长,性能太差。
经过阿里云同学建议,我们将两张小表调整为广播表之后,执行计划发生了很大的变化,直接在底层DN就完成了关联操作,链路变短,性能提升数倍。
PolarDB分布式版的适配过程
schema设计
从单机往分布式的跨越,第一大问题就是schema的设计,需要定义数据的拆分,是水平拆分还是垂直拆,哪些表需要拆,以什么维度拆,这都是需要预先考虑的问题。在迁移初期,我们与阿里云同学进行沟通后,大体拟定了如下几条原则:
● 数据量超过500万的,进行数据拆分(与公司具体情况有关,数值仅做参考);
● 拆分维度优先主键,没主键的表,选择区分度最高的列进行拆分;
● 设计阶段,不设计任何全局二级索引,后续根据压测再进行调整;
● 其他表全部建成单表,是否采用广播表,后续根据压测再进行调整。
联调压测
功能联调是相对顺利的,PolarDB分布式版跟MySQL高度兼容,整个过程业务侧代码是保持不变的,仅在数据库侧进行了优化调整,借助这种高兼容性,我们从测试到最终上线,仅耗时3周,技术团队工期缩短至平时的1/3。
压测阶段是整个环节中最重要的一环,一直以来我们都缺少有效的业务压测手段,在这次云原生数字化改造中,很多能力也还在建设当中,暂时我们也不具备全量压测能力。阿里云数据库推荐了智能压测的解决方案CMH-DOA(也称frodo),CMH-DOA可以全量录制原生产端MySQL的全量SQL,在目标端PolarDB分布式版进行完整回放。同时也支持倍速回放,回放完成后提供评估报告,内容包含SQL的执行次数、成功次数、失败率和模板化后SQL的数量、成功率、平均RT,以及分段RT统计等内容,让我们对当前规格的实例能承载多大的业务流量有非常好的判断依据,帮助我们提前发现问题,降低了割接上线的风险。
生产割接
结合我们割接窗口期和实际情况,我们与阿里云团队共同设计了完整的割接方案。割接当晚我们从停业务、数据检查,业务校验、业务切流上线整套动作30分钟内全部完成。为了保证核心,我们也设计了回退方案。在业务正式上线之前,我们建了一条回流链路从PolarDB分布式版到MySQL,一旦出现不可预期的问题,可以立刻将业务回退回MySQL。
数据迁移以及回退方案都以DTS产品为主,DTS是阿里云瑶池数据库自研的数据传输服务,支持多种异构数据库之间的数据同步、数据订阅、数据迁移。它是集结构迁移、全量同步、增量同步与一体的传输传输服务,同时还支持数据校验,断点续传等高可靠能力。
极氪APP经历了云原生架构的探索升级,数据库也经历了集中式往分布式的演进,阿里云瑶池旗下的云原生数据库PolarDB分布式版彻底打消了我们对业务扩展性的顾虑,帮助我们提高了业务的稳定性和敏捷性,让我们更专注于客户体验和客户服务。我们相信这仅仅是探索的开始,随着云原生架构的深入,业务的可用性将持续增强,PolarDB分布式版将在新能源汽车行业的to C业务端发挥更加重要的作用。