• 建模杂谈系列177 APIFunc继续实践-比对研究


    说明

    在最终的实用上,我还是选择了Kettle。主要还是因为考虑未来公司的部署和使用上有比较全的文档,也比较有说服力。所以有时候也挺有趣的:

    • 1 其实APIFunc要好得多,但是(刚做完原型验证)并不能取得大部分人的信任
    • 2 有一些方法对于有一定基础的人来说很方便,但是对于更多的人是觉得不好用(专业上还是有很大鸿沟的)

    Kettle(HiTaCHI Pentaho)的部分商业用户,所以看起来似乎是经过大量实践检验的。对于其他人推广起来就很容易。
    在这里插入图片描述

    我现在越来越能理解这种现状,所以我一点都不排斥使用Kettle,更多的,我会把Kettle的实践过程与APIFunc相类比:

    • 1 作为产品设计时的参考,他山之石,可以攻玉
    • 2 我会坚定不移的推进APIFunc,因为在设计之初就考虑过,即使是我自己使用(One User - One Service),也完全值得开发

    kettle介绍

    一开始只搞etl,后来也慢慢延伸到机器学习。所以和KNime,以及其他一些平台做的事情都很类似,只不过起点不同而已。我的核心是搞算法的,等这一波APIFunc弄完应该就会把精力调回去主攻算法,同时给自己提供一些前端支持。

    在这里插入图片描述
    在这里插入图片描述

    内容

    内容比较多,边研究边记录的,主要就顺着时间顺序吧

    1 总体对比

    我先基于目前的比对,做个汇总

    序号APIFuncKettle
    1同时支持行式、列式处理只支持行式
    2同时支持结构化与非结构化数据库似乎只支持结构化
    3天然并发付费后并发
    4允许批量编辑(Fork)目前看到的都是一个个单元拖拽,还不清楚有没有这样的设计
    5复用简单目前还不确定怎么复用,至少第一眼感觉不那么容易
    6可控性强(基于RR)可控性弱,本质上和硬代码贯序执行没有差别的
    7一体化(直接和Redis以及Mongo绑定)分体式(只负责一段数据处理,IO另外做)

    结论:APIFunc的潜力,无论是计算效率、逻辑复杂度与操作便利性比Kettle至少是高一量级的。 当然,这个是期望之中的事,我希望APIFunc可以支持我以非常低的成本,非常短的周期去完成逻辑复杂度很高的应用。在设计之初我就是以提高“逻辑集成度”的方向去设计的。

    2 细节

    整体架构

    这个是Kettle的概念模型。JOB承担了一堆杂事,起到了IO和调用的功能。具体的转换逻辑看起来是在Transformation里面的
    在这里插入图片描述
    以下解释引用自这篇文章,介绍的基本内容还比较详细,建议参看。


    4.2.1、转换(Transformation)
    主要是针对数据的各种处理
    一个转换里可以包含多个步骤(Step)
    4.2.2、作业(Job)
    相较于转换,是更加高级的操作。
    一个作业里包括多个作业项(Job Entry)
    一个作业项代表了一项工作,而转换是一种作业项,即作业里面可以包括多个转换


    所以很显然,我的APIFunc和转换(Transformation)概念是基本对应的。

    APIFunc内部是通过「瀑布」的方式来提供对每一个变量的精细处理,而Transformation的每个Step都是假设表到表的变换(虽然也可以拆字段)。

    然后有一个比较大的不同点是Hop,这个在APIFunc里称为依赖(Dependancy)。

    APIFunc里的依赖分为运行依赖与数据依赖,这些依赖不仅与程序是否正常执行相关,也与执行的规则结果相关。在表达能力上比HOP丰富很多。另外APIFunc里默认按照尽力交付的原则,不会因为个别问题停止全量的交付。

    Transformation ~ APIFunc.Worker

    这篇文章时对Job做了一些介绍。
    在这里插入图片描述
    这点从某种程度上APIFunc还没有开发到,APIFunc是基于某一个Job而讨论的,未来随着用的业务场景变多,也会出现类似的快速构造Job的功能。

    APIFunc假定面对的Job通常经过一个转换,或者两个转换就会完成,而且基于的数据库系统也就随之确定。以单个Step的数据转换为例,需要对3张Mongo表,一个Redis队列进行初始化设置。整个流程会用到3个Mongo表和3个Redis队列。整个流程由Sniffer推动。

    Job ~ APIFunc.Sniffer

    这种流程的设定是比较简单的,所以未来要加上并不难。(也应该加)

    另外从运行部署上,Kettle是使用Java构建的(分为单机和Docker版),APIFunc使用Python构建,部署方式只有Docker(简单)。

    数据约定

    采用数据库和一些约定是有非常大的帮助的,它可以简化大量的数据吞吐操作,并且能将元数据(RR)也持久化,使开发者得到的不仅是“然”,还有“所以然”。

    数据的流转全部通过微服务流转,只要改个参数(大部分是数据库和表的名称)就好了。我认为开发者最核心的工作是开发逻辑,而不是管理数据吞吐。

    APIFunc.DBase可以使得整体数据处理的吞吐达到极高的能力,并且可以随时“后悔”。例如有时候交付的目标库出问题,如果没有持久化,就得重跑。

    最大的帮助是元数据收集

    Kettle分为spoon、kitchen、pan和carte,功能如下:


    4.3、运行工具
    Kettle里有不同的工具,用于ETL的不同阶段。主要工具如下:

    Spoon:图形化工具,用于快速设计和维护复杂的ETL工作流
    Kitchen:运行作业的命令行工具
    Pan:运行转换的命令行工具
    Carte:轻量级的(大概1MB)Web服务器,用来远程执行转换或作业,一个运行有Carte进程的机器可以作为从服务器,从服务器是Kettle集群的一部分


    这部分倒没有特别可说的,对应于spoon,我会做一个简单的表单前端(基本可行),拖拽组件暂时还没有研究。最大的不同是需要基于简单的python代码来编写逻辑,没有其他的按钮和配置。当然很多时候也不用写代码,改几个表单配置就行。

    pan就是很简单的对应我的docker manager 服务的命令,调度上我会用flask_apscheduler控制,这些都是已有的组件,要加一些前端协同起来。

    在组件上,有一个很大的不同点是微服务体系。

    我的APIFunc是先天假设处于一个微服务环绕的体系中的,所以会借助微服务构造很多特殊的功能,例如实体识别服务。甚至于数据库的吞吐都做好了约定,最大的不同点只是在末端的IO需要定制化一些对应的取数和存数程序。

    所以APIFunc最好工作在一个局域网集群中,当然如果计算传输比高的任务,通过广域网也可以无缝拓展。

    HOP

    看到了这里,也挺有意思。Kettle通过Hop来控制批处理的容量,而APIFunc则是利用Redis Stream,加上一些程序的预判,来实现一样的效果。 如果队列满,流程将会自动阻塞


    4.6、Kettle里面的 Hop跳(即图元之间的连线)
    跳就是步骤之间带箭头的连线,跳定义了步骤之间的数据通路。
    跳实际上是两个步骤之间的被称之为行集的数据行缓存(行集的大小可以在转换的设置里定义)。
    当行集满了,向行集写数据的步骤将停止写入,直到行集里又有了空间。
    当行集空了,从行集读取数据的步骤停止读取,直到行集里又有可读的数据行。


    字段类型

    有一点可以确定的是APIFunc里面的数据类型会比Kettle多得多,而且通常并不会只定义String这样简单的一级类型。而是StringLikeName之类的。

    除此之外,对于数据的传递还会要求数据结构。例如 is_listofdict


    4.7.1、字段的几种数据类型
    String:字符类型数据
    Number:双精度浮点数。
    Integer:带符号长整型(64位)。
    BigNumber:任意精度数据。
    Date:带毫秒精度的日期时间值。
    Boolean:取值为true和false的布尔值。
    Binary:二进制字段可以包含图像、声音、视频及其他类型的二进制数据。


    并行

    APIFunc里是按照Docker容器来并行的,因为数据库和Redis队列已经做了一些规范和约定,只要通过我的Docker Manager服务(需要再加点前端)就可以灵活的启动n个worker并行。worker的每次执行都意味着一个python脚本的执行,这样的好处是资源的释放是特别干净的。

    当然,通过Docker本身也意味着拓展是超级便利的。


    4.9、Kettle里面的 并行概念。
    跳的这种基于行集缓存的规则允许每个步骤都是由一个独立的线程运行,这样并发程度最高。这一规则也允许数据以最小消耗内存的数据流的方式来处理。在数据仓库里,我们经常要处理大量数据,所以这种并发低消耗内存的方式也是ETL工具的核心需求。

    对于kettle的转换,不可能定义一个执行顺序,因为所有步骤都以并发方式执行

    1. 当转换启动后,所有步骤都同时启动,从它们的输入跳中读取数据,并把处理过的数据写到输入跳,直到输入跳里不再有数据,就中止步骤的运行。
    2. 当所有的步骤都中止了,整个转换就中止了。(要与数据流向区分开)

    如果你想要一个任务沿着指定的顺序执行,那么就要使用"作业"


    下面是针对看到的另一篇写的不错的kettle介绍文章进行的比对ETL之Kettle工具十大功能特性详解

    在这里插入图片描述
    一方面是我把这个用在公司的机器上应该从效率上没太大问题。

    比较有意思的是,Kettle的分发和复制方式和我用Redis Stream实现的机制是一样的,当然我更多用的是分发。所以借助Redis这样的工具,我觉得这个功能是不会比Kettle差的(我还是更相信数据库工具)

    在这里插入图片描述
    没有特别Get到 作者这段话的意思,反正APIFunc也是灵活的。

    在这里插入图片描述
    这个挺好,不过还要研究一下怎么用。在APIFunc中,第一版的时候我并没有考虑这方面的概念,在实践的时候发现这其实是一个很重要的点。按目前APIFunc的设计,复用方面应该会比Kettle的自映射要强很多。主要是基于根函数概念和三种链函数的结构定义。不仅容易复制,还容易修改。

    在这里插入图片描述
    Kettle对于Java来说是更友好的,毕竟Born With Java。APIFunc则是基于微服务(所以灵活性是语言无关的)以及python的脚本扩展。

    在这里插入图片描述
    这个功能我的老板们应该会喜欢,这样所有类型的业务都可以承载。对于APIFunc.DBase来说,很多问题是更简单的。对于主库是Mongo来说,变更维度不是事。通过使用MongoAgent, 单表内的数据操作是没有问题的。倒是对于合并,目前会直接放在一个Mongo表里,不需要再连接。

    这里对于大部分的场景应该是无所谓的,小部分特殊场景再看吧。

    在这里插入图片描述
    这方面APIFunc就要强很多了,毕竟我做APIFunc的初衷就是节约我自己的时间,特别是在Debug这种,偶尔碰到,一碰到就要翻旧账的工作。

    在整个流中,通过一个主键来关联同一条数据在不同处理下的结果。本身APIFunc.Core里面的会话也是使用示例数据创建的,通过前端页面,可以将这个功能投射到前端。直接在页面上看到问题,修改调试,对所有样本再次试运行上线。

    在这里插入图片描述
    这方面我不太清楚怎么比较,感觉APIFunc可能没有那么清晰的去搞这个概念,但由于RR(RuleResult)的存在,应该是容易做到影响分析的;而全流程唯一主键则可以确保血统追溯? 我猜的

    在这里插入图片描述
    这部分APIFunc做了一些底子,但没有做的那么清晰,毕竟就我一个Root,我没有对自己审计 。但是日志库和统计库里往往也包含了类似的信息,我是打算做到前端DashBoard的。

    总体上来说,APIFunc关于数据处理的核心功能优于Kettle,但在一些辅助功能(日志、审计这些)会逊于Kettle。主要是因为场景还没走到那一步。

    先这么多吧,感觉还是挺不错的,有比较更有方向。

  • 相关阅读:
    iceoryx源码阅读(一)——全局概览
    Netty之DefaultAttributeMap与AttributeKey的机制和原理
    Git分支及使用原则与流程
    User parameters自定义用户参数 (zabbix监控)
    python+django_vue旅游酒店预订出行订票系统pycharm项目lw
    【算法/图论】2-SAT问题详解
    图之最小生成树Prim算法详解(C语言版)
    我在这块牛X的A40i Linux开发板上点了个流水灯
    uniapp&小程序打开地图导航
    程序化交易接口作用和算法交易有哪些不同?
  • 原文地址:https://blog.csdn.net/yukai08008/article/details/127859982