摘要:本文由网易云音乐数据智能部资深数据平台开发工程师蒋文伟分享,次要介绍 Flink SQL 在云音乐的产品化实际。分享内容如下:
- 简介
- 产品性能
- 性能优化
- 运维欠缺
- 将来布局
一、背景简介
1.Flink in Music
先简略的介绍下云音乐的现状,目前音乐这边的客户端日志,服务端日志大略在每日大千亿条左右,维度表数据源像 Redis,MySQL 这些大略有上百个。而服务的实时计算工作开发的人员有上百名,其中不仅包扩数据开发工程师,分析师,也包含算法,后盾业务等同学。这些同学们也累积开发了上千个实时计算工作,这些工作不仅有统计工作,还有些一线业务,比方排行榜,实时热度等。
2. 利用场景
这里我略微列举了一些业务场景,比方咱们的内容散发、实时数仓、算法举荐,还有索引工作、实时监控,AB test 等,简直涵盖了整个数据链路中的大部分业务场景,能够说咱们当初的业务曾经离不开 Flink 的体系,那前面咱们会以其中几个场景为例,看看咱们在这些场景中应用原生的 Flink 会遇到那些问题。
■ 内容散发
第一个介绍的场景是散发,散发是个十分典型的场景。它会依据肯定条件对数据流进行划分,把输出数据流切分成多个子流。
个别状况下散发会是整个数据链路的上游,所以相对来说这类工作十分重要,那么咱们在这个场景中会遇到什么问题呢?
- 问题 1: 开发效率低,业务规范流程难以复用
首先是开发效率低下,这类业务逻辑非常简单,外围开发工作其实就是个 where 筛选,然而传统的开发方式须要用户理解很多额定的货色,比方 HDFS 的定时清理性能,如果这个组件交由用户开发,势必要凋谢权限,那么就可能会导致 HDFS 仓库文件被误删等安全事故,所以咱们须要建设一套对立框架,且能够提供一系列标准化的组件,用户仅须要关怀其外围业务逻辑即可。
- 问题 2: 学习老本高
第二个问题是学习老本较高,SQL 是一种十分优良的数据处理语言,很多同学也都会,然而 Flink SQL 的配置却没一般 SQL 那么简略。Flink SQL 要求用户对每个组件的配置都十分相熟,这是一个 HDFS 的 sink 操作,须要在 SQL 中配置输入目录,分区字段,文件大小,keytab,压缩格局等一系列的参数,而这些参数须要用户通过文档来学习。
针对这个,咱们须要一种前端上的优化,通过给用户可视化的提醒,来简化配置,升高学习老本。
- 问题 3: 外部环境凌乱
第三,对一个稳定性,以及性能要求比拟高的工作来说,所有的这些监控、报警的配套体系建设也都是必不可少的。
■ 特色快照
第二个例子,特色快照,先简略的说下什么是特色快照,特色快照简略的能够了解成把特色的历史版本进行存储,为什么要这么做呢,因为特色是动态变化的,每个事件未必能保准程序达到,一个用户先点喜爱 DJ,在播放歌曲,再点击喜爱了动漫,咱们最终这次播放关联的应该是 DJ 而不是动漫,但依照工夫序可能就是错的,所以,对一每个版本的特色和 tag,都会有其惟一的 traceid 来进行治理,也就是一个 traceid 一个特色版本,这块在实时机器学习场景应用的十分宽泛。
这边能够看到工作的流程图,包含数据荡涤,收集,抽样,去重,join 等流程,这些流程也有很多业务逻辑,像 join 这个流程如果 join 不上怎么办,是放在内存里等,还是再次回流到 kafka 期待下一轮匹配,亦或是应用降级计划。相对来说,对稳定性、兜底计划等都有较多要求。
咱们来看特色快照场景下会遇到哪些问题。
- 第一,开发成本较高,调试也比较复杂。上述提到咱们有很多种模块独特组成这个工作,如果通过传统的日志打印,很难进行调试和保护。
- 第二,非凡的需要没有方法被疾速的满足。像抽样性能齐全取决于业务,比拟难以形象和复用。
其它的一些问题,包含调优问题、运维问题、监控的问题,我演绎为技术赋能。这些问题不能推给用户来做,只能由平台来进行对立的治理和保护。
综上所述,咱们的产品化指标也进去了,咱们心愿打造一套能升高用户学习老本、运维老本,晋升开发效率,并在全方位进行一个赋能的一站式的实时计算平台。也就是咱们的次要介绍的产品,音乐的实时计算 Notebook 服务。
二、云音乐的实时计算 Notebook 服务
1.NoteBook with block
咱们的 notebook 服务是由多个 block 快组成的,每个 block 能够自由组合,比方 SQL 类型的块之后加 2 个 sink 的组件,再加一个 source 组件,都能够。
同样,每个 block 块领有子类型,也就是二级类型,比方一个 sink,会有一些相似 MySQL sink,Redis sink 的子类型,他们都以插件的模式进行加载,因而主类型能够被疾速扩大,子类型也同样能够被疾速扩大,组件开发就变得十分不便。
而整个 notebook 执行的过程,也会依照程序由上至下的执行每一个 block,同时咱们的 block 中除了 sink 之外都反对在页面的 debug 服务。
具体分享一下目前反对的 block 类型。
- 第一种就是 SQL block,反对 Flink SQL,当然咱们也在两头做了一些优化。比方建设本人的 catalog 以及 function 管理中心,自定义的一些参数 set 语法等。
- 第二种是 custom block,咱们会提供给用户一套规范的 API,通过 API 就能够进行个性化的开发,相似一个无限条件下的 Flink 的 jar 包工作。
source 和 sink 类型,他们比纯 SQL 类型有更多的劣势,比方同样的性能在 SQL 中也能够实现,然而须要加很多 set config 配置。而当初,不仅 catalog DB 反对搜寻,并且有些配置也将更加直观的被出现。就像 HDFS sink,他的归档大小,序列化类型,前缀,等等惯例的配置就间接能够让用户进行抉择。
第二个劣势,咱们能够通过可视化 block 来提供组件,比方 source 端的动静限流,能够开启一个 source 的 slot 来做全局 config 的轮训,比方 sink 有相似 HDFS 文件过期清理或者小文件合并的性能。相似的规范组件能够通过 block 块更直观的提供给用户。
整个平台的页面大略介绍到这里,这里是些小的演绎总结,良好的交互也就是跟简略直观的操作咱们刚刚介绍了一些,良好的扩大,也就是咱们的 block 的插件化,元数据中心以及监控配套等,咱们先看如何用这套 notebook 来解决理论例子。
■ Snapshot 场景的利用
首先是 snapshot 场景的利用,咱们能够看到这个场景中,链路上的 4 种工作别离通过不同的 block 类型实现。
- Clollect,通过 SQL 就能实现;
- ETL,会有一些业务上的抽样办法和去重逻辑,所以会通过自定义 source 来实现;
- Snapshut join,除了 join 操作之外,可能会有业务降级计划等一系列非标需要,通过 SQL 无奈实现,须要通过自定义的 transform 组件来实现;
- Extrect,通过可视化 sink 来进行最初样本文件的落盘。
2. 性能实现
说完前端性能,咱们再来说下实现。
整套 block notebook 在执行的时候,都会找到对应类型的 Interpreter,每个 Interpreter 再通过子类型去发现真正的实现类。像第一个 source 指向 MySQL 的 blog 日志订阅,最终会创立一个 MySQL 的 blog 日志订阅 source 实现,每个 Interpreter 都会接管到所有上游执行过的所有后果,这个后果对立以 table 的形式进行流转,在没有指定的状况下,默认应用离本人最近的一个 table 作为输出。
■ Block Structure
这是 notebook 的数据结构,属于 JobContext。作为一个全局的共享的内容,外面蕴含着一个可执行环境和一些全局共享的配置。blockList 数组里每一个都是加载一个 interpreter 具体事件类。如果业务上有需要,扩大一个 block 也非常简单,只有实现一个接口即可,其余的局部都交给框架来实现。
■ 提交执行
以上是 block 的外部执行逻辑,咱们再来独自讲一下提交的服务。
首先,服务会判断工作中的所用到的插件和依赖的文件,而后通过一些机制来确定主程序版本,这么做的起因很简略,咱们常常会做降级,而降级之后可能执行打算可能会变动,有些用户进行工作后再通过 checkpoint 可能就起不来了,通过这个服务来实现多版本就非常简单了。咱们还能够依据一些条件,比方工作是否是 checkpoint 启动的等来判断主程序版本。最初提交服务会通过一些逻辑对集群和队列的进行智能抉择。
■ 整体架构
通过以上对整体架构的分享,想必大家也就比拟清晰了。下层会有一层 notebook 的 server 的服务,上层会有一个 submit 的提交服务和一个 debug server。外围会有元数据管理核心来治理咱们的 catalog,而后还有权限或者一些其余的内部零碎来进行辅助。
整个体系最大的益处在于,用户的代码都在框架的范畴内进行执行,这样的话咱们能够疾速的进行性能优化和性能调整。
三、性能优化
团队对整个平台有十分多的性能优化,这里只能抛砖引玉的说几点。
1.Table source 优化插件
第一个就是 Table source 的优化。生产过程中的遇到的性能问题,如:
- 原生的 KafkaTableSource 因为须要解析 Schema 无奈将反序列化过程提取进去,而 Kafka 的并发受制于业务的 partition 数量,如果反序列化计算量要求较大,会造成性能瓶颈。
- 维表 Join 如果先进行 keyBy,能够晋升缓存命中率。
咱们的解决方案包含 3 个大的步骤。
1、动静代理形式获取 byte 流。
2、将 byte 流进行二次解决:
- 动静的加载所需执行的插件。
- 调配插件到 Map 和 Filter 算子 中去(保障插件变动时 ckp 启动)。
- 调整并发。
- 反序列化成指标 Row。
3、返回 ProxyTableSource。这样就能够有限的扩大性能。
这是一个优化实例:升高因为序列化计算量过大而导致的 source 端性能瓶颈咱们把有 5 个 kafka partition 的一个工作拆分成 5 个 source 跟 10 个 Deserialization 的并发,从而晋升了整个工作的吞吐。
2. 多 Sink 合并
第二个是多 sink 合并,这块高版本曾经有了,因为咱们还在应用 1.10,所以才须要优化,这块就不具体说了。
3. 流量降级计划
第三个是咱们的流量降级计划,这块优化波及到一些体系的建设。一般来说,咱们的散发工作会有 2 个 sink,会散发到主音讯队列和备份音讯队列,这 2 个队列的 catalog 完全一致,只会通过 tag 进行辨别,所以相干代码开发也完全一致,上游读取的时候,会依据工作的 tag 剖析说咱们读主还是备。举例,归档工作,测试工作,等会从备份流来读取,这样咱们就对 kafka 集群进行了压力分流。
四、运维监控加强
介绍完性能优化,咱们来聊下运维和监控。Flink 本人曾经带有不少监控,比方 failover 次数、QPS、checkpoint 成功率,然而在生产过程中,这可能还不够,所以会减少很多内置监控,并且对血统进行收集。
此外咱们做了 4 个智能诊断性能,包含内存诊断、性能诊断、checkpoint 诊断和日志诊断,从而来判断咱们的工作运行状况。
这是咱们之前看过架构图,红色就是监控诊断局部,由一个对立的数据收集服务来获取信息,并提供给监控报警等服务应用。
监控加强这块其实就是在在框架中减少很多内置的指标,比方 sink 均匀写入工夫,序列化错误率,维表 join 命中率,sink 写入工夫等等一系列的指标,这些参数也有助于咱们更多维度的理解工作理论状况,当然咱们能够抉择是否开启这些监控,以保障高峰期工作性能。
第二块是血统,它是数据治理中十分重要的一块。咱们收集数据血统比较简单,通过 Block 的参数进行一个动态解析来看所有的输出源和输出表,而后上报给数据中心,最终组成一个血统的关系图。
咱们的智能诊断其实是利用所有监控数据来综合判断一个工作是不是处于失常状态,包含四块。
- 第一,内存诊断
- 第二,性能诊断
- 第三,Checkpoint 诊断
- 第四,日志诊断,举例说明,内存诊断,它次要通过 GC 如何触发报警,会有很多条判断规范,比方 young gc 频率,full gc 频率,gc 耗时等等是否大于或者小于肯定值,通过这些条件综合来判断一个工作是否存在 gc 异样,以及异样的等级。而日志会通过肯定条件对谬误日志进行筛选,这个条件能够是用户自定义的,比方统计某个具体的 exception 的次数,当达到统计次数时候进行报警的触发。这样的话,某些业务不想被 failover,又想收到异样报警,就通过简略的 try catch 就能实现。
这是咱们智能诊断的一个内存诊断的前端的页面,展现了一个理论工作的内存的应用状况散布。
五、将来布局
最初讲一下对将来的一些布局。
第一,体系建设:权限体系将更加灵便,数据安全 / 用户治理等配套将更新欠缺。
第二,Notebook 体系将引入其余数据计算引擎(如 druid 等)。
第三,拥抱新版本,当初的 Flink 1.12 有十分多的新个性,有些也十分吸引人。咱们心愿能踊跃的跟上社区版本。