逻辑上讲,整个系统分为三个大部分。
终端应用和人员相关的系统属于这个部分,这部分需要做到尽量简单和易用。一是相关人员并不一定很熟悉大数据和机器学习的细节,将大量的设置项和定制化编码的部分开放给他们,不利于系统的推广。 二是减少系统的学习成本和迁移成本,如果一个公司已经有了较成熟的基础IT设施,改动它们并让其适应新来的大数据系统,会遇到很大的阻碍,同样不利于系统推广。
具体来讲,包含三个部分。首先是数据库,里面包含了业务方的核心数据,是我们之后开展分析工作所必须的基础数据。 这里的一个重要工作是ETL,如果对时效性要求不高,可以使用SQOOP等工具做离线同步,这些同步的工作可以由调度系统来安排(具体见下文)。 如果是对时效性要求高,则需要使用到数据库edit log解析和replay的功能。 解析的话,MySQL可以采用阿里的canal,oracle可以采用ogg。 replay的话目前并没有很好的开源方案,不过自己做一套也并不会特别复杂。
第二部分是和业务相关的系统服务。希望在业务中采用到我们产品得到的模型,肯定需要业务系统将数据传给我们,并能把结果拿走。 在我的结构图里面,假设对数据处理的需求是异步的,即业务不需要知道结果才能进行下一步的操作。这种适用于安防监控等业务。 如果是同步的话,只需要把kafka去掉,用同步API调用连接即可。这种适用于智能决策等业务。 值得说明的是,在异步的场景下,如果设置了数据库的实时同步机制,可以直接采用数据库同步过来的数据作为model serving的输入,不需要修改业务系统来主动发出数据,这样能进一步减少对已有IT系统的修改。
第三部分是用户交互界面。这个交互界面可以是一套独立的网页管理系统,也可以是一系列的API供程序调用。 值得注意的是,这里的用户不一定是业务方的非技术同事,也能是技术同事,或者我方的技术支持和模型支持的同事,而他们对于系统的需求是不同的。 非技术同事可能感兴趣的点包括,系统是否在正常运行,触发了多少报警信息或者做了多少个智能决策,这些报警或者决策各是哪些种类以及如何分布,从而判断出该系统对于业务系统的贡献。 技术同事,需要为非技术同事进行支持,包括制作各种报表,监控系统各种组件的运行情况和各种数据流的速率,执行模型训练和上下线等任务。
以上是应用区的三个主要部分。如果一个大的公司内需要多个机器学习系统的支持,就需要考虑到安全性了。 做到用户隔离、数据隔离和资源隔离,并提供足够的审计功能,是必须考虑到的。 下面的两层系统里都有为安全性做的设计。
系统区是最复杂的一个部分,里面大数据基础设施、大数据周边系统、模型训练集群、模型服务集群、队列服务等。下面分别讲述。
大数据基础设施,包括分布式存储(HDFS)、分布式资源管理(Yarn)、计算框架、数据仓库等,这些是大数据系统的标准配置。 计算框架里,我选择了Hive、Spark和Streaming(Spark/Flink)。 选择Hive,是因为它的使用简单,用户群很广,也能很好得跟其他系统进行结合。近些年来的优化,使得它的性能有了很大的提升,常见的计算并不比其他框架慢。 选择Spark,是因为它基于内存的迭代计算优化的很好,提供了很多的算子,开发起来比较方便快捷。同时它的生态系统也不错,可以执行SQL、图计算等,并能通过mllib进行简单的机器学习训练。 Streaming有两种选择,Spark Streaming和Flink。对于需要复杂计算,特别是多步迭代计算的场景,以及对时效性要求不是特别强的场景,可以采用Spark streaming,这样能跟其他的Spark场景混合使用。如果是对时效性要求特别强的场景,需要做到单条时间单独处理,可以采用Flink。
以上只是最基础的组件,如果需要NoSQL存储,可以采用Hbase;需要大规模全文检索,可以采用Elasticsearch或者Solr;需要大规模图数据库,可以采用Titan等。这里面可选的组件是多样的,都可以跟这些最基础的组件进行有机结合,形成更强大的大数据基础设施。
大数据周边系统,包括两个基本组件,元数据系统和调度系统。 元数据系统目前并没有特别完善的开源解决方案,大部分时候是需要跟已有的IT设施进行定制化开发。 前些时间Linkedin开源出来的WhereHows提供了不错的框架,我们可以在之上进行二次开发,以满足更多用户的需求。 调度系统的话,开源世界里有san 个比较成熟的,Azkaban,Oozie和Airflow。 本图中选择azkaban作为示例,选择其他的调度系统问题应该也不太大。
模型训练集群,是需要进行模型训练的地方,这里可以采用TensorFlow,Mxnet等深度学习框架,也可以是scikit-learn等偏通用的机器学习框架。 最理想的情况是,模型训练集群从属与整个大数据框架内,由Yarn调度。 但考虑到已有算法工具并不都支持分布式,更不一定能支持Yarn调度,所以从逻辑上把它跟大数据基础设施分离开。 如果要进一步的,在物理上把它跟大数据的基础设施分离开,那做训练的时候将会发生大规模的数据迁移,对于网络的压力会很大,相应的成本会升高。
接下来是模型服务集群,它接收模型训练集群生产的具体模型参数,并从线上系统的数据流中拿到数据,将执行的结果写回到业务系统中去。 将训练集群和服务集群分隔开,是因为一般线上系统执行的过程中,对于响应时间是比较关注的,延迟的增大可能导致严重的事故(想一下高频交易),而模型训练的过程中,一般对于资源的消耗是比较严重的。 将模型服务的集群单独隔离开,有助于减小此种事情发生的概率。
最后是队列服务。使用队列服务,能将服务解耦,减小依赖程度,并能较好的保证服务质量,防止故障的蔓延,是一个很常用的设计思路。 这里采用了Kafka,主要看中的是它的扩展能力和性能,跟Hadoop等系统都有很好的应用实践。 使用Kafka除了能作为数据的流式管道使用外,还能作为数据的传输系统,通过定时任务或者streaming job将数据写入到HDFS中,供之后的训练使用。
如果一个模型支持增量更新,那么可以采用额外的kafka队列来得到实时反馈数据,使得线上模型始终保持最佳状态。
管理区是用来控制整个系统的,里面包括了指标体系、日志归集和分析、配置服务器、审计和安全相关的设置。
一个复杂的系统在运行的过程中,有成千上万的指标来描述状态。 有些状态能用来标示系统的各种指标是否正常,有些在后期的问题追溯中能起到重要作用。 想要一个系统能稳定高效的持续运行,完整的指标系统是必不可少的。 可以选用传统的Ganglia、Graphite等,也可以选用open falcon或者Prometheus等较新的方案。
日志归集和分析系统,能将散落在各处的日志进行统一管理和查询,方便开发者和管理者。 在日志的简单归集之上,其实还可以做很多事情,比如进行交互式的报表展现,或者根据某些计算指标来发出报警。 开源的ELK方案(Elasticsearch+Logstash+Kibana)是比较不错的选择,在很多生产环境中都有部署,易用性、稳定性和性能表现出色。
系统组件很多,配置也是多种多样的,我们需要一个中央的配置服务器,来把各种配置管理起来。 这样既能减少配置出错的可能,也能降低运维的工作量。
审计和安全相关的设施,在大多数多用户的场景下是必须的。 因为我们的系统复杂,包含了很多的组件,每个组件都应该使用统一的安全和审计策略。 在User Console和Admin Console里,有用户登录和管理的需求;在大数据基础设施中,有文件读写权限的需求和集群资源分配的需求;在模型训练集群中,有特殊资源(比如GPU)的分配需求;各种API调用的时候需要做app和token的验证;等。 目前并没有一个开源的工具能同时满足上述的需求,需要我们从现有的开源框架中定制一个出来,同时又要能和系统其他组件(比如Hadoop、Hive、Kafka等)进行有效互操作。
要实现上述设计图,有一些步骤需要注意。
是需要建立私有云,还是可以采用现成的公有云? 上面的设计主要是针对私有云来做的,如果切换到公有云,很多组件已经由公有云提供了,使用起来更加简单,但无法自己控制,潜在风险较大。 私有云建立之初会有不小的固定成本,需要考虑的事情更多,比如机房和网络的选择,不同组件对于机型也有不同的需求,日常的基础运维也会耗费不少的人力成本。 但随着使用的延续,成本会渐渐平摊到日常的运营中。 下面的讨论基于私有云展开。
机器资源的需求,大体上有这么几种:
提前做好资源规划,可以预防资源不够用的尴尬,也避免浪费,降低成本。
做好这套系统,最基本的人员配置需要5类人: