MLSQL底层由Spark开发,跟传统的Spark App模式不同的是,MLSQL是以Service模式启动的Spark App,这种方式比传统方式要解决的问题复杂些(笔者使用的几个开源的Spark监控工具,都进行了二次开发,因为MLSQL的任务单位是GroupId级别的[各种计算规模的任务],而不是单个App级别),但它的优势让人眼前持续亮。MLSQL目前已经在生产稳定运行3年多了,累计跑700多万个任务,服务于公司各个部门,TB级别下的计算在生产已经验证,非常平稳(但是也偶有跑挂的情况,原因是脚本写得太低效了,99%发生在Shuffle阶段)。今天笔者主要分享在MLSQL生产实施中需要解决的问题,希望对大家有所帮助。
1. MLSQL安全问题
对于金融行业,安全第一位,宁可选择没有功能,也不能出现任何安全漏洞。MLSQL没有提供精细化的权限控制Server,因此Server需要使用者自行实现,一般都会和企业内部现有的权限系统进行整合。为了严格的进行权限控制,ET的权限需要使用者自行实现。在笔者公司,权限做得非常精细化(权限体系做了非常多的精细化开发与优化),下面有张模糊的图(有些东西无法直接发布,请谅解),是公司同事梳理的一套非常完备的权限体系,非常精细化。而且在此基础上实现了脱敏后保持计算语义不变的动态脱敏策略。打破了传统数据脱敏需要数据落地,流程长而且慢的问题,管理员只需要动态配置用户的脱敏策略,经过审批后,用户就可以立即使用动态脱敏视图(还有动态拓展列的功能)。对于必须走JDBC协议的计算(比如SAS),笔者公司走的是Hive Beeline,通过Ranger进行权限控制。
2. Spark History问题
很多公司使用Spark on Yarn模式,传统App模式生成的Log一般不会太大,而Service模式就大不一样,长时间运行,生成几十GB的日志很正常,当你去看这个日志的时候,页面会非常卡,大多时候都是无法打开的。因此可以通过检测日志文件大小,配合调度策略进行重启,解决这个问题。另一个问题是,MLSQL是以GroupID为单位的任务,因此查任务变得很困难,因为UI也没有搜索功能(这使得查找变得非常困难),而且总条数有上限限制。这里介绍一个工具叫做delight(https://github.com/datamechanics/delight),需要进行二次开发,还可以扩展其他监控的指标,以GroupId粒度显示任务,并实现一套UI系统。下面是官方的图。
3. Spark DRA模式Yarn日志不清理问题
在Spark动态资源分配模式,Yarn的日志不会自动清理,因此需要自行实现日志清理,或是检测日志文件大小,配合调度策略进行重启(建议这种方式,比较简单,而且重启的好处很多)。如果超过最大阈值,则直接杀死任务。这个单独拿出来是因为这个非常重要。
4. Spark JVM监控
这里笔者介绍一个插件叫jvm-profiler(https://github.com/uber-common/jvm-profiler),它可以监控JVM的数据,并发送到Kafka,对于分布式应用很友好。但是它不能监控off-heap内存。对于Spark,Shuffle的时候Netty的堆外内存使用比较重要,所以可以扩展jvm-profiler,支持监控Netty的堆外内存使用。GC的调优还是有必要的,笔者通过GC调优把之前跑的很慢的任务,性能提升了很多。这个真的需要读者自己去研究,看指标,调优。
5. 调度问题
DolphinScheduler(https://github.com/apache/dolphinscheduler)笔者强烈推荐,它有丰富的Rest API。虽然文档写得不清晰,但是可以通过操作页面,打开开发者模式,查看接口的参数格式。Rest API的好处是,方便与企业内部系统打通,方便批量管理调度(ETL的时候很多)。以及做很多自动化的调度。它目前的功能,已经满足绝大多数的调度需求。
6. 血缘
血缘包含指标血缘分析,任务依赖血缘分析,依赖任务血缘合并等等功能,给定一个指标,可以迅速查找到依赖的任务链条,以及它所涉及的数据源。对于单个任务可以实现单个指标计算的过程分析,比如经过了group by然后sum最后max等操作。血缘分析非常重要,比如一个报表一个指标出现了问题,能迅速找到依赖哪些底表(字段级别)和任务,有助于快速定位和解决问题。
7. MLSQL开发工具之查询计划
MLSQL的脚本一般都很长,生成的查询计划也非常庞大,因此,是无法通过肉眼分析的。因此需要对查询计划进行裁剪、隐藏、折叠、溯源、定位等等功能,让用户可以快速分析查询计划,快速定位到分析的点。
8. MLSQL开发工具之交互分析notebook
Jupter的模式其实就不错,但是从笔者使用的角度,它真的很弱。因此这个地方需要自己摸索,设计出一个强大的分析工具,而不局限于notebook,笔者称之为分析工坊(用户工作空间+工具包+可视化+调度接口等)。机器学习虽然很伟大,但是对数据进行深度分析占有更大的比重,因此需要提供强大的分析工具包与可视化技术。SAS是一个很好的"高级"分析工具,有很多可以借鉴的地方。同时也可以看看砖厂的大数据洞察产品。在这个地方可以做非常多的文章,而且空间巨大,做到像SAS一样的高级分析工具,还有很长的路要走。在着重强调下,是高级分析工具。
9. Python机器学习支持
MLSQL对Python的支持是笔者非常喜欢的,也是目前数据交换最友好的方式(MLSQL完美解决了数据安全问题与数据流转问题)。Conda环境的好处就不用多说了(环境隔离+可移植+环境备份),对于生产环境,大多都是外网隔离的,因此,从测试环境生成ENV,发到生产,这个真的很Nice,用Ansible统一管理也很方便。由于笔者公司风险团队很大,而且主要基于SAS分析,导致大数据组的机器学习需求很匮乏,所以这方面的生产实践经验不足。就不多讲了。
10. 执行风险提示
为了减少人为的错误,会对一些耗时的操作进行风险提示。举个例子,笔者公司有一个表日增数据几千万,要是不指定分区,计算的数据量是相当庞大的。比如分区表分区检查、笛卡尔积检查、根据元数据的局部笛卡尔积检查、BroadcastNestedLoopJoin检查、元数据检查等等,防范人为的错误。
11. 任务执行复杂度
还记得第二点笔者提到的工具吗,MLSQL建议Spark采用Fair的调度模式,由于调度延时任务的执行时间波动范围比较大。为了更准确的计算任务运行时间,可以把同一GroupID的所有Task的时间汇总到一起,这个时间还是相对稳定的(比如不计算调度延时,虽然还有一些副影响,如一个Executor任务之间有GC的影响等)。通过Delight的指标和自定义指标,可以综合打分,形成复杂度计算公式。对任务执行时间和资源消耗做个评分。但是如何解决冷启动的问题呢,这需要用户的预估,随着用户使用经验的积累和对业务的理解,用户可以大概评估各个计算代码段的计算量级,然后对整体做一个全局预估(当然不能适用于所有任务)。
12. 智能调度
调度系统真的非常复杂,需要权衡的点也很多。而且与业务关联紧密。比如对于某个任务,必须在指定时间内运行并完成,如果此时没有资源,就需要杀死一个或几个任务,如何选择杀死哪个任务呢,就需要利用计算代价最小模型。对于重复定时调度,可以根据调度执行历史与监控指标,进行任务调度优化。但是对于交互式的任务呢,很多用户一起用的时候,如何才能爽呢?笔者目前没有想到理想的解决方式。因为需要执行前,对任务执行复杂度做计算,这个是相当复杂的,而且需要很多业务元数据。如果大家都是开发高手,可以自行推断个大概,这样就简单多了。如果哪位小伙伴有好的想法,欢迎一起探讨。
13. 技术探索
笔者做了很多技术探索,感兴趣的可以留言,一起探讨,计算存储分离、Z-Index索引技术、Parquet文件级别数据修复、动态ET、BitMap+动态全局字典精确去重、模糊Join、Session切割等等(UDTF这种So Easy的东西就不提了),大部分已经落地。积累了大量MLSQL实践经验与案例。
加餐:如何让大家开心的使用MLSQL
初三的物理老师说的一句话,笔者至今还记得。"很多物理题都这么简单,为什么你们不明白呢?"老师给我们分析了他是如何学习认知的,并探索如何把知识传递到每一位学生。回想起这件事,笔者忽略了一个问题,认知差异。很多使用者的认知是初步阶段,对MLSQL理解不够深入,会出现很多"我以为的"问题。比如as语法,很多人以为是把数据加载到内存里。为此,笔者特意研究了大脑学习过程和认知的东西,希望把大数据的基础知识普及以及讲明白MLSQL执行原理等等。笔者对MLSQL是包容的心态(曾经抱怨过使用者不看文档,但是这又有什么用呢,甩锅能解决问题?),把MLSQL技术分享常态化,才是一个良性的开始,以Peace And Love的方式,让大家都能开心的使用MLSQL,才有助于MLSQL的健康成长。笔者接触MLSQL三年多了,已经把它当做孩子,大家的孩子,为了各位家长理解与认可这个孩子,笔者从未停止过努力(请记住一切消极的态度,都不是解决问题的根本)。
笔者认为工作也好,生活也好,需要修心,需要经历"万种风情",有太多的事情都不是那么Nice,能做的只有靠自己强大的心,让事情往更好的方向发展。

图片素材1:Siracusa, 意大利的奥提伽岛
图片素材尾:互联网

喜欢就点击最上方的[ MLSQL之道 ]关注下吧!右下角还有在看哦!
源码地址:
https://github.com/latincross/mlsqlwechat