Reddit月浏览量从百万扩容到十亿的陷阱和教训

伯乐在线导读:Reddit[1]是一个社交新闻网站。用户可以将互联网上搜集或原创的图片或材料以帖子形式发布于网站上。而后其他用户可以投票,投票的结果将作为帖子排名的依据。

Reddit 网站的第一位领薪雇员杰里米·埃德伯格在RAMP[2]讨论会上做了一次出色的演讲 ,他教给我们很多关于如何创建一个成功的社交网站。这儿可以看到视频。

杰里米借用了(宗教里对比)罪恶和美德的方式来总结经验教训,他分享了在扩展Reddit过程中所犯错误的例子,也可以看到他们同样做了很多正确的事情。不过有点令人吃惊的是,杰里米现在是Netflix[3]的可靠性架构师。所以这篇文章中也有Netflix的一些经验。(感谢 dryrun 的热心翻译和详细的译注,感谢@战斗的那美克星人 的重审校对。如果其他朋友也有不错的原创或译文,可以尝试提交到伯乐在线。)

我完全认可的一些经验教训:

  • SSD[4]看做是便宜的内存[5],而不是昂贵的硬盘。当我们为了数据库的性能将reddit从普通硬盘转移到SSD后,我们的服务器数量从12台降低到1台(这个很可能是个比例数据,译者),并且还有很大的富余。SSD虽然贵了四倍,但是你会得到16倍的性能提升,这么做是很值得的。
  • 给用户一些权力,看看他们怎么做,然后考虑把好的点子加入到网站功能中来。用用户让reddit学到了很多东西,并且,用户很大程度上提升了网站的流畅度(文后会有描述用户如何协助网站的顺利运转,译者),这个是我众多收获中很重要的一点。用户会告诉你很多你不知道的事情。关于这点,reddit gold是个很好的案例,这个项目开始只是社区里的一个玩笑,后来它被做成了产品,并深得所有用户喜爱。
  • 项目之初关于可扩展性架构的考虑其实是没有太多必要的。一开始时你不知道什么会是你的功能集,所以你也不会知道你有哪些扩展问题。随着你的网站增长,你可以了解哪里将存在扩展问题。
  • 把未登录用户当作二等公民。给未登录用户返回缓存内容,Akamai(美国著名CDN服务提供商)[6]首当其冲,reddit压力大减,这种做法带来巨大的性能提升。

 

还有很多。我们从早期扩展reddit的错误中学到许多经验教训,下面是我的观点的一些解释和展开:

