×

如何架构一个数据工程

96
chen_h
2017.12.14 13:39 字数 2064

1. 介绍

在我们深入讨论这个 “数据工程” 业务细节之前,我们需要先知道标准(PyData)机器学习数据管道的局限性,如下图所示:

典型的 PyData 机器学习数据管道设计,通过 Python 脚本完成链接(通常是单线程)

模型的优点

  • 低门槛
  • 快速部署

模型的缺点

  • 可扩展性差

对于机器学习可扩展性差问题的解释,可以查看这篇文章,有非常详细的解释。在这里,我们将采用一个更加简单的方式来说明这3个问题,为什么这个数据管道的加载是如此的重。

1. 太多的计算

如果我们开始增加一个单线程来加载 PyData 数据管道,那么这种操作最终肯定是会失败的。我们不能将这种操作扩展到单个节点之外,也就是说,如果你的数据太巨大以至于不能在内存中操作,那么你需要对其进行批量处理,否则你将无法进行处理。如果你没有足够的CPU资源去训练一个模型,那么你只能去购买一个更好的处理器来解决这个问题,但是如果你已经拥有了一个很好的处理器,那么接下来又会发生什么呢?更糟糕的是,因为模型的数据输入请求是由一定的速率要求的,如果模型不能按照一定的速率得到预测结果,那么这将成为整一个系统的性能瓶颈。Python 中的多线程是有限的,如果一个线程失败了,那么系统是没有办法优雅的去切换到默认值,所以我们只能失败。

上述所有的问题都可以通过拆分 - 应用 - 组合的策略来解决,该策略允许将一个任务分割成多个子任务然后并行子啊不同的线程或者节点上面去计算,最后将计算结果进行合并,加快数据管道的处理效率。MapReduce 的思想就是来解决这个问题的,我们可以用任何的语言来实现这一个算法,但是你会度过几小时的痛苦时间,因为从零开始编写 MapReduce 是一件非常疯狂的事。一个可行的方式是我们利用 Hadoop 的 MapReduce 或者 Spark 的。Hadoop 的操作可能会慢一点,因为它每次操作之后都会发生磁盘读写操作(所以现在几乎没有人使用它),但是 Spark 所有的计算都是发生在内存中,加快了机器学习算法的迭代速度,甚至比一般的流水式数据管道还要快(但是你需要一个很大的内存空间)。

由于 Spark 不但提供了数据批处理和流处理,它还提供了 Spark ML 这一个强大的包。这个包允许你进行分布式机器学习操作,用 Spark jobs 可以完全替代 Python 脚本中的 PyData 数据管道和模块之间的连接器,而且可以很方便的在分布式集群上面运行,线程失败了可以正常重启。

2. 太多的数据

让我们试想一下,我们已经用 Spark jobs 和 Spark ML 模块替代了典型模型 PyData ML Pipeline 中的中间脚本,如下图所示:

Improved pipeline

在这个数据管道中还存在一个弱点:DB。当处理的数据量超过 5TB 的时候,关系数据库的处理能力表现不佳。关系数据库的分片和复制是一个本身就存在的大问题,如果你想要去支持如此大的数据量,那么这必将是一个昂贵的冒险行为。所以当我们的数据量在达到 5TB 的天花板之前,可能需要放弃关系型数据库。

那么,对于大数据来说,还有那些其他的数据存储方案可以选择呢?首先,需要一个分布式数据存储系统,它能够对抗如下问题:

  • 硬件故障导致的数据丢失问题
  • 需要一个高的吞吐量
  • 可以扩展到很多的数据平台

Hadoop 分布式文件系统(HDFS)满足于以上所有特性,这是 Apache Hadoop 项目中的一部分。而且这个可以在本地硬件集群上面设置 HDFS,如果你有几个 DevOps 专家,那么你就可以部署到任何你喜欢的地方了。为了存储一些冷数据,我们可以考虑 AWS S3 作为存储器。但是如果你考虑到速度性能,建议不要把 S3 作为整个模型的一部分。最好将这些热数据存放在计算资源的附近,比如计算资源是在云服务器上面,那么最好将数据存放在本地的 HDFS 集群或者云 HDFS 集群中。

但是这个只是分布式数据的基础设施,那么存储数据的方式呢?

正如我们已经想到的那样,利用关系型数据库是一个糟糕的选择。那么,采用纯文本的方式呢?令人惊喜的是,.csv 或 .tsv 文件通常是可以被存储在 HDFS 系统上的,作为快速和不加判断的方式来存储从外部服务中提交的数据(比如,脚本批量接受的数据)。

优点

  • 快速存储

缺点

  • 最大容量是有限的
  • 需要去读取整个文件
  • 查询不是很容易

那么 NoSQL 数据库呢?请注意,并不是所有的 NoSQL 数据库都是分布式的。

优点

  • 查询方便
  • 高吞吐量

缺点

  • 维护成本高

Cassandra 是分布式 NoSQL 数据库的一个典型选择,但是他仍然需要一个专门的 DevOps 来设置,维护,监视,扩展等等。因此,分布式 NoSQL 是存储数据的默认选项,因为我们需要一个可以方便查询的数据库。

对于那些想要减少 DevOps 人员工作量的人来说,有一个简单的解决方案就是使用 Parquet

优点

  • 与 Spark 能很好的结合
  • Columnar,这可以让分析人员加快查询速度
  • 不是分布式数据库,只是一些文件,较少维护工作
  • 读取速度很快
  • 存储效率很高

缺点

  • 架构混乱
  • 迭代困难

我们把上面讲的架构设计都反应在一张图中,如下图:

3. 杂乱的数据管道

随着 spark jobs 数量的增加,数据管道变得杂乱无章,所以有很多的事情需要去处理:

  • 作业调度
  • 时间依赖型的作业
  • 逻辑相关的作业(任务链)
  • 监控和报警
  • 故障转移恢复(重试失败的作业,而不是整个数据管道)
  • 作业可视化(仪表盘)
  • 其他工作流的管理方式

有一些解决方案可以去管理重新编排这些数据管道,我们来重点来介绍其中的 2 个。

Luigi

Python 开发的一个简单的工作流管理解决方案,由 Spotify 开源。

优点

  • 低门槛
  • 依赖管理(链式结构)
  • 具有状态和错误跟踪的 WEB UI 集中式作业管理器
  • 故障恢复

缺点

  • 没有调度
  • 没有流媒体
  • 难以扩展

Airflow

更加复杂和有效的工作流管理工具,由 Airbnb 开发和开源。

优点

  • 所有上述的优点 + 调度和可扩展性

缺点

  • 由于功能的强大,所有学习门槛有点高

总结

最后,我们可以画出我们一整个数据工程架构图。如下图所示:


来源:Medium

Deep Learning
Web note ad 1