# 接下来的大型声音如何使用 Hadoop 数据版本控制系统跟踪万亿首歌曲的播放，喜欢和更多内容

> 原文： [http://highscalability.com/blog/2014/1/28/how-next-big-sound-tracks-over-a-trillion-song-plays-likes-a.html](http://highscalability.com/blog/2014/1/28/how-next-big-sound-tracks-over-a-trillion-song-plays-likes-a.html)

![](img/7983a905c376ef6b7f410040a654d96a.png)

*这是 Next Big Sound 的首席架构师 [Eric Czech](http://www.linkedin.com/profile/view?id=26317730) 的来宾帖子，讨论了解决音乐分析中可伸缩性挑战的一些独特方法。*

跟踪在线活动并不是什么新主意，但是要在整个音乐行业中做到这一点并不容易。 每天有五十亿个音乐视频流，曲目下载和艺术家页面喜欢出现，并且衡量跨 Spotify，iTunes，YouTube，Facebook 等平台的所有活动的可能性带来了一些有趣的可扩展性挑战。 Next Big Sound 从一百多个来源收集此类数据，将所有内容标准化，并通过基于 Web 的分析平台提供该信息以记录唱片公司，乐队经理和艺术家。

尽管我们的许多应用程序都使用诸如 Hadoop，HBase，Cassandra，Mongo，RabbitMQ 和 MySQL 之类的开源系统，但是我们的用法是相当标准的，但是我们这样做的一个方面是非常独特的。 我们从 100 多个来源收集或接收信息，我们很早就努力寻找一种方法来处理这些来源的数据随时间变化的方式，最终我们决定需要一个可以代表这些变化的数据存储解决方案。 基本上，我们需要能够以与使用修订控制（通过 Git）控制创建数据的代码几乎相同的方式对这些源中的数据进行“版本化”或“分支化”。 为此，我们在 Cloudera 发行版中添加了一个逻辑层，并将该层集成到 Apache Pig，HBase，Hive 和 HDFS 中之后，我们现在有了一个基本的版本控制框架，可用于 Hadoop 集群中的大量数据。

作为一种 [Moneyball for Music，](http://www.forbes.com/sites/zackomalleygreenburg/2013/02/13/moneyball-for-music-the-rise-of-next-big-sound/)“ Next Big Sound 已经从 MySpace 上的一台服务器 LAMP 站点跟踪播放（开始之初很酷）发展为少数艺术家，从而发展了整个行业[ 广告牌的流行度图表[以及在 Spotify](http://www.digitaltrends.com/social-media/billboard-social-networking-music-chart-debuts/) 上播放的每首歌曲的[摄取记录。 数据的增长速度已接近指数级，而分布式系统的早期采用对于保持数据的更新至关重要。 跟踪了来自公共和私有提供商的 100 多个来源，处理音乐分析的异质性需要一些新颖的解决方案，这些解决方案超出了现代分布式数据库免费提供的功能。](http://www.spotifyartists.com/spotify-next-big-sound-artist-analytics/)

Next Big Sound 也已经在全云提供商（Slicehost），混合提供商（Rackspace）和托管（ [Zcolo](http://www.zayo.com/services/colocation) ）之间进行了过渡，而这些工作全部由小型工程人员使用，除了开放源码系统外什么也没有。 在这个过程中我们不乏经验教训，我们希望其他人可以从我们的成功和失败中汲取教训。

## 统计信息

*   40 个节点 Hadoop 集群（150TB 容量），约 60 个 OpenStack 虚拟机

*   10TB 的未复制压缩指标数据（原始 6TB，已索引 4TB）

*   10 名工程师，共 22 人

*   5 年的发展

*   每天 30 万次时序查询

*   每天有 400G 新数据，处于峰值

*   为超过 100 万名艺术家录制了超过 1 万亿个事件，包括 YouTube 音乐视频观看次数（ [Kris Schroder 的 Google I / O 演讲](http://commondatastorage.googleapis.com/io-2013/presentations/1122%20-%20Find%20the%20next%20big%20thing%20with%20the%20YouTube%20Analytics%20API.pdf)  [ [GNIP](http://gnip.com/sources/twitter/) ），iTunes 购买和在线广播流（通过[与 Spotify](http://www.spotifyartists.com/spotify-next-big-sound-artist-analytics/) 的合作伙伴关系）

## 平台

*   **托管**：通过 [ZColo](http://www.zcolo.com/) 托管

*   **操作系统**：适用于 VM 和物理服务器的 Ubuntu 12.04 LTS

*   **虚拟化**：OpenStack（2 个 Dell R720 计算节点，96GB RAM，2 个 Intel 8 核 CPU，15K SAS 驱动器）

*   **服务器**：主要是 Dell R420、32GB RAM，4 个 1TB 7.2K SATA 数据驱动器，2 个 Intel 4 核 CPU

*   **部署**：詹金斯

*   **Hadoop** ： [Cloudera（CDH 4.3.0）](http://www.cloudera.com/content/cloudera/en/products-and-services/cdh.html)

*   **配置**：厨师

*   **监控**：Nagios，神经节，Statsd +石墨， [Zenoss](http://www.zenoss.com/) ，[立方体](http://square.github.io/cube/)，[口红](http://techblog.netflix.com/2013/06/introducing-lipstick-on-apache-pig.html)

*   **数据库**：HBase，MySQL，MongoDB，Cassandra（最近放弃使用 HBase）

*   **语言**：PigLatin + Java 用于数据收集/集成，Python + R + SQL 用于数据分析，PHP（ [Codeigniter](http://ellislab.com/codeigniter) + [Slim](http://www.slimframework.com/) ），JavaScript（ [AngularJS](http://angularjs.org/) + [Backbone.js](http://backbonejs.org/) + [D3](http://d3js.org/) ）

*   **处理**：黑斑羚，猪，蜂巢， [Oozie](http://oozie.apache.org/) ， [RStudio](http://www.rstudio.com/ide/docs/server/configuration)

*   **联网**：瞻博网络（10Gig，带自动故障转移功能的冗余核心层，机架上有 1 个 Gig 访问交换机）

## 存储体系结构

使用 Cassandra 和 HBase 等分布式系统存储时间序列数据相对简单，但是管理数据随时间变化的方式则要简单得多。 在 Next Big Sound，来自 100 多个源的数据聚合涉及某种传统的 Hadoop [ETL](http://en.wikipedia.org/wiki/Extract,_transform,_load) 管道，其中原始数据通过 MapReduce 应用程序，Pig 或 Hive 处理，并将结果写入 HBase，以便以后通过[进行检索。 Finagle](http://twitter.github.io/finagle/) / [节俭](http://thrift.apache.org/)服务； 但有一个转折。 Hadoop / HBase 中存储的所有数据均由特殊的版本控制系统维护，该系统支持 ETL 结果随时间的变化，从而允许定义处理管道的代码中的变化与数据本身保持一致。

我们在 Hadoop 中管理数据的“版本”方法是对 [Linked.in 数据周期](http://data.linkedin.com/blog/2009/06/building-a-terabyte-scale-data-cycle-at-linkedin-with-hadoop-and-project-voldemort)中所用技术的扩展，其中 Hadoop 的结果将定期重复进行完全重新计算并自动替换 [Voldemort](http://www.project-voldemort.com/voldemort/) 中的旧结果集具有可恢复的版本控制。 我们系统的区别在于版本控制不仅发生在全局级别，还发生在许多可配置的更深层次上。 例如，这意味着，如果我们在 Twitter 上记录艺术家所在国家/地区的转推数，并且发现对推文位置进行地理编码的逻辑在几天内是错误的，那么我们只需创建新的数据版本即可 那些日子，而不是重建整个数据集。 现在，这些新版本中的每一个都将具有不同的值，并且可以将某些版本的访问权限限制为某些用户。 开发人员可能只会看到最新版本，而普通用户将看到旧版本，直到确认新数据正确为止。 像这样的“分支”数据对于跟上数据源和客户请求的变化以及支持有效的增量数据管道至关重要。

有关该系统的更多详细信息，此图描绘了上述一些关键差异。

[](https://dl.dropboxusercontent.com/u/65158725/hadoop_arch.png)

有关更多详细信息，请查看 [论文：HBlocks：用于迭代数据工程的 Hadoop 子系统](https://dl.dropboxusercontent.com/u/65158725/hblocks.pdf) 。

除了 Hadoop 基础架构，我们还面临许多其他挑战。 跨社交网络和内容分发站点映射音乐行业中实体的关系，构建 Web 应用程序以对数百万个数据集进行排序/搜索，以及通过数百万个 API 调用和 Web 爬网管理信息收集，都需要专门的解决方案。 我们仅使用开源工具来完成所有这些工作，下面简要介绍了这些系统之间的相互关系。

[![](img/71a5dfef96b935acef0ce26a6451573f.png)](https://dl.dropboxusercontent.com/u/65158725/nbs_arch.png) 

*   **数据表示**：我们的指标仪表板的构建一直是一个正在进行的项目，大部分都是由我们的客户指导的。 要在灵活性和学习曲线之间取得适当的平衡，是一个移动目标，其中有许多不同的数据集，并且维护一致的 JavaScript / PHP 代码库来管理这些代码，这对每个新客户和新功能都将变得更加困难。 以下是到目前为止我们如何处理的一些要点：

    1.  从简单的 Codeigniter 应用开始，尝试尽可能多地整合 Backbone，现在（积极地）转向 Angular
    2.  大型静态对象的内存缓存（例如国家/地区与州之间的映射）
    3.  用于指标数据缓存和历史记录的本地存储（即，当您重新加载页面时，这就是我们之前所知道的方式）
    4.  用以前使用过的[人力车](http://code.shutterstock.com/rickshaw/)进行的 D3 绘制图形

    同样，我们对功能标志不做任何花哨的事情，但是我们不断地使用它们的基本实现。 在一直被重写的代码库中，它们一直是一个至关重要的（尽管有时是混乱的）常量，如果没有它们，我们将无法完成许多工作。

*   **查找**：我们已投入巨资开发产品，使我们的用户能够根据多种标准在我们的数据中搜索有趣的歌手或歌曲（我们称其为“ “查找”产品）。 与音乐的股票筛选器类似，该产品可让用户按“在以前从未出现在某种流行度图表上的 YouTube 视频观看次数的 30％-40％范围内说唱艺术家”等条件过滤后对结果进行排序。 此基础结构的大部分驻留在 MongoDB 中，该位置由 MapReduce 作业提供索引丰富的集合，并在数百万个实体中提供近乎即时的搜索功能。

    在 MongoDB 上构建这种类型的产品效果很好，但是索引限制一直是一个问题。 我们目前正在探索更适合这种用例的系统，特别是 ElasticSearch。

*   **内部服务**：我们的产品和 API 使用的所有度量标准数据均从内部 Finagle 服务提供，该服务从 HBase 和 MySQL 读取。 这项服务分为多个层（所有层都运行相同的代码），在这些层中，我们的产品直接使用了更关键的低延迟层，而第二层则具有更高的吞吐量，但具有更高的 90％延迟 程序化客户。 两者中的后者往往更加突发和不可预测，因此使用这样的单独层有助于使客户的响应时间尽可能短。 这也是一种方便的拆分方式，因为这意味着我们可以为关键层构建更小的虚拟机，然后将其他 Finagle 服务器阵列并置在我们的 Hadoop / HBase 计算机上。

*   **下一个 Big Sound API** ：我们已经在对外公开以及在内部为产品提供动力的主要 API 上进行了许多迭代。 以下是一些我们发现最有影响力的最佳做法：

    1.  不要构建仅公开方法的 API，不要构建对系统中的实体建模的 API，并让 HTTP 动词（例如 GET，PUT，POST，HEAD，PATCH，DELETE）暗示这些实体的行为。 这使得 API 的结构更容易推断和试验。
    2.  对于需要实体*关系*的方法，请对主要实体使用类似“字段”参数的方法，并让该参数中的字段存在暗示实际上需要查找什么关系。 对我们来说，这意味着我们的 API 公开了带有“ fields”参数的“ artist”方法，该方法仅在将字段设置为“ id，name”时返回艺术家的姓名，但也可能返回有关 YouTube 艺术家的数据 频道及其上的所有视频（如果字段设置为“ id，名称，个人资料，视频”）。 获取实体之间的关系可能很昂贵，因此这是保存数据库查询的好方法，而无需编写一堆丑陋的组合方法，例如“ getArtistProfiles”或“ getArtistVideos”。
    3.  使用外部公开的 API 来构建自己的产品始终是一个好主意，但是我们看到的另一个微妙的优势是新加入 Web 开发人员。 过去，我们在 JS 代码和 API 调用之间放置了很多 PHP 代码，但现在试图将交互作用严格地限制在 JavaScript 和 API 之间。 这意味着网络开发人员可以将精力集中在他们熟知的浏览器代码上，并且可以与他们喜欢的 Backbone 和 Angular 框架更好地协作。
*   **警报和基准**：音乐世界中总是发生着很多事情，我们尝试在所有噪声中挖掘重大事件的一种方法是通过对整个平台的数据进行基准测试（例如 确定每天发生的 Facebook 喜欢次数的总体趋势），并在客户关心的艺术家看到活跃的活动高峰时提醒我们的客户。 我们在此方面存在一些早期的可伸缩性问题，但我们已经解决了大多数问题，致力于将仅 Pig / Hadoop 用于其结果存储在 MongoDB 或 MySQL 中。 剩下的问题集中在如何为“重要”设置阈值上，到目前为止，我们最大的收获是在线活动趋向于全球趋势和峰值，因此基准必须考虑尽可能多的数据，而不能仅仅关注 在单个实体（或本例中的艺术家）上。 与这些更全面的基线的偏离是*实际*行为变化的良好指示。

*   **Billboard Charts** ：我们向 Billboard 杂志授予了两张图表，一张用于在线艺术家的整体流行度（[社交 50 图表](http://www.billboard.com/charts/social-50)），而另一张基本上是试图预测哪些艺术家最有可能 以便将来列出该列表（[下一个大声音图表](http://www.billboard.com/charts/next-big-sound-25)）。 计算这些图表不会带来任何重大的缩放挑战，因为它只是对所有艺术家的计算得分进行反向排序，但是生成经过精打细算，具有重复数据删除功能且值得生产的列表是需要考虑的。 我们系统中的重复或几乎重复的艺术家以及这些艺术家与他们的在线个人资料的关联存在很多问题（例如，贾斯汀·比伯的 Twitter 用户名是“ justinbieber”，“ bieber”还是“ bieberofficial”？）。 解决这样的问题通常需要自动化和人机交互的结合，但是当在过滤例程中避免误报非常重要（即，即使删除一个合法的艺术家是一个大问题）时，手动管理也是必要的。 但是，我们发现，通过记住执行的动作然后具有重播这些动作的功能的系统来增加这种管理是非常有效且易于实现的。

*   **预测性广告牌得分**：我们产生的更有趣的分析结果之一是[专利算法](http://making.nextbigsound.com/post/68287169332/predicting-next-years-breakout-artists)，用于计算艺术家在下一次“突破”时的可能性 年。 此过程涉及[随机梯度增强](http://astro.temple.edu/~msobel/courses_files/StochasticBoosting(gradient).pdf)技术的应用，以基于不同社交媒体号码的“病毒性”来预测这种可能性。 除了数学之外，这很难做到，因为我们使用的许多工具都没有 Hadoop 友好的实现，并且我们发现 [Mahout](http://mahout.apache.org/) 不能在基本应用程序之外运行。 然后，我们针对此类过程的体系结构包括通过 MapReduce 作业构建并写入 MongoDB 或 Impala 的输入数据集，然后通过 [R-Mongo](http://cran.r-project.org/web/packages/RMongo/index.html) 和 [R-Impala](http://cran.r-project.org/web/packages/RImpala/index.html) 引入 R 中，然后进行处理 在单个巨型服务器上使用 R 的一些并行处理库，例如[多核](http://cran.r-project.org/web/packages/multicore/index.html)。 使用 Hadoop 进行大多数繁重的工作，并将其余的工作留给单个服务器存在一些明显的局限性，目前尚不清楚我们最终将如何解决这些问题。 [RHadoop](https://github.com/RevolutionAnalytics/RHadoop/wiki) 可能是我们最大的希望。

## 托管

*   推出自己的网络解决方案很糟糕。 如果您要组成一个小型团队，请确保您已经有人专心完成以前完成的任务，否则请找人。 这很容易成为我们托管的最大痛苦（也是一些令人恐惧的中断的原因）。

*   在托管服务提供商之间移动总是很棘手，但如果您预算要在运行于两种环境中的机器上不可避免地花费的额外资金，则不必冒险，它们或多或少地在做同一件事。 除了一些不可避免的例外，我们总是最终在关闭任何旧资源之前，在新的提供程序中完整地复制体系结构，并且通常会进行一些增强。 供应商之间的共享系统似乎永远无法正常运行，通常节省下来的钱不值得缺少睡眠和正常运行时间。

*   由于我们约有 90％的容量专用于 Hadoop / HBase，并且工作负载真正稳定，因此很难超越拥有自己的服务器所带来的价格。 由于用户流量，我们的工作量并不是每天都突发，因为与正在进行的所有内部号码处理相比，该流量很小。 我们确实必须定期增加容量，但是将其作为步进功能很好，因为这些增加通常与大客户或数据合作伙伴的收购相吻合。 这就是为什么我们继续使用自己的硬件每月可节省约 2 万美元的原因。

## 获得的经验教训

*   如果您要汇总来自许多来源的数据并对其进行适度的转换，那么您将犯错误。 在大多数情况下，这些错误可能很明显，您可以在将它们投入生产之前将其修复，但是在其余时间中，一旦它们出现，您将需要适当的地方来对其进行处理。 这是我们在意识到这一点之前经历了很多次的场景：

    1.  为 Twitter 艺术家的追随者收集 TB 级的数据集，在一两天内将其加载到数据库中。
    2.  让客户知道数据已经准备好了，而让我们知道这些数据真是太棒了。
    3.  （一个月后）等等，为什么所有追随者中有 20％生活在堪萨斯州的大黄？
    4.  哦，将位置名称转换为坐标的代码会将“ US”转换为该国家中部的坐标。
    5.  好的，既然客户仍在使用数据集的正确部分，我们就不能删除整个内容，而只能对其进行重新处理，将其写入新表中，更新所有代码以读取两个表中的所有代码，仅从中获取记录 如果新表中不存在旧表，则在重新处理完成后删除旧表（容易吗？）。
    6.  一百行骇人的意大利面条代码（永不消失），几天后，工作完成。

    在某些情况下，可能有一种更聪明的处理方式，但是当您遇到足够多的情况时，很显然，您需要一种更新生产数据的好方法，而不仅仅是将其完全删除和重建。 这就是为什么我们要为它构建系统的麻烦。

*   我们的大多数数据都是使用 Pig 生成和分析的。 它功能强大，几乎我们所有的工程师都知道如何使用它，并且它作为我们存储系统的中坚力量发挥了很好的作用。 搞清楚它到底在做什么，到底有什么进展，我们发现 Netflix 的 Lipstick 对此很有帮助。 我们还发现，用 Pig 来缩短开发迭代的时间很重要，而不是具有较高的可见性。 必须花时间在运行时间更长的脚本上智能地构建示例输入数据集，这些脚本会生成 20 多个 Hadoop 作业，然后再尝试对其进行测试。

*   从 0.4 版本开始，我们就使用了 Cassandra 多年，尽管初期经历过恐怖的经历，但是当我们离开它时，它确实很棒。 这一举动与 Cassandra 并没有多大关系，而实际上只是由于我们在重建存储架构时希望使用 Cloudera 平台的结果。 在广泛使用 HBase 和 HBase 之后，我们吸取的教训是，对于大多数人来说，争论使用哪种可能只是浪费时间。 一旦我们了解如何对其进行调整，它们都可以可靠地工作并表现良好，并且专注于我们的数据模型（例如，键压缩方案，行大小上限，使用可变长度整数，查询访问模式）产生的变化要大得多。

[下一个 Big Sound Blog](http://blog.nextbigsound.com/) 也有一些关于音乐行业数据挖掘的有趣帖子，如果您真的喜欢这种事情，我们总是[招聘](https://www.nextbigsound.com/about#join)！

因此，这些算法将以博弈数据为基础来制定自我强化的商业决策，而这将花费所有人类的技巧和投入。 知道了，商业音乐变得更加孤立和注重结果，而计算机会告诉我们我们想要什么，然后我们就会喜欢它。 明白了，音乐品味的天网。