本文根据 Akulaku 算法总监马宇翔在「OpenMLDB Meetup No.1」中的演讲整理而成。

Akulaku 介绍

关于 Akulaku

Akulaku 公司成立于 2016 年,是一家专注于东南亚市场的金融科技公司。金融科技公司的显著特点,就是所有的业务都和钱直接相关。

Akulaku 的业务场景

从业务场景的角度,团队首先从类似于花呗的场景切入,随着业务逐渐壮大,开始涉足虚拟信用卡业务,目前 Akulaku 拥有商业银行以及理财投资业务,所有业务均涉及庞大的交易量。

科技助力业务快速发展

不断增长的用户量和交易量给风控系统带来极大的压力,团队首先需要保障公司风控的高水平状态,而这主要依赖于机器学习、CV、NLP、Graph 等人工智能技术,同时利用收集到的庞大数据量,推动业务发展。

以上是 Akulaku 业务场景的大致介绍,如果是业界同行,目前应该已经能理解 Akulaku 为什么会非常迅速的上手 OpenMLDB 了。

机器学习技术栈

下图是 Akulaku 当前的技术栈,目前技术栈的每一层均独立规划。

  • 场景层:涉及 CV、NLP、Speech、图挖掘、AutoML 等各类算法,用于解决诸多业务场景所面临的问题,同时开发各类模型用于填补可能出现的各种风险漏洞
  • 平台层:各个环节中,数据处理占据 80% 以上的资源和耗时,服务层和算法库基本采用业界主流解决方案。

初识 OpenMLDB

结识 OpenMLDB 的经历

第一次接触 OpenMLDB,是 2021 年 4 月份,彼时正在探索 Spark 的优化问题,了解到 OpenMLDB 离线计算的前身 Spark 发行版。6 月份参加第四范式的技术发布会,了解到 OpenMLDB,发现它正好切中了 Akulaku 的一个业务痛点。基于这个痛点,我开始研究 OpenMLDB 的源码。过往尝试过阿里的闭源流批一体实时数仓解决方案,但因其闭源,且主要服务于阿里内部业务的原因,特性不是非常的贴合业务需求,但也无法改动。第一次遇到一个开源的一体化解决方案,我感到非常好奇,于是基于 OpenMLDB 做了特定场景的测试。8 月看到 OpenMLDB 发表于 VLDB 2021 的性能优化论文。9 月份开始使用 OpenMLDB 解决具体业务问题。12 月在一个相对比较新的场景上基于 OpenMLDB 将离线特征开发上线实时环境,开始将 OpenMLDB 应用于生产环境。

Akulaku 机器学习开发 Pipeline

下图是一个通用的 Akulaku 结构化数据建模场景,通常由原始数据、特征工程、机器学习、风控模型更新等环节构成。基于海量原始数据,根据数据的基本属性,进行人工或者自动特征工程,抽取属性、文本、时间序列等特征属性,通过超参数优化、模型选择等完成模型构建,最终实现应用上线。团队过往基于 KubeFlow 实现模型更新,但特征更新一直是机器学习开发当中最大的痛点。那么,特征更新能否单纯通过堆砌计算资源来实现呢?

  • 不限资源,就能马上算完吗?即便在不限资源的情况下,面对每天产生的 PB 级结构化数据,也难以有效的保证计算速度。
  • 算完等于算得准吗?即便能够完成计算,也无法保证计算结果的正确性。在 Akulaku 实际业务场景中,数仓和实时数据属于两套完全独立的系统,具有完全不同的结构、定义、开发工具和逻辑。在这种情况下,很难仅仅通过上百行甚至几百行的复杂 SQL 来保证两套系统计算结果一致性。
  • 公司的钱够花吗?若希望同时满足算得快以及算得准的需求,需要招聘上千人的团队、大量的专家以及庞大的机器资源投入,普通公司只能望而却步。

AI 系统本质上是一个复杂工程问题