统计

  • 流量大约每15个月增加1倍。
  • 上个月(8月份),来自177个不同国家的 73,293,644 名独立访客查看了reddit的 4,885,611,148 个页面。“10亿的PV承载能力”来自这个数据。不确认现在的架构是否会有很大不同。
  • 28名雇员。
  • 每名雇员应对大约240万独立访客。(链接
  • 数以千计的版主。
  • 在2012年时,他们用240台服务器,支撑每月20亿页面浏览量和Postgres[7]里的2TB数据。所有高流量压力数据从EBS[8]转移到本地临时磁盘。

 

起源故事

  • Reddit始于2005年。在带着“通过文字来点餐”的想法去Y Combinator[9]被拒绝后,他们和Paul Grahm讨论并着手开始建设互联网网页。这就是reddit。那时他们并不知道Digg[10]
  • 从数据中心开始,随后将功能逐步转移至EC2[11]

1 在2006年在EC2上开始使用S3[12]提供标识的存储和服务。

2 2007年开始使用S3支持缩略图。

3 2008年使用EC2提供批处理服务,并通过vpn通道连接数据中心。

4 2009年使用EC2服务整个网站。网站停运一天,将数据全部迁移到EC2。稍后会谈到著名的数据重力例子。

 

EC2

  • 迁移到EC2上的动机

5 堆叠机架不好玩。不想租用更多的机柜和购买更多的服务器。

6 数据中心增长过快,增速在早期无法预测。

7 4人一组的开发团队的使用价格,EC2比在旧金山的数据中心成本节约29%。

  • EC2不是灵丹妙药。你要经受更高的网络延迟和嘈杂的邻居,所以计划好应对方案。好处是你可以随时按需扩容。
  • 持续跟踪EC2的资源限制

8 所有资源都有账户配额。

9 甚至亚马逊自己都不清楚什么地方可能有配额。

10 跟踪配额,并在需要的时候提升。

11 捕获异常以确认什么时候又达到了配额上限。

 

架构

  • Reddit的架构很简单。用户连接网络层,网络层对话应用层。应用层跟memcache[14],Cassandra[15],以及Postgres对话。Postgres使用主从配置。批处理系统使用Cassandra和Postgres。
  • 对比netflix,使用面向服务架构,所有组件之间通过REST API进行交互。

12 优点:更容易自动调节,因为只是有问题的服务需要调节;更容易规划容量;问题也更容易定位,因为它们在REST调用背后都是孤立的;改动和升级产生的影响范围更小;更高效的本地缓存。

13 缺点:需要多个开发团队或开发者来跟进多个服务,因此你需要更多的人;需要一个共同的平台以防重复工作;对刚起步的小团队来说太多的间接支出。

  • PostgreSQL是一个出色数据库。它提供很棒的、很快的键值存储。
  • 电子邮件是一个很难的问题。很难正确被送达。开始是使用自行开发的邮件系统,但是今天可能会去选择一个电子邮件服务提供商。
  • 队列是救世主。组件之间传递任务时,把它放到一个队列。你会得到一个不错的小缓冲区。(Reddit使用RabbitMQ[17]作为消息队列。)
  • 混合HAProxy[18]Nginx[19]。一些流量被引导到它们中的一个。在尝试Niginx(遇到故障)后,负载均衡会选择HAProxy。它使用L7[20]做负载均衡。Nginx仍被用来完成SSL[21]请求和服务静态内容。

 

代码

  • 框架。最开始,使用了一个基于Python的架构(Django[23]太慢了)Pylons[22]。对Pylons进行定制以使上手变得容易,不过最终因为使用场景差异较大而放弃。对Pylon做了很大改动,结果最后使得它难以升级到新版本(现在修复了)。会将再次使用金字塔的(Pylons的新名字)。
  • 基于线程还是事件?基于线程可以提前以排列大小,但大小可能是错误的。基于事件可以处理更多连接。但是当你碰壁时就只能碰壁。你想花更多时间来规划你得线程池大小,还是就突然碰壁?
  • 开源很不错。Reddit建立在开源基础上。不用为软件付钱很不错,特别是在起步阶段。

 

数据

  • 数据是公司最重要的资产。Facebook,Google和Flickr[24]等公司都是建立在数据之上。
  • 数据重力。数据放在哪儿,应用就部署到哪儿。思路是应用随数据调整。数据创建了重力井,其他东西需要围绕它展开,因为数据是最难移动的。数据越多就越难移动。目前,从EC2导出数据的成本太大了。这就是为什么EC2允许你免费导入数据,当你导出时向你收费。他们希望你把你所有的数据放在云中。
  • 关系与非关系。Reddit里的大部分数据是以键值方式存储在Postgres。一切涉及金钱交易的数据都被保存在关系数据库,这样可以保障更好的事务性和更容易进行分析。
  • Postgres很稳定。它坚如磐石,他们从未有过自身问题。如果他们有问题,那也是使用上的问题,例如用Python编写的调用系统。因为,很难找到Postgres专家。
  • Postgres被选为键值存储,因为当时还木有Cassandra。另外,Postgres的速度非常快,而且现在原生地支持键值(KV)。
  • 分区。写入被分割的四个主数据库:链接,帐户,subreddits[25],评论,投票,以及杂项。

14 每个数据库都有主从设计。投票用数据库是一主一从。而注释用数据库是一主12从。

15 尽可能避免从主数据库读取,而是直接从从属数据库读取,保持主数据库只进行写操作。

16 客户端库将在从属数据库之间进行负载平衡,如果一个从属数据库处于忙状态,则尝试使用另外一个从数据库。

17 编写一个叫“thing”的数据库访问层。

18 这种方式支撑了很长时间,包括数据库切分、从数据库读取、跟踪从数据库的性能用于更好的负载均衡。

  • Cassandra

19 快速写入,快速反查,简单的增量可扩展性,无单点故障。

20 在Netflix数据被分布式部署在三个不同的区域。完整的数据副本同时存在三个区域中。即使一个区域丢失,依然可以正确运行。

21 将“投票”相关数据切换到Cassandra是reddit的一个巨大成功。Cassandra的布隆过滤器(Bloom Filters[26])使快速反查成为可能。它能很快识别哪个评论你没有投票,所以反查结果会很快返回。(更多关于这个话题

 

社交

  • 2008reddit是开源的

22 用户可以读取代码从而得知篡改投票是不存在的。

23 用户可以添加他们想要的功能,reddit会接受它。这个其实行不通,因为人们并不真的想写代码。

24 招聘。其他人知道这代码,所以更容易雇人。

  • 蠕虫事件。有人指出在页面中注入额外的JavaScript的方式可以制造蠕虫病毒。如何出现已无关紧要,但是蠕虫事件失控了。在一个创始人的婚礼当天,整个团队乘一架飞机从婚礼现场赶回。一个用户已经预先提交了一个可以组织蠕虫蔓延的补丁。代码开源使社区在危急时刻提供了很大帮助。

 

Reddit如何挣钱?

  • 侧栏广告,自助式广告,商品,reddit gold,市场。
  • 需要注意的是reddit是尚未盈利(链接)。这带来了一个问题,像reddit这样的网站,什么时候能在云端盈利?
  • 还要注意的是,reddit已不属于Condé Nast[27]了,所以它是独立的。(链接

 

错误

  • 没有考虑到迁移到EC2后增加的延迟。在数据中心,机器之间的响应是亚毫秒级的,一个页面的加载时间内可以进行1000次memcache访问。在EC2上并非如此。 Memcache访问时间增加了10倍,到毫秒级,使得之前的逻辑基本不可用。修复方法是在一个memcache请求内进行批量操作。
  • 只是承诺。亚马逊并不总兑现承诺和解决问题。所以设计的时候需要考虑绕过而不是解决。 (这里没有提到,也许EBS?)
  • 在生产中使用更稳定的产品。我们在Cassandra的开发阶段就开始使用它。现在真的很棒,但那时它是个问题专业户。
  • 本应该更早将负载转移到客户端。服务器做了很多的页面渲染,其中一些本可以交给客户端去做。 Facebook是这方面的大师。返回一个提前规划好的空间和很多的div,以及通过API调用来填充他们。这就是他们起初所希望的reddit。它本可以扩展得更好。它还有助于调试,因为很容易确定哪个API调用出了问题。
  • 不具备足够的监控,使用的监控系统并不能很好支持虚拟化。一开始用的是Ganglia[28],倒是有很好的图形界面,但很难使用,而且变化太快,特别是在一个实例会不断创建和消亡的场景下。
  • 数据没有过期时间。 你可以在reddit看到最初的那些评论被挖坟。他们已经开始着手做一些限制工作,你不能再给旧评论投票,或给旧帖添加评论。挖坟的问题会导致数据随着时间的推移不断增长,使得在数据库保存热点数据的难度越来越大。
  • 没有使用一致性哈希算法。当hash一个缓存时问题是,如果你需要添加更多的缓存,你会被卡住,因为所有的数据会命中一个hash或者许多你正在哈希的缓存。当增加缓存时你无法在此平衡。一致性哈希算法是解决这个问题的一个方法。迁移到Cassandra使这个问题被解决。

 

经验教训

  • 扩展的关键是现于用户发现瓶颈。
  • 使用代理是扩展的巨大福音。根据用户命中的URL进行路由。 Reddit有一个系统,监控每个URL抵达服务的时长(从请求发起到到达服务的时间,译者)。人们被放进不同的线路。慢流量去一个地方,快的去另一个。基于响应速度的流量分割是一个巨大的改进。
  • 自动化所有事情。像对待你的代码一样对待你的基础架构,你的生活会容易得多。一切都应该自动上线,自动配置。
  • 没有必要从一开始就建立一个可扩展的架构。一开始时你不知道什么会是你的功能集,所以你也不知道你有会有哪些扩展问题。随着你的网站增长,你可以了解到哪里将是扩展问题。
  • 刚起步时不要使用面向服务的架构。记住,当发展到中等规模时你可以去实现它;前期只会带来很多额外的开销。
  • 不要跟随潮流。有时候潮流是对的,例如node.js。
  • 给所有东西加个限制。给反复发生的事情设置一个上限,并根据需要提高或降低限制。如果超过限制,阻止用户以。这样可以保护正常服务。例如为subreddits上传文件标识。有用户指出他们可以上传很大的文件并损害系统。也不要接受巨大的文本。会有人指出如何给你发送一个5GB的文本。
  • 长远计划。在设计时总是假设将有一大堆事情需要你做。应用服务器,数据库,缓存。总是在开始时就假定你有一个以上的事情。这样,未来的横向扩展会更容易。
  • 用C重写Python函数。在reddit扩展中,为了获取速度,他们找出Python代码里重复次数最多的函数,并用C重写。比如过滤器,markdown渲染,memcache调用。Python的一个好处是可以很容易并高效地调用C。
  • 尽可能保持无结构模式。这样的话,可以很容易地增加新的功能。你所要做的就是添加新的属性,而无需改变数据表结构。
  • 数据过期。锁定旧帖和创建一个完整渲染的页面并缓存它。这个可以用来应对大规模旧数据冲击数据库的场景。同样的,不要允许在旧的评论上投票,或给旧帖添加评论。用户很少会关心这个。
  • 把SSD[4]看做是便宜的内存[5],而不是昂贵的硬盘。当我们为了数据库的性能将reddit从普通硬盘转移到SSD后,我们的服务器数量从12台降低到1台(这个很可能是个比例数据,译者),并且还有很大的富余。SSD虽然贵了四倍,但是你会得到16倍的性能提升,这么做是很值得的。
  • 每个工具都有不同的使用场景。Memcache不提供持久性保障,但是会非常快,所以投票数据存储在那里,以使渲染页面尽可能的快。Cassandra持久,快速,并能提供快速的反查询,因为其布隆过滤器,所以它适合提供memchche里投票数据副本的持久化。 Postgres是坚如磐石而且是关系型的,所以用作备份Cassandra投票(如果需要,Cassandra中的所有数据可以从Postgres恢复),也可以做批量处理,有时这需要关系的能力。
  • 将未登录用户当作二等公民。未登录用户之前曾占据约80%的流量,现在是接近50%。总是给未登录用户提供缓存内容,Akamai承载了大部分Reddit的流量,带来巨大的性能改进。附带的好处是如果reddit宕机,你不登录的话,你可能永远不会知道。
  • 把一切都放入一个队列。投票,评论,创建缩略图,预计算查询,邮件处理和更正。通过监控队列长度,你可以知道什么时候队列可能存在问题了。附带的好处是队列隐藏了用户的问题,因为诸如投票请求的事情都在排队,投票不做提交时用户并不会马上发现。
  • 把数据分散到多个可用区域进行保存。
  • 避免在单一实例上保存状态。
  • EBS磁盘频繁创建快照。
  • 不要在实例上保存密钥。亚马逊现提供了一个服务。
  • 基于安全分组分解功能
  • 提供API。程序员将会在你的平台上做东西。例如,reddit的iPhone应用程序,就是其他人用公开的API制作的。
  • 在自己的社区保持活跃。Reddit的用户喜欢reddit的管理员在自己网站上活跃,并与他们互动。
  • 让用户为你工作。有用户输入的网站,总是有作弊、垃圾邮件和欺诈这样一些问题。Reddit大部分管理的工作是由成千上万的志愿者来完成的,比如他们处理大多数的垃圾邮件问题。这种方式运转得非常好,是reddit的可以保持小团队的原因之一。
  • 给用户一点权利,看他们用它做什么,并好东西变成功能。例如,当添加了给subreddits增加CSS得能力时,他们看到人们在做什么,增加了许多通用的东西作为大家的功能。这也使得用户能在Reddit上做东西而兴奋,因为他们喜欢那种操控感。有很多其他的例子。
  • 倾听你的用户。用户会告诉你很多你不知道但是你可能想知道的东西。例如,reddit gold在社区里以一个笑话开始。后来他们把它做成了产品,用户也很喜欢。

 

 

译注:

1. Reddit是一家美国社交新闻网站Reddit.com。
2. RAMP是一个所有创业者在扩大经营规模前想要参加的讨论会。
3. Netflix是一家美国公司,提供互联网随选流媒体播放、在线出租业务。
4. SSD即Solid State Disk固态硬盘。
5. RAM即Random Access Memory随机访问存储器。
6. Akamai是一家美国内容分发网络(CDN)服务商。
7. Postgres即PostgreSQL, 是一个自由的对象-关系数据库服务器(数据库管理系统)。
8. EBS即exclusion basis system,动态密钥管理方法。
9. Y Combinator是一家以投资种子阶段初创公司为业务的创投公司。
10. Digg即“掘客”,或者“顶格”,美国公司,2012年被纽约科技开发公司Betaworks收购。
11. EC2即亚马逊弹性计算云(Elastic Compute Cloud),是一个让使用者可以租用云端电脑运行所需应用的系统。
12. S3即亚马逊简易存储服务(Simple Storage Service),由亚马逊网络服务系统提供的在线存储服务。
13. VPN即虚拟专用网络(Virtual Private Network),是在公用网络上建立专用网络的技术。
14. Memcache是一个高性能的分布式的内存对象缓存系统。
15. Cassandra是一套开源分布式NoSQL数据库系统。
16. REST即表征状态转移(Representational State Transfer)是Roy Fielding博士在2000年博士论文中提出来的一种软件架构风格。
17. RabbitMQ是流行的开源消息队列系统。
18. HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理。
19. Nginx即engine x,是一个高性能的 HTTP和反向代理服务器。
20. L7即Layer7,是网络层协议的脚本文件。
21. SSL即Secure Sockets Layer安全套接层,是为网络通信提供安全及数据完整性的一种安全协议。
22. Pylons是一个开放源代码的Web应用框架,使用python语言编写。
23. Django是一个开放源代码的Web应用框架,使用python语言编写。
24. Flickr是雅虎旗下图片分享网站。
25. Subreddit 是reddit上一个定制的子论坛。
26. Bloom Filter即布隆过滤器,是一个很长的二进制向量和一系列随机映射函数。
27. Condé Nast即康泰纳仕,是一个总部位于美国纽约市的国际期刊出版集团。
Ganglia是UC Berkeley发起的一个开源集群监视项目。

4 收藏 7 评论

关于作者:dryrun

(新浪微博:@dryrun)!dryrun140131) 个人主页 · 我的文章

相关文章

可能感兴趣的话题



直接登录
最新评论
  • 翻译的很多地方都不通顺,难道翻译后没自己读读吗?

    • 黄利民 站长 2013/09/10

      谢谢提醒和批评。
      已尽力校对完善了。这篇英文就是整理自杰里米·埃德伯格的演讲稿。演讲稿并不是完整连贯内容,所以翻译难度会比普通文章大。
      cc: @dryrun

  • 老码农 其实,我是一个作家 2013/09/10

    看了前面一小段,翻译的确有一些问题。译者对英文的理解基本上是到位的,问题主要出在中文表达上。严格准确地翻译是很重要的,但有时对于一些文化背景差异,需要用意译的方法稍微加以变通,这样才能让读者看明白。

    比如:“Jeremy uses a virtue and sin approach. Examples of the mistakes made in scaling reddit are shared and it turns out they did a lot of good stuff too.”

    这一段被翻译成了“杰里米使用一种美德和罪恶的方法,分享在扩展 Reddit 时的错误例子。事实证明,他们也做了很多好东西。”

    这样翻译感觉不太通顺。断句不正确,所以句子内部的逻辑就不一致了。另外“一种美德和罪恶的方法”这个说法也比较突兀。其实这段话的意思是说,Jeremy采用了宗教里对比罪恶和美德的方式(比如七宗罪和七个美德,是相互对立的关系)来列出他们在扩展Reddit时犯下的错误和获取的经验。可以翻译为:“Jeremy借用了(宗教里对比)罪恶和美德的方式(来总结经验教训)。他分享了在扩展Reddit过程中所犯错误的例子,也可以看到他们同样做了很多正确的事情。”

  • 这个网站与国内网民关系大吗?有没有类似的网站?

    • 黄余粮 站长 2013/09/12

      Reddit是一个面向全球的网站。它包括很多子版块,但没有地域之分,无国界。比如: programming板块,国内的程序员不也一样看?

      类似的网站?国内的吗?近在眼前啊,http://www.jobbole.com/news 就是参考Reddit做的。

跳到底部
返回顶部