在过去的几年间,我们一直致力于重构Digg的架构,现在我们称之为“Digg V4”.本文我们将全面介绍Digg的使用的系统和技术。找出Digg引擎的秘密。 首先,我们来看下Digg给大众用户提供的服务吧:
- 一个社会化的新闻站点
- 为个人可定制的社会新闻
- 广告平台
- API 服务
- 博客和文档站点
人们通过浏览器或者其他应用来访问这些Digg服务。一些有Digg账户的用户,可以得到“我的新闻”。每位用户可以得到的我们称之为“热门新闻”。我们有digg.com和移动版的m.digg.com,API服务的services.digg.com,信息介绍的about.digg.com,为开发者服务的developers.digg.com。这些站点统一为用户,新闻发布者,开发人员提供了博客和文档服务。
本文主要介绍Digg在社会化新闻产品中使用的高级技术。
我们努力要做的
我们努力搭建以用户发布新闻和广告商发布广告为基础 一个社会新闻站点。
故事提交 注册用户提交文章,文章包含:一个标题,一篇段落,一个媒体类型,一个主题,或者一个缩略图。这些内容通过一系列的元字符标准(Facebook open graph protocol, OEmbed等)如从文章中解压出来,当然提交者在提交前最后这些元字符具体是什么。广告发布商将广告发布到另外一个独立的系统,当然如果Dugg够的话,完全可以成为故事。
故事列表 在个性化新闻产品“我的新闻“里,你追随的用户发布的所有故事以“故事列表”显示,采用最近发布,媒体类型,故事的主题等方式排列。
故事动作 用户可以对故事进行操作,比如说阅读,点击,Digg,掩埋,发表评论,投票等等。没有注册登录的用户只能阅读和点击这些故事。
故事推荐 我们会决定每个小时有一些故事会从最近故事列表转移到热门新闻列表。我们的算法(这个是保密的)通过查看用户的行为和故事内容的分类来决定选择哪些故事进入热门新闻。
我们是如何实现它的?
让我们从宏观的角度看下如果一个用户访问Digg的站点,做一些基于内容的操作。下面的图片显示了公众看到的内容及内部提供的页面、图片、API请求等服务。
我们内部系统的简单描述如上。我们的API服务代理想内部后端服务进行请求。前端的服务是被虚拟化的(与缓存是有区别的),并且放置在相同的服务层。CMS和广告系统将在此文章中不做详细说明,纵览整个系统,大致可以分为以下两类:同步和异步。
1、对用户进行即时响应的同步操作
同步操作主要表示对用户请求(包括API请求)的即时快速响应,包括一些在页面中通过AJAX方式进行的异步请求。这些操作通常要求最长一两秒的时间内就能完成。
2、离线批量进行的异步计算
除了实时响应的请求外,有时候还需要进行一些批量的计算任务,这些任务可能是间接的被用户启动的,但用户不会等待这些任务的完成。这些异步计算通常可能会花费数秒,数分钟甚至几小时。
上面所说的两部分如下图所示:
下面就更加深入的了解各个组成部分。
线上系统
提供页面和API请求服务的程序主要以PHP(前端Web页面,Drupal CMS)和使用的Python(API服务,Tornado)编写。前端通过Thrift protocol协议来调用后端的服务(Python)。很多数据会被如Memcached 和Redis 这样的内存缓存系统缓存。
消息和事件
线上和离线的信息通过主要数据存储transient / logging系统这种同步方式连接和使用 RabbitMQ 作队列系统,将不用同步响应的操作放到队列异步地进行。比如说”一个用户Dugg了一个故事“,”计算这个东西“。
批处理和异步系统
上面的消息系统是指队列,而这个指的是具体从队列取出任务执行的部分。此系统将任务从队列中取出,进行一定的计算后再对主存储进行操作,对主存储的操作在实时系统和异步批量系统中都是一样的。
当队列中发现信息时,一个“工作者”被调用来完成特定的动作。一些信息由事件触发,有点象cron机制。然后工作者对主存储设备或者离线存储设备的数据进行运算和操作,在HDFS中记录日志,然后把结果写回到主存储设备,这样在线服务就可以使用他们。举个例子:比如说索引新的故事,计算故事提升算法,运行分析工作。
数据存储
Digg根据数据的类型和使用方式的不同,将数据存储在不同的系统中,当然,有时候还避免不了有一些历史原因。
- Cassandra:对诸如文章、用户、Digg操作记录等“类对象(Object-like)”的信息,都是使用Cassandra来存储的。我们使用的是Cassandra0.6版本,由于0.6版本并没有劫持二级索引,于是我们将数据通过应用层处理后再用它进行存储。比如我们的用户数据层提供通过用户名及Email地址来查询用户信息的接口。这样就允许了服务器能够查看,比如说,通过用户的用户名或者邮件而不是用户的用户ID来查询。这里我们使用了Python Lazyboy wrapper。
- HDFS:来自站点和API事件,用户活动的日志都在这里。主要用到日志信息存储及分析计算,利用 Hive 操作 Hadoop,进行MapReduce计算。
- MogileFS:是一个分布式文件存储系统,用以存储二进制的文件,比如用户头像,截屏图片等。当然,文件存储的上层还有统一的CDN。
- MySQL:目前我们的文章置顶功能上使用了MySQL存储一些数据,用来存储故事提升算法和计算的数据,因为这一功能需要大量的JOIN操作。很自然不适合其他类型的数据存储。与此同时 HBase 好像也是个不错的考虑。
- Redis:由于 Redis 的高性能及其灵活的数据结构,我们用它来提供对 Digg Streaming API 的存储,存储每个用户新闻数据,每个用户的新闻具有不同和需要及时更新的特征。同时用Redis来提供Digg Streaming API和real time view and click counts服务。作为一款基于内存存储的系统,它提供了超低的负载。
- SOLR:用来构建全文索引系统。以提供对文章内容、话题等的全文检索。
- Scribe:日志收集系统,比syslog-ng更强大更简单。用它收集的日志会被放到HDFS进行分析计算。
操作系统和配置
digg目前运行在基于GNU/Linux的Debian系统。配置了Clusto,Puppet。使用的是Zookeeper做系统协调。
原文链接:http://about.digg.com/blog/how-digg-is-built