在过去的几年间,我们的职责越来越大,做的事情越来越多。就像大部分的环境一样,系统慢慢变得庞杂和难于管理。 趁着现在架构梳理和产品化加速的机会,我在本文中重新设计一个易于产品化的大数据机器学习系统,抛开历史包袱,结合这几年的经验从头做好架构设计。 希望各位读者能有所收获。

目标

终端用户

终端用户是,有数据和应用场景,但大数据和机器学习的相关经验不足,但希望做到数字化转型的相关公司和组织。

用户需求

根据对终端用户特点的感性理解,可以得到如下的切实需求:

  1. 门槛低,容易上手并快速在业务端起到效果。
  2. 降低开发成本,最好是适合这个场景的成型解决方案,或者只需要有限定制化的半成品方案。
  3. 安全,灵活有效的权限管理,操作可追溯,减少风险事件发生。
  4. 与现有系统结合,减少对已有业务的冲击。

系统需求

  1. 降低运维成本,系统做好自动化,甚至是无人值守,只在发生严重问题时才干预。
  2. 灵活可变,可以很好的支持未来无法预知的新需求。
  3. 高性能,充分利用最新的硬件和软件优化,提高训练的速度。

逻辑结构图及解释

逻辑结构图

逻辑上讲,整个系统分为三个大部分。

Application space

终端应用和人员相关的系统属于这个部分,这部分需要做到尽量简单和易用。一是相关人员并不一定很熟悉大数据和机器学习的细节,将大量的设置项和定制化编码的部分开放给他们,不利于系统的推广。 二是减少系统的学习成本和迁移成本,如果一个公司已经有了较成熟的基础IT设施,改动它们并让其适应新来的大数据系统,会遇到很大的阻碍,同样不利于系统推广。

具体来讲,包含三个部分。首先是数据库,里面包含了业务方的核心数据,是我们之后开展分析工作所必须的基础数据。 这里的一个重要工作是ETL,如果对时效性要求不高,可以使用SQOOP等工具做离线同步,这些同步的工作可以由调度系统来安排(具体见下文)。 如果是对时效性要求高,则需要使用到数据库edit log解析和replay的功能。 解析的话,MySQL可以采用阿里的canal,oracle可以采用ogg。 replay的话目前并没有很好的开源方案,不过自己做一套也并不会特别复杂。

第二部分是和业务相关的系统服务。希望在业务中采用到我们产品得到的模型,肯定需要业务系统将数据传给我们,并能把结果拿走。 在我的结构图里面,假设对数据处理的需求是异步的,即业务不需要知道结果才能进行下一步的操作。这种适用于安防监控等业务。 如果是同步的话,只需要把kafka去掉,用同步API调用连接即可。这种适用于智能决策等业务。 值得说明的是,在异步的场景下,如果设置了数据库的实时同步机制,可以直接采用数据库同步过来的数据作为model serving的输入,不需要修改业务系统来主动发出数据,这样能进一步减少对已有IT系统的修改。

第三部分是用户交互界面。这个交互界面可以是一套独立的网页管理系统,也可以是一系列的API供程序调用。 值得注意的是,这里的用户不一定是业务方的非技术同事,也能是技术同事,或者我方的技术支持和模型支持的同事,而他们对于系统的需求是不同的。 非技术同事可能感兴趣的点包括,系统是否在正常运行,触发了多少报警信息或者做了多少个智能决策,这些报警或者决策各是哪些种类以及如何分布,从而判断出该系统对于业务系统的贡献。 技术同事,需要为非技术同事进行支持,包括制作各种报表,监控系统各种组件的运行情况和各种数据流的速率,执行模型训练和上下线等任务。

以上是应用区的三个主要部分。如果一个大的公司内需要多个机器学习系统的支持,就需要考虑到安全性了。 做到用户隔离、数据隔离和资源隔离,并提供足够的审计功能,是必须考虑到的。 下面的两层系统里都有为安全性做的设计。

System space

系统区是最复杂的一个部分,里面大数据基础设施、大数据周边系统、模型训练集群、模型服务集群、队列服务等。下面分别讲述。