AI 系统的构建本质上是个复杂的工程问题,绝大部分时间被用于海量数据处理以及系统搭建,机器学习模型构建甚至可以说是耗费精力最小的环节。工业界的同学,应该深有同感。

模型人生命的敌人:对数

下面这张图来源于 OpenMLDB 的产品介绍,非常好的概括出我们之前的日常工作状态。

  • 数据科学家离线开发 :AKULAKU 的数据科学家,在数据平台上利用大数据框架,通过数据仓库、数据湖做离线数据特征抽取。特征抽取出来之后,用来训练模型,定义各类 SQL。
  • 数据开发工程师上线服务 :当数据科学家完成模型效果验证之后,把定义好的特征文件交给线上的数据开发工程师。数据开发工程师使用一套保障实时性、稳定性、可用性的方式做实时特征开发,完成服务上线

两个团队使用的甚至都不是一个标准的 SQL 语句。对离线来说可能有多种实现方法,甚至直接使用原生代码。但对于线上来说,必须使用硬代码解决实时性保障问题。离线开发和线上服务存在诸多逻辑上的不一致。而这种不一致在金融行业中非常难以解决,因为我们模型的训练目标是用户的还款账单,还款账单通常以月为单位计数,这就意味着如果数据无法有效对齐,需要至少一个月的时间来判断离线和在线模型结果是否一致,而一个月的时间消耗对于我们来说是非常恐怖的成本。

因此,我们目前面临的主要问题,概况来说可以分为研发系统和团队、技术栈、实现逻辑以及效率和效果四个维度的不一致:

  • 研发系统和团队不一致。离线和在线完全是两套系统,两套不同的工具和平台,以及两类不同的使用者。线下数据挖掘主要是数据科学家依赖数据平台实现,线上特征生成主要是数据开发工程师依赖特征平台实现。
  • 技术栈不一致。离线场景主要为 MPP 场景,以 Spark 作为主力工具,同时还使用了一些实时数仓工具,例如 Hive。在线场景主要为 OLTP 场景,试过很多种方案,比如 TiDB,PolarDB,Flink 等。Flink 可能又分很多种,比如滑动时间窗口或者 CDC,每种方法也不太一样。
  • 实现逻辑不一致。离线以模型效果为目标,为保证效果会使用各种工具和语言。在线要求使用同样一个特征,由于 A 模型和 B 模型同时使用的需求较难同时满足,为了解决这个问题,需要使用统一的 SQL 描述。但是每种大数据工具对 SQL 的支持也是不一样的,底层实现也存在差异,跑出来的数据无法有效对应。
  • 效率和效果不一致。对于离线任务而言,算力和时间相对充裕,可以做比较多的深度模型或者复杂逻辑。但对于在线业务,比如下单场景的反欺诈,对于时效性、准确性、稳定性存在很高的要求。

这些不一致对于业务实现带来了很多问题,线上和线下数据对不上,轻则导致方案无法使用、效果不达标,重则造成生产事故或者严重的线上缺陷。从业务层面上,如果无法快速完成特征计算任务,导致用户需要耗费 1 分钟时间等待欺诈交易验证,将造成极大的用户流失。我们经常面临的实际状况是,花费大量时间做出一个效果极高的线下方案,但是线上无法使用。然而,如果妥协线上应用的时效和准确性,效果则会下降。最可怕的是,如果在对数环节甚至没有发现这个问题,那么上线之后肯定就是生产事故或者线上的某类问题一直得不到解决,这都是金融领域非常痛苦的点。如果每个特征都是几百行的 SQL 语句,完全无法在几天内解决。即便是保守估计,风控模型对数也往往要耗费模型开发同学接近一半以上的时间精力,甚至是以月为周期的时间消耗。

OpenMLDB 的价值

