# Pixable Architecture-每天对 2000 万张照片进行爬网，分析和排名

> 原文： [http://highscalability.com/blog/2012/2/21/pixable-architecture-crawling-analyzing-and-ranking-20-milli.html](http://highscalability.com/blog/2012/2/21/pixable-architecture-crawling-analyzing-and-ranking-20-milli.html)

*这是 Pixable 的 CTO PHD 的 Alberto Lopez Toledo 和 Pixable 的工程副总裁 Julio Viera 的来宾帖子。*

![](img/c757a58e9a5343904e20bc929f9dc75a.png) [可混合](http://new.pixable.com/)汇总来自您不同社交网络的照片，并找到最佳照片，因此您永远不会错过重要时刻。 这意味着当前每天要处理超过 2000 万张新照片的元数据：对它们以及已经存储在我们数据库中的其他 5+十亿张图像进行爬网，分析，排名和排序。 弄清所有数据都面临挑战，但尤其要强调两个挑战：

1.  如何每天以最有效的方式从 Facebook，Twitter，Instagram 和其他服务访问数百万张照片。
2.  如何处理，组织，索引和存储与那些照片相关的所有元数据。

当然，Pixable 的基础架构正在不断变化，但是去年我们学到了一些东西。 因此，我们已经能够构建可扩展的基础架构，以利用当今的工具，语言和云服务，所有这些都在 Amazon Web Services 上运行，其中我们有 80 多个服务器在运行。 本文档简要介绍了这些课程。

## 后端架构-一切都会发生

### 基础架构-喜欢 Amazon EC2

我们使用 CentOS Linux，使用从 t1.micro 到 m2.2xlarge 的各种实例在 Amazon EC2 上维护所有服务器。 设置服务器后，我们将创建自己的内部 AMI（每种类型的服务器一个）。 我们总是准备好在负载增加时立即部署它们，从而始终保持最低性能标准。

为了补偿这些负载波动，我们开发了自己的自动伸缩技术，该技术可以根据一天中特定时间的当前和历史负载来预测每种类型的服务器数量。 然后，我们启动或终止实例只是为了保持正确的配置水平。 这样，我们就可以通过在不需要服务器时缩减服务器规模来节省资金。 在亚马逊中自动缩放并非易事，因为要考虑许多变量。

例如：由于 Amazon 会收取整个小时的费用，因此终止仅运行了半个小时的实例是没有意义的。 此外，亚马逊可能需要 20 多分钟才能启动即时实例。 因此，对于流量的突然激增，我们对按需实例（启动速度更快）进行了一些巧妙的启动调度，然后在接下来的一个小时内将它们替换为现场实例。 这是纯粹的运营研究的结果，其目的是为了以适当的金额获得最佳性能。 可以把它想像成电影《 Moneyball》，但它带有虚拟服务器而不是棒球运动员。

我们的 Web 服务器当前运行 Apache + PHP 5.3（最近我们一直在微调一些 Web 服务器以运行 nginx + php-fpm，它将很快成为我们的标准配置）。 这些服务器平均分布在 Amazon Elastic Load Balancer 后面的不同可用性区域中，因此我们可以吸收 Amazon 的停机时间和价格波动。 我们的静态内容存储在 Amazon Cloud Front 上，并且我们将 Amazon Route 53 用于 DNS 服务。 是的，确实……我们爱亚马逊。

### 工作队列-用于抓取照片并对其进行排名，发送通知等的工作

实际上，Pixable 的所有处理都是通过异步作业完成的（例如，从 Facebook 抓取来自不同用户的新照片，发送推送通知，计算朋友排名等）。 我们有数十个工作服务器，它们从不同服务的照片中抓取元数据并处理该数据。 这是一个连续的，全天候的过程。

不出所料，我们有不同类型的工作：一些优先级高的工作，例如实时用户呼叫，消息收发以及为当前活动用户抓取照片。 优先级较低的作业包括脱机爬网和长时间的数据密集型延迟任务。 尽管我们使用功能强大的 [beantalkd](http://kr.github.com/beanstalkd/) 作为我们的作业队列服务器，但我们在其之上开发了自己的管理框架。 我们将其称为自动驾驶仪，它会自动管理优先级的处理，例如 通过将作业服务器时间用于高优先级作业，并在满足平台范围的某些条件时暂停低优先级作业。

我们开发了非常复杂的规则来处理这些优先级，同时考虑了影响系统性能和影响用户感知速度的指标。 有些是显而易见的，例如作业的平均等待时间或从属服务器的滞后时间（ssshhh，我们从不滞后于从属服务器:-)），而更复杂的指标则是分布式分布式 PHP 同步互斥锁的状态。 环境。 我们会尽力在效率和绩效之间做出公平的权衡。

### 抓取引擎-在 Facebook，Twitter 等 24/7 上抓取新照片

我们一直在不断改进抓取技术，这是一种复杂的并行算法，它使用内部开发的互斥锁库来为特定用户同步所有进程。 自推出以来，该算法已帮助我们将 Facebook 的抓取速度提高了至少 5 倍。 现在，我们每天可以轻松获取超过 2000 万张新照片。 考虑到事实上，对 [Facebook API](http://developers.facebook.com/) 的任何大数据查询都可能需要几秒钟的时间，因此这是非常出色的。 我们将在一个辅助文档中更深入地了解我们的抓取引擎。

### 数据存储-索引照片和元数据

自然，我们的数据存储每天都在增长。 目前，我们使用两组服务器将 90％的数据存储在 MySQL 中（其顶部是 memcached 层）。 第一组是 2 主 2 从配置，该配置存储几乎每个系统访问的更规范化的数据，例如用户配置文件信息，全局类别设置和其他系统参数。

第二个服务器组包含手动分片服务器，我们在其中存储与用户照片有关的数据，例如照片 URL。 此元数据已高度反规范化，以至于我们实际上仅以 MySQL 表（NoSQL-in-MySQL）的形式将存储作为 NoSQL 解决方案（如 MongoDB）运行。 因此，您可以猜测其他 10％的数据存储在什么地方，对吗？ 是的，在 MongoDB 中！ 我们将部分存储移至 MongoDB，主要是因为它提供了简单灵活的分片和复制解决方案。

### 记录，分析和分析

我们开发了高度灵活的日志记录和性能分析框架，该框架使我们能够以高粒度记录事件-只需一行代码。 每个日志事件均按一组我们稍后查询的标签进行分类（例如，用户 X 的事件或模块 Y 中的调用）。 最重要的是，我们可以动态地分析任何日志记录事件之间的时间，从而使我们能够构建整个系统的实时性能分析。 日志记录和概要分析系统在存储系统上的负担非常重（每秒数千次更新），因此我们开发了两级 MySQL 表（基于内存的快速缓冲区，用作实际数据的泄漏存储区）的混合体 存储），再结合一些分区的 MySQL 表，这些表稍后会异步填充。 这种架构使我们每秒可以处理 15,000 多个日志条目。 我们还拥有自己的事件跟踪系统，其中记录了从登录到共享到单个点击的每个用户操作，以便以后可以使用复杂的查询进行分析。

我们还严重依赖于出色的 [Mixpanel](http://www.mixpanel.com/) 服务，这是一个基于事件的跟踪系统，我们在其中执行大部分高级分析和报告。

## 前端-简单的可视化设备

Pixable 可在多个（前端）设备中运行，最受欢迎的设备是 iPhone 和 iPad。 我们也有加载简单索引页的 Web 和移动 Web 站点，其他所有操作都通过广泛使用 jQuery 和 Ajax 调用在客户端中执行。 我们所有的 Web 前端都将很快运行一个可自动适应移动或桌面屏幕的代码库（尝试一下！ [http://new.pixable.com](http://new.pixable.com/) ）。 这样，我们可以在我们的主站点，Android 设备或 Chrome 浏览器扩展程序上运行相同的代码！ 实际上，我们的 Android 应用是原生应用和我们的移动网络前端的结合。 Android 应用程序使用最少的控件来渲染框架，并仅在其中显示移动 Web 视图。

听起来有些刺耳，但是我们所有的前端都是“哑巴”。 所有繁重的工作都在后端执行，所有事情都通过我们自己的私有 API 连接。 这使我们能够快速进行开发和部署，而不必更改已安装的用户群。 敏捷，宝贝！

## API-连接我们的前端和后端

API 是使一切保持协同工作的粘合剂。 使用 [Tonic PHP](http://peej.github.com/tonic/) ，我们开发了自己的私有 RESTful API，该 API 公开了我们的后端功能。 另外，我们扩展了 [Tonic](http://peej.github.com/tonic/) ，使其支持内置版本控制。 这样一来，在开发新功能或更改 API 中的响应格式时，我们很容易保持向后兼容性。 我们只配置哪个设备版本支持哪些版本的 API 调用。 无论版本多旧，我们都有不留设备的政策！

但是 API 并没有做任何实际的工作。 它仅依赖于来自前端的信息，并将其传递给实际的 Pixable 心脏：后端。

每天排名 2000 万张照片？ 真的很棒

值得读。 谢谢你的好文章。