大数据基础设施,包括分布式存储(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队列来得到实时反馈数据,使得线上模型始终保持最佳状态。

Admin space

管理区是用来控制整个系统的,里面包括了指标体系、日志归集和分析、配置服务器、审计和安全相关的设置。

一个复杂的系统在运行的过程中,有成千上万的指标来描述状态。 有些状态能用来标示系统的各种指标是否正常,有些在后期的问题追溯中能起到重要作用。 想要一个系统能稳定高效的持续运行,完整的指标系统是必不可少的。 可以选用传统的Ganglia、Graphite等,也可以选用open falcon或者Prometheus等较新的方案。

日志归集和分析系统,能将散落在各处的日志进行统一管理和查询,方便开发者和管理者。 在日志的简单归集之上,其实还可以做很多事情,比如进行交互式的报表展现,或者根据某些计算指标来发出报警。 开源的ELK方案(Elasticsearch+Logstash+Kibana)是比较不错的选择,在很多生产环境中都有部署,易用性、稳定性和性能表现出色。

系统组件很多,配置也是多种多样的,我们需要一个中央的配置服务器,来把各种配置管理起来。 这样既能减少配置出错的可能,也能降低运维的工作量。

审计和安全相关的设施,在大多数多用户的场景下是必须的。 因为我们的系统复杂,包含了很多的组件,每个组件都应该使用统一的安全和审计策略。 在User Console和Admin Console里,有用户登录和管理的需求;在大数据基础设施中,有文件读写权限的需求和集群资源分配的需求;在模型训练集群中,有特殊资源(比如GPU)的分配需求;各种API调用的时候需要做app和token的验证;等。 目前并没有一个开源的工具能同时满足上述的需求,需要我们从现有的开源框架中定制一个出来,同时又要能和系统其他组件(比如Hadoop、Hive、Kafka等)进行有效互操作。

实现思路

要实现上述设计图,有一些步骤需要注意。

私有云 VS 公有云

是需要建立私有云,还是可以采用现成的公有云? 上面的设计主要是针对私有云来做的,如果切换到公有云,很多组件已经由公有云提供了,使用起来更加简单,但无法自己控制,潜在风险较大。 私有云建立之初会有不小的固定成本,需要考虑的事情更多,比如机房和网络的选择,不同组件对于机型也有不同的需求,日常的基础运维也会耗费不少的人力成本。 但随着使用的延续,成本会渐渐平摊到日常的运营中。 下面的讨论基于私有云展开。

机器资源需求规划

机器资源的需求,大体上有这么几种:

  1. Web服务器,主要提供各种console和管理界面的服务。因为是内部服务,不需要很多台服务器做主备或提高性能。
  2. 大数据服务器,一般需要高配,采用高性能CPU、大内存和大磁盘,如果有性能需求,可选配SSD。这种机器的数量跟业务的量有关。有的业务数据量大,但计算复杂度低,有的业务数据量不大,但计算非常复杂还涉及到大量的迭代计算。服务器的配置和数量,都需要根据这些业务需求来做出调整。
  3. 大规模搜索(如果需要的话),一般需要大内存和高性能CPU,还需要SSD来提高IO性能。如果搜索的量大且时效性要求高,那SSD基本上是必须的。
  4. 模型相关服务器,很多时候需要GPU等特殊设备,CPU和内存的要求也高,但磁盘的容量要求不高。这种服务器的数量和具体配置,也是跟业务相关的。

提前做好资源规划,可以预防资源不够用的尴尬,也避免浪费,降低成本。

人员成本规划

做好这套系统,最基本的人员配置需要5类人:

  1. 商业产品经验丰富的产品经理:能和用户很好的沟通,了解他们的实际需求,将分析好的需求转化为系统的功能设计,并把良好的用户交互设计到各种页面中。
  2. 大数据架构师:熟练掌握各种大数据工具及周边系统的原理和设计架构,能在必要时修正bug并进行定制化开发。
  3. 前端开发工程师:将产品经理的交互设计实现出来。
  4. 后端开发工程师:实现各种需要定制化的开发,将各种组件有机的结合到一起。
  5. 机器学习科学家:在模型训练和服务的环节中,给出改进建议。