OpenMLDB 提供统一的特征开发系统、统一的技术栈、统一的逻辑实现以及统一的效率、效率

  • OpenMLDB 提供统一的特征开发系统。OpenMLDB 确实是一个以模型开发为视角的数据工具。对我们来说,特征开发使用 OpenMLDB,可以真正的实现由数据科学家来写 SQL,对数据科学家来说不会因为使用的工具性能差,或者无法满足线上要求,而导致他必须把实时特征开发工作再交接出去,避免了由两个不同团队开发所造成的不一致性。
  • OpenMLDB 提供统一的技术栈。OpenMLDB 提供了线上和线下统一的技术栈。数据科学家不需要一边学习 Spark、PolarDB,一边学习 Flink,有效降低学习的门槛和上手的难度。
  • OpenMLDB 保障一致的逻辑实现。我们测试过 OpenMLDB 每个底层执行函数跑出来的结果,是一致的。OpenMLDB 顶层的 SQL 表达,在线下改线上的时候,是一致的,只需要改一些前缀的语句。
  • OpenMLDB 提供一致的效率和效果。OpenMLDB 基本上能够保证线上执行的速度与线下计算的速度一致,不会出现很大的偏差。我们测试过线下数据计算,通过执行推到线上之后,速度基本一致。

过往使用传统的 Kafka+Flink 这套方式,线下版本和线上版本的速度并不能保证一致,万一线上出现数据突增或者内存爆炸,或者数据散压回来,计算速度会受到很大的影响。

OpenMLDB 的这些一致性能力,对我们来说具有很好的价值。

  1. 简化开发方案。Akulaku 的一些模型,开始去让算法同学直接写 SQL,直接做线上部署。
  2. 解放开发人员。因为这个优势,可以把一些开发人员解放出来,去做一些更深度的、不那么重复性的工作。
  3. 缩短迭代耗时。迭代的耗时缩短,不需要以月为单位去做模型一致性校验。
  4. 避免线上事故。基于前面三点的加持,避免了一些线上事故的发生。

成本和收益

下图是我们使用 OpenMLDB 之后成本和收益的统计。

  • 成本:年化成本 200 万左右。 目前我们在尝试使用阿里云的神龙裸金属服务器持久化内存版本,大概接近 2 万 RMB / 台 / 月,8 台机器年化成本不到 200 万。
  • 收益:节约资源保守估计 400 万以上。 从收益上来讲,使用阿里云神龙服务器持久内存版本之后,之前的一些基于时序或者是 Spark 的大数据工具集群解放了出来,大概释放出来 20 台 128G 的机器,大概也是 200 万的机器成本。另外很多算法和数据开发工程师的精力也释放出来,数据开发工程师不需要重复的去做几百个特征,算法工程师解放出来不需要参与对数。保守估计,人力加机器成本的节约在 400 万以上。

这里补充一下,8 台机器是我们目前暂时的使用量,大家还是要根据自身企业内部的数据量以及使用的场景去配置合适的资源。

业务场景应用

业务场景是我本次介绍的重点,我们做了很多场景的尝试,本次展示的是我们公司的关键业务场景,比如风控场景,以及 OpenMLDB 在实战中效果最好的几个场景,和大家分享。

场景 1:RTP 系统案例

RTP 服务是一个面向通用场景的排序服务。排序服务如果要做到通用,就会面临各类型特征的挑战。

我们之前的做法,是首先做一个原始数据的实时数仓,在实时数仓的基础上,通过独立的特征服务去做特征生成。再把生成的向量,塞到模型里,模型产出的向量或者分数再放到纯粹的排序机制里,就是我们之前的排序系统。

这套系统存在一些问题,首先各个组件的切分会比较明显,切分明显的好处,比如解耦。但是排序系统的关键是速度优先,如果所有功能都是为最终结果垂直服务的话,那么我们会倾向于做一个内聚化的事情。

在这个场景上我们使用 OpenMLDB,从 Kafka 把数据写过来之后,直接在 OpenMLDB 里面做特征生成以及最后的排序,下图为使用之后的性能。

从性能的角度,将 OpenMLDB、MPP 方案及 Flink 方案进行比较。每次 TopK 的查询都有实时的数据涌进来。对应的 MPP 方案存在的问题,每进入一条数据就需要完成一次全量的计算,导致耗时非常恐怖。而 Flink 的时间窗口方案,性能是非常优秀的,但毕竟不是一个做 TopK 排序的工具。而从柱状图可以看到,OpenMLDB 的效果几乎是线性的。

  • 在 Top1 的查询中,OpenMLDB 的查询速度仅为个位数,这里是 9.8 毫秒。
  • 在 Top8 的查询中,Flink 能够实现不到 100 毫秒的性能,而 OpenMLDB 此时还是线性增长,查询速度在 20 毫秒左右。

从 OpenMLDB 的原理来看,应该是使用了即时编译的技术,使得 TopK 变成带参数查询 ,直接优化到执行的机器码,使得查询速度快速增长。

场景 2:通用复杂计算

复杂计算难以直接使用 SQL 各种常见计算公式进行表达,比如地理位置的查询,由于每次查询必须关注到所有 GPS 之间的相对关系,所以每次查询必须基于全量数据。

从性能的角度,将 OpenMLDB 与 Spark 方案进行比较

  • OpenMLDB 将 SQL 使用 LLVM 或 NVVM 动态编译为机器码,充分利用 SIMD 等方法处理复杂查询,查询时间基本在 30ms 左右
  • 十亿级别地理位置信息基于 OpenMLDB 的毫秒级实时分析, 比常用数据库快 30 倍 以上, 比 Spark 快 10 倍 以上

如果基于 Spark 做 10 亿级数据的全量数据查询,图中的返回时间不是 1000 毫秒的上限,而是直接 OOM。此外,还有一个很大的痛点,首先 Spark 的内存结构可能是有问题的,无法对同质化以及完成任务比较单一的结构做优化,导致其内存存储的性能较差。

总结一下,这是我推荐大家使用的第二个场景,比如标签传播、图聚类、GPS 的实时分析等任务,或者是其他需要用到全量数据但是执行比较单一的场景。

场景 3:团伙挖掘

第三个场景是我们最新做的尝试,团伙挖掘场景。团伙在我们内部或者说在任何一个金融企业的风控模型中,都是一个关键场景。

团伙挖掘的特色是特征相对复杂,每个特征都需要关联到所有人的属性,导致每轮 SQL 计算几乎都有数百行,一般也会达到上百个特征。

我们需要从下单环节开始,实时的覆盖全部数据。而这又会带来第二个问题,比如说授信环节,还能做到分钟级,可以把数据全部拉进来做一个计算。但是下单环节基本上都是毫秒级的,如果牺牲数据覆盖度就会损失模型效果,如果要尽可能确保数据的准确性,则无法在下单环节实时反馈,只能等用户完成下单才能做出预测,这就会有很大的问题。而 OpenMLDB 则能够非常好的进行大数量的实时处理。

过往实现方式,无法满足团伙挖掘业务场景对实时性以及硬实时的需求:

  • 离线数仓 + T+1 团伙挖掘算法,无法满足实时性需求 :我们之前的实现方式是使用离线数仓以及 T+1 的团伙挖掘算法,比如 HG suspector 或者是一些标签传播的方法。最大的痛点是特征无法硬实时的完成计算。团伙场景对于实时性要求很高,因为异常的欺诈团伙基本是撸完就跑,不会给风控很多的反应时间。可能一天的活动投放,当天就已经被薅完了,如果第二天才发现其中某一批人是集中欺诈,那对业务的意义就比较小。
  • 实时数仓 + 实时图挖掘,无法达到硬实时效果 :实时图挖掘可以用增量的方法解决,但是实时数仓和线上流式特征的一致性就成为瓶颈。我们之前一直没有找到一个好的解决方案,当时尝试过 Kafka + Flink CDC 来做,相对来说是勉强可用,可以做到异步实时,但受限于外存储的性能,无法完全做到硬实时的效果。

