1. 引入
Zillow是美国1.1亿套房屋以及房屋出租的信息来源。就摄取和存储而言,两者都需要大量数据。Zillow还使用外部数据源,包括来自Google Analytics(分析)的Clickstream数据。Zestimate团队在先前的博客文章中描述了他们如何使用数据作为事件流来加快Zestimates的计算。这篇文章将详细介绍我们如何开发用于处理点击流的数据管道以克服规模问题以及如何构建可用于数据收集和处理的通用平台。
2. 数据库中的数据
Zillow最初成立时使用了许多数据库来存储数据,并使用了高速缓存以实现快速搜索和快速查找。后来我们将Amazon S3标准化为数据湖提供商。
首先必须克服将数据库中的数据导入数据湖的挑战。最初我们使用自定义Sqoop作业直接从表中提取数据并将其导入S3,这解决了将数据导入S3的问题,但同时也引发了一些其他问题。
首先,由于Sqoop作业是由数据科学家/工程师开发的,他们可能不了解表的语义或如何将他们适用于产品中,而且他们必须不断处理表模式的演变。
其次,导出数据的模式与数据库(DB)的模式相同,但数据库模式不一定针对数据科学/机器学习应用程序进行了优化。
由于Sqoop作业每天运行,有时会影响数据库性能,因此DBA必须创建这些数据库的特殊只读副本,这导致了更多的维护和开销,但有时无法复制这些数据库中的某些数据,这迫使我们不得不从落后一天的旧数据库快照中读取数据。
3. 直接写入数据湖
产品团队开发了将数据直接写入S3的代码,这意味着可以直接发送数据至数据湖,但这也意味着无需实施模式。有些团队写json,而有些团队写文本文件或csv文件,这些文件的结构由不同团队定义并且不一致。在变更模式时,对于历史数据的回填时间也没有统一的规则。
此外,还需要团队创建和管理自己的AWS资源,如果他们直接写到S3,则需要创建适当的角色和凭据,如果他们使用firehose写入S3,则除了凭据之外还必须创建一个firehose流。
最后团队并不了解数据的治理和生命周期策略。例如,如果数据包含PII,则应将其加密, 否则,原始数据和处理后的数据应具有不同的生命周期策略。通常当直接写S3时,他们并不了解这些策略。
4. 数据流平台
为解决以统一形式将数据传输到数据湖的问题,我们开发了一种流平台服务,目标是将流处理作为服务进行构建和架构,以支持实时分析和机器学习应用程序,该体系结构包含如下主要原则。
4.1 构建流式架构
我们对使用Streams将数据发送到数据湖的过程进行了标准化。团队不需要了解流,他们只需要调用发送流数据的REST API即可。另外通过抽象底层技术,我们可以监视使用情况并根据需要进行扩容。团队可以在不了解流技术的情况下便可发送事件和其他数据集,团队无需关心流式架构,而只需专注于数据分析。我们使用持久路由表将消息路由到正确的目的地。
4.2 单应用程序单流
由于用户不再需要考虑底层的流技术,因此他们可以请求资源后直接使用,这使他们可以获取尽可能多的流资源,并以所需的粒度使用它们。
4.3 生产者和消费者流隔离
生产者流只能由基础架构团队访问以进行数据转换。由于不知道访问流的客户端数量及其访问方式,所以将消费者流与生产者流分开创建更安全的,这将确保使用者可以连接而不会影响接收消息的能力,这也使得我们能够分别扩展消费者和生产者流,从而能够维护我们为数据传输设置的严格的服务水平(SLA)。
4.4 发送数据至Kafka
对内部Kafka集群进行优化以支持更低延迟和更高的吞吐量,将数据发送至Kafka与架构中注册表紧密集成,以支持具有兼容性约束的消息。
4.5 支持通用处理/归档场景
通常当用户将数据发送到系统时,他们也希望能够轻松查询这些数据。为了支持这一点,我们实现了“流处理即服务”范式,通过该范式,发送到系统的数据会自动存档到Hive表中,并且可以使用Mode或Tableau查询最终用户(分析师和业务用户)的数据。
4.6 数据目录和发现
随着数据生产者和消费者的增长,需要进行分类以便知道谁在以何种格式和模式生产数据,另外也还需要知道谁是消费者,以便进行数据治理,并能够就上游数据集的问题或变更向数据消费者发送告警。为支持这一点,我们实现了一个可搜索的数据目录,该目录存储了有关所有数据实体和相关上下文(包括数据沿袭)的元数据。数据目录还用于标记具有特殊特征的数据集,例如个人身份(PI)数据和生命周期策略。
4.7 数据质量
需要检查流入系统的所有数据的质量,这可能包括模式检查,数据完整性检查以及度量标准值检查。我们采用了一项称为Luminaire的数据质量服务,该服务结合了启发式方法和模型来跟踪数据集的质量,它使用时间序列模型的集合来确保数据流符合我们的预期,否则它将向上游生产者发送告警。
5. 当前状态
当前,我们有以下类型的数据进入系统
6. 当前挑战
6.1 静态的架构工具
我们在Zillow大量使用terraform来创建基础构架,包括设置AWS资源(如kinesis和firehose),拆分EMR集群以处理数据等。但使用terraform按需拆分资源效果并不理想,尤其是当资源请求来自外部团队时,并且由于我们共享数据湖帐户,因此需要在人员之间进行周转。为了解决这个问题,我们正在缓慢迁移至Kafka,并且正在开发一个CICD管道,该管道可以自动创建Kafka主题并在架构注册表中注册Avro架构。
6.2 Kinesis生态
Kinesis允许限制每个分区容量,并可通过添加更多分区进行扩容。为最大程度利用分区容量,建议使用Kinesis Producer库(KPL)。我们的最开始的部署是使用KPL写入kinesis。但发现扩展性不是很好,因为我们的服务正在写入许多不同的流,并且KPL用于跟踪每个流的分区和每个分区的消息缓冲的开销导致服务消耗了很多JVM资源并且会挂掉。因此我们决定开发自己的KPL兼容库,该库提供了KPL的某些功能。换句话说,我们决定权衡kinesis 分区容量的效率和服务的稳定性。
另外,由于其他方面(例如Python)对KPL的支持还不够完善,它需要在另外运行本地语言守护程序。由于这些问题,我们认为迁移到Kafka能够提高分区的利用率以及服务稳定性。
7. 总结
通过创建数据流平台,使得团队能够轻松将数据发送到数据湖。现在用户可以请求资源,而无需联系AWS Account管理员。对所有发送的数据都会验证其模式,这将团队向数据湖发送数据的速度从数周提高到了几天,它还使数据团队能够对点击流数据获得新的见解,这有助于进行个性化推荐,如房屋详细信息页面上显示“相关房屋”。