2.5 数据驱动系统的基本组件
简单地说,一个数据驱动架构包含如下的组件(或者可精简为以下这些组件):
数据收集:需要从系统和设备上收集数据。大多数的系统有日志,或者至少可选择将日志写入本地文件系统。一些系统可以通过网络来传输信息,比如syslog。但若没有审计信息,缺少持久层意味着有可能丢失数据。
数据转换层:也被称为提取、变换和加载(ETL)。现在数据转换层也可以进行实时处理,即通过最近的数据来计算汇总信息。数据转换层也用来重新格式化数据和索引数据,以便能被UI组件有效地访问。
数据分析和机器学习引擎:这层是标准数据转换层的一部分,因为这一层需要很多完全不一样的技术。构建合理统计模型的思维方式通常与快速移动数TB数据不同,尽管偶尔可以找到具有这两种技能的人。通常称这些人为数据科学家,但是他们在任何特定领域的技能通常不及专注于一个特定领域的人。另一个原因是机器学习,数据分析需要多次汇总和使用相同的数据(与大多数的流式ETL转换相反),这需要不同的引擎。
UI组件:UI表示用户界面,它通常是一系列组件,这些组件能让用户通过浏览器来访问系统(浏览器曾经是一个简单的GUI,但如今基于Web的JavaScript或基于Scala的框架能构建更强大和更易于移植的UI)。从数据管道和建模透视图来看,UI提供了访问数据和模型的内部表示的API。
动作引擎:这通常是一个可配置的规则引擎,基于灵感来优化给定的指标。这些动作可以是实时的,例如在线广告就属于这种情形。在这种情况下,引擎应当能够提供实时评分信息或者针对用户操作进行推荐,也可以采取电子邮件的形式来提醒。
关联引擎:这是一种新的组件,可以对数据分析和机器学习引擎的输出进行分析,以便能对数据或模型有更深入的理解。动作也可能由此层的输出触发。
监控:这是一个复杂的系统,包含的功能有日志记录、监控和更改系统参数。监控是为了优化系统性能的嵌套决策系统,并能自动减轻问题或者向系统管理员报告问题。
下面来详细讨论每个组件。
2.5.1 数据收集
随着智能设备的增加,信息收集对任何不止一种类型的文本业务而言都非常有必要。本章假设有一个或多个设备通过互联网来来传递信息,其连接方式可能是通过家庭拨号,也可能是网络直接连接。
此组件的主要目的是收集所有可能与数据驱动决策相关的信息。下表给出了与数据收集相关的最常见框架:
如果要求数据传输接近实时的话,那通常会通过批量或小批量方式进行。信息通常会放在本地文件系统中,常称为日志的文件,然后被传送到控制中心。最近开发的Kafka和Flume通常用于管理这些传输,并将传统的syslog、rsync或netcat整合在一起。数据最终可保存在本地或分布式存储(如HDFS、Cassandra或Amazon S3)中。
2.5.2 数据转换层
完成在HDFS或其他系统的存储后,需要处理数据。通常会按预定的计划处理数据,并且最终会按时间来划分。使用新的Scala流式处理框架时,处理时间可按天或小时为单位,甚至可以是次分钟(sub-minute),这取决于对延迟的要求。该处理过程可能涉及一些基本的特征构造(或向量化),这通常被认为是机器学习的任务。下表总结了一些有效的框架:
应该特别注意流处理框架,这种情形要求延迟减少到一次只有一个或几个记录。首先,流处理通常需要更多的处理资源,因为与处理成批记录不一样,若一次处理单个记录会更加昂贵,即使一次处理几十或几百个记录也是如此。所以,架构需要基于最近结果来判断附加成本,这并不能保证一定有。其次,流处理需要对架构进行一些调整,因为处理更新的数据有优先级;由单个子流或一组节点来处理最新数据的架构变得非常流行,比如目前流行的Druid(http://druid.io)系统。
2.5.3 数据分析与机器学习
机器学习(ML)算法用来计算可操作的聚合或摘要。从第3章到第6章都会涉及很复杂的机器学习算法。但在某些情况下,一个简单的滑动窗口平均,再加上偏离值就足够了。在过去的几年中,人们在进行模型构建和部署时还在采用A/B测试。作者并不是怀疑理论没有用,但许多基本假设(如独立同分布)、平衡设计和长尾现象在许多大数据情形下并不适用。更简单的模型往往会更快,并且具有更好的性能和稳定性。
例如,对于在线广告,仅仅需要跟踪一段时间内一组具有相似广告内容的平均表现就能决定是否投放此广告。关于异常或偏离的信息可能是新的不知之不知的信号,这表明旧数据不再适用,在这种情况下,系统不得不重新开始构建。
本书将在第6章、第8章以及第9章中讨论更复杂的非结构化数据、图和模式挖掘。
2.5.4 UI组件
在现实中,UI通常会让除数据科学家以外的人们感觉很不错。一个好的数据分析师应该够通过一张表的数据就能计算t检验。
应该评估不同组件的有用性以及所使用的次数。好的UI往往是合理的,但也与受众群体有关。
目前有一些UI和报表框架,它们中的大多数都不是基于函数式编程。由于复杂或半结构化数据的存在(将在本书第6章中做更详细的介绍),许多框架需要实现某种DSL才能做数据处理。下面介绍基于Scala构建的几个UI框架:
2.5.5 动作引擎
虽然这是数据导向的系统管道的核心,但它却最简单。一旦度量和值的系统是已知的,基于已知等式的系统将决定是否执行一组确定的动作,这些动作以提供的信息为基础。虽然基于阈值的触发是最常见的实现,但目前出现了一种概率方法,它可向用户呈现可能性和相关性,或者可以像搜索引擎那样向用户提供前N个相关的选择。
这会涉及规则管理。人们常用规则引擎(如Drools,http://www.drools.org)来管理规则。但管理复杂规则常常需要开发DSL(Domain-Specific Languages by Martin Fowler, Addison-Wesley, 2010)。Scala非常适合开发这种动作引擎。
2.5.6 关联引擎
决策系统越复杂,就越需要一个次级决策系统来优化它管理。DevOps正在变成DataOps(Getting Data Right by Michael Stonebraker et al., Tamr, 2015)。在数据驱动系统上收集到与性能相关的数据通常用于异常检测和半自动维护。
模型经常会漂移,其性能可能由于数据收集层的变化或群体的行为变化而恶化(将在第10章讨论模型漂移)。模型管理的另一方面是跟踪模型性能,在某些情况下,可通过各种共识方案来使用模型的“集体”智慧。
2.5.7 监控
监控系统会收集用于审计、诊断或性能调整的系统性能信息。虽然它与前面几节提出的问题相关,但监控解决方案往往包含诊断和历史存储的解决方案,以及关键数据(如飞机上的黑匣子)的持久性。在Java和Scala中,一种流行的工具是Java性能bean,它可以在Java控制台中进行监视。Java本身支持MBean,并用它来获取基于JMX的JVM信息。Kamon(http://kamon.io)是一个开源库,它也使用此机制来获取Scala和Akka度量。
Ganglia(http://ganglia.sourceforge.net/)和Graphite(http://graphite.wikidot.com)是另外一些流行的开源解决方案。这里不再介绍,因为第10章会对系统和模型监控进行更为详细地介绍。