OpenMLDB 应用于团伙挖掘场景,满足业务硬实时需求,实现几十毫秒至 200 毫秒的计算速度

可以说之前的方案都是不可用的,最新我们使用 OpenMLDB 解决了实时特征计算,通过 OpenMLDB 的 SQL 语言把图的特征全部复现了一遍,同时推到了线上的流式,最后发现 OpenMLDB 是可用的,耗时基本上都是满足业务要求的几十毫秒,不超过 200 毫秒的速度。

我们也做了一些研究,将 OpenMLDB 和一些时序数据库进行了比较。目前来说时序数据库的优势是对任何时序场景的通用性,包括 SQL 的覆盖度是有优势的,但是对于专一场景,尤其是如果我们需要一个偏模型化的,不是那么严格时序的场景,就会出现一些问题,比如说可能不支持某些 join 的操作。因为时序数据库更多关注的是只有时间线的单表的性能,在这点上 OpenMLDB 是有针对性的,而且 OpenMLDB 的开发难度明显低于时序数据库,所以最终我们选择了 OpenMLDB 的方案。过往的处理过程中,会做一些中间结果并结合排序服务进行排序,由于 OpenMLDB 具备很好的排序性能,可以无需进行中间环节,直接输出最后的结果。

演进建议

介绍一下我们使用后对 OpenMLDB 的演进建议,也包括当前版本存在的一些需要注意的点。

模型开发工程师角度

  • SQL 语句方法支持和多表联合查询可以进一步完善 :目前的 SQL 语句的语法和具体函数的支持,希望可以进一步完善,多表联合查询有些时候还会有一些缺陷
  • 可将一些统计或模型方法整合为 SQL 语句调用形式,拓展特征开发的空间 :可以把一些统计或者模型方法整合为 SQL 语句的调用形式,有点类似于 SQLflow,会把 PC 或者 onehot 整合成 SQL 语句的函数,写 SQL 的实现就可以调用,可以纯闭环的在 OpenMLDB 里面完成机器学习特征工程的全部工作。目前 OpenMLDB 支持 SQL 语法已经几乎可以完成 90% 的业务特征开发

数据开发工程师角度

  • 当前版本的每次冷启动还比较复杂,简化统一数据准备工作 :由于我们频繁做实验,发现每次冷启动是比较复杂的。我们有 8 台机器,每次需要先把线下数据做成线上数据流式差不多结构的表,先把数据灌进去,然后才能把线上实时数据接入。这个其实有点像 Feast,Feast 我们之前试用的时候也是有同样的特性,它只管做自己的管理,把所有的数据按照一定的时序做排序,但是它并有去真正简化数据准备工作,需要用户熟悉 Feast feature store 的结构,才能很好的用它。我希望 OpenMLDB 能够更贴近使用者的角度进行优化。
  • 支持更长的时间窗口,满足更大规模任务应用 :时间窗口上,希望能够支持更长的时间范围。目前在 Flink 的使用上,90% 的特征可以通过 24 小时以内的时间窗口解决。但是有一些特征,比如设备欺诈案例,同一个设备指纹 ID,可能会关联到 1 年内的多个设备,而 Flink 针对这类需求的效果不是特别好,我觉得这也是一个突破口。

运维工程师角度

  • 拥抱云原生,提供云原生版本,降低运维成本 :目前数据倾向于直接使用云原生数据库,因为作为一个非常依赖稳定性的组织,云原生会给我们带来很大的优势。类似于我们这种中小型公司,不会自己去开发一套云系统。
  • 作为数据库产品,提供更多的支撑性工具,例如更完善的审计、日志、权限管理等支持 :作为一个数据库产品,目前还是需要有一些更多的支撑性工具把它平滑的交接给运维团队,比如更完善的审计、日志、权限管理。目前由于权限管理问题,我们内部搭了两套 OpenMLDB,线下开发使用测试环境,然后再把 SQL 复制到线上环境,因为我们会很担心权限管理的缺失导致误操作,把线上的一些数据或者信息搞乱。