十亿月PV网站秘诀:Reddit自失败中总结的25条经验

云计算
Jeremy现为Netflix可靠性架构师,更添为 Year One Labs的顾问;曾任Reddit首席架构师,兼技术、运营部门负责人,更早之前还效力于eBay及Sendmail。

Reddit前雇员Jeremy Edberg在RAMP会议上发表了主题为“Scaling Reddit from 1 Million to 1 Billion–Pitfalls and Lessons”的精彩演讲,分享了知名社交网站Reddit的打造经验。Jeremy现为Netflix可靠性架构师,更添为 Year One Labs的顾问;曾任Reddit首席架构师,兼技术、运营部门负责人,更早之前还效力于eBay及Sendmail。

近日HighScalanbility创始人Tod Hoff对该讲话进行了总结,并基于Netflix做了相应的对比,以下为译文:

首先,一些值得关注的观点:

1. 将SSD看做便宜的RAM,而不是磁盘。在Reddit磁盘都更换为SSD之后,服务器的数量从12台减少到了1台,并且有资源结余。SSD是比磁盘贵4倍,但是你得到了16倍以上的性能,值得投入。

2. 给用户动手空间,看看他们都在做什么,然后将好的东西加入到特性里面。Reddit从用户的身上学到了太多东西,网站的平稳运行有很大一部分归功于用户。通过用户你可以了解很多未知却非常有价值的东西,比如开始被比作社区笑话的Reddit Gold服务;当被Reddit做成产品后,深得用户欢心。

3. 开始时并不需要一个可扩展架构。未来的特性集肯定无法在开始被预测,所以有充足的时间去弄清扩展问题。随着网站的发展,系统将被更清晰的认知,扩展性问题也将迎刃而解。

4. 将未登录用户作2等公民对待。未登录用户远离缓存,让Akamai首当其冲,性能将得到大幅提升。

这样的点还有很多,下面就看一下Jeremy Edberg在不断失败中提取的宝贵经验:

统计

1. 流量每15个月翻一倍

 

 

2. 如上图所示,Reddit 8月的统计为:来自177个不同国家,67,328,706 UV及4,692,494,641PV。这个讲话结束在10亿PV这个点。

3. 28个员工

4. 每个员工大概负责2400万UV。

5. 上万个志愿版主

6. 在2012年,Reddit使用 240个服务器支撑每月20亿的PV及2TB的PostgreSQL数据。所有高流量数据都从EBS(Elastic Block Store)转移到Local Ephemeral Disk。

故事的起源

1. Reddit起源于2005年,开始的想法是订餐服务,并未获得Y Combinator的青睐。再次来到Y Combinator与Paul Graham详谈时,他们提出了建立整个互联网首页的创意。也就是现在的Reddit,当然那个时候他们还不了解Digg。

2. 网站开始托管在一个数据中心,然后逐渐过渡到EC2。

EC2在2006年首次被采用,主要使用S3存储和服务日志

2007年使用S3存储缩略图

2008年使用EC2做批处理,使用VPN与数据中心连接

2009年使用EC2服务整个网站。其花费整整1天的时间将所有数据迁移到EC2,Data Gravity一个很好的示例

EC2

1. EC2决策制定的积极因素

不想租更多的机柜及购买更多的服务器

数据中心规模扩展太快,并且无法在早期做增长预测

对一个4人团队来说,使用EC2更具成本效益,EC2比旧金山的数据中心便宜29%

2. EC2并非一直无往不利。你需要忍受更高的网络延时及吵闹的“邻居”,因此必须早做打算,好处是可以按需扩展。

3. EC2上资源限制记录

所有资源都存在单账户限制

Amazon有时候并未认识到一些来自他们的限制

追踪限制,并在需要之前克服

捕获异常,了解限制的临界点

架构

1. Reddit的架构非常简单的。用户连接到一个与应用程序层通信的web层,应用程序层则负责与memcache、Cassandra及PostgreSQL通信。PostgreSQL使用了主-从配置,一个批处理系统通过Cassandra及PostgreSQL实现。

2. 相比起来,Netflix使用了一个面向服务的架构,组件间通信通过REST API实现

优势:易于扩展,因为扩展往往只是针对某个服务进行;易于容量规划;更容易确定问题所在,因为他们都通过REST调用隔离;作用域变窄;更有效的本地缓存。

劣势:需要在不同服务上工作的多个开发团队或开发者,因此需要很多人力;需要防止工作重叠的通用平台;对小团队来说,初始的开销太大了。

3. PostreSQL是个非常好的数据库,具备完美及飞速的键值存储。

4. Email是个不小的挑战。投递正确性难以保障。开始时使用自己的邮箱服务器,现在已经转向电子邮件服务提供商。

5. 队列是“救世主”。在做组件间工作传递时,将其放入一个队列,将是一个非常不错的小缓冲区。(Reddit使用RabbitMQ支撑队列)

6. 混合使用Nginx和HAProxy。许多传输是相互的,为了负载均衡,在Nginx无法处理时果断转向HAProxy。它使用L7负载均衡,而Nginx仍然用来终止SSL及服务静态内容。

代码

1. 框架。开始时,使用的是Pylons(Django太慢了),一个基于Python的框架。确实易于起步,然而很快就被迫放弃,因为它们不符合你的用例。Pylon被做了太多的修改以至于无法更新到下一个版本,这个问题现在已经被修复了,所以还会再次使用Pyramid(pylon的新名字)。

2. 基于事件还是线程?基于线程更好做容量规划,但是线程池的容量需要投入很多的精力。基于事件,可以获得更多的连接,但是你必须花时间去做好棘手问题凸现的准备。

3. 开源是极好的。Reddit基于开源打造,付费软件并不一定是个很好的决策,特别在起步阶段。

数据

1. 数据是最宝贵的财产。类似Facebook、Google及Flicr都是建立在数据之上。

2. 以数据为中心。围绕数据建立应用程序,也就是应用程序需要绕数据运作。数据建立了一个重力井,所有的一切都需要向它靠拢,因为数据是最难移动的。数据集越大,迁移就越困难。如果将现在的Reddit搬离EC2,将造成非常大的开销,这也是为什么EC2在数据传入时是免费的,读出时却是收费的,因为他们企图将你所有数据都带入云中。

3. 关系型数据库和非关系型数据库。大部分Reddit数据都是键值型的,储存于PostgreSQL。基于事务的需求及易于分析,所有涉及金钱的处理都使用了关系型数据库。

4. 铁打的PostgreSQL。PostgreSQL非常可靠,使用至今未发现其自身问题。如果真的出问题了,肯定由其它事件引起,比如使用Python编写的备份系统。之所以PostgreSQL的使用场景多于Cassandra,因为Cassandra出现的比较晚。再加上PostgreSQL确实非常的快,并且原生支持KV。

5. 分片。写操作被分布到4个主数据库: 链接、 账户、subreddit、评论、投票及杂项。

每个都有从节点。投票使用了1主+1从模式,而评论则是1主+12从

尽可能的避免从主数据库中读取,直接在从节点上读取,从而让主节点专注于写操作

客户端库将负责从节点的负载平衡,在某个从节点繁忙时会自动选取另一个

编写了数据库访问层“thing”

这个组合使用了很长一段时间:结合分片数据库、从读并且监视从读性能以更好的均衡负载

7. Cassandra

写入速度快,否定查询速度快,易扩展,没有单点故障

在Netflix每个数据都会被分配到3台主机上,如果1台主机故障,余下的可以继续运行。

将投票数据迁移至Cassandra让Reddit获益不浅:Cassandra布隆过滤器提供了非常快的否定查询,对于评论来说,可以非常快的查询出没投票的评论,这样反的答案将非常快的出现。( 更多细节)

社交

1. 2008年的Reddit是开源的

用户可以查看源代码,然后确定没有投票干预成分存在

用户可以添加自己一直想要的特性,Reddit就会支持它,当然这对不想写代码的人毫无作用

招聘。因为代码为许多人知晓,所以就更容易招聘了解代码的人,这个理论通常被用于创意推销

2. 蠕虫事件。有人发现了如何通过给页面注入javascript来编写蠕虫,虽然无意传播但是已经泄露。而那天,刚好是Reddit一个创始人的大婚之日,整个团队都在一架飞机上往回赶。然而不想一个用户已经设计好了阻止蠕虫传播的补丁,并将之开源,在最危急的时候帮助到了社区。

Reddit如何赚钱

1. Sidebox广告、自助式广告、商品、Reddit Gold 服务、市场。

2. 需要注意的是 Reddit尚未盈利,它同样带给我们一个问题——像Reddit这样的网站是否可以通过云来盈利?

3. 同样需要注意的是Reddit已不再属于Condé Nast,也就是它独立了。

曾犯过的错误

1. 未考虑迁移到EC2的延时。数据中心机器间访问延时是亚毫秒级,所以针对一个页面负载访问1000次memcache也是可行的。然而在EC2中就不行了,memcache访问时间延长10倍至毫秒级,这就让老方法并不适用。应对方法是对memcache进行批量访问,这样一个请求将返回大量的结果。

2. 未履行的承诺。Amazon不总是遵循承诺,并一遵循承诺为目标。要学会与故障周旋,而不是去修复。

3. 不要怕使用新产品。Cassandra采用时,还处开发阶段,虽现在发展不错,但仍不乏问题。

4. 在发往客户端前,是否需要尽可能的简化工作。在推送到客户端之前,服务器做了很多的页面渲染。Facebook在这方面的经验非常丰富,你得到一个拥有许多div及API(用于填充div)的矩形,这也是Reddit想尽快实现的地方。这样会让应用有更好的扩展性,同样帮助到了调试,因为很容易确定是哪个API产生了问题。

5. 没有足够的监视,使用的唯一监视系统并不适合虚拟化场景。开始时使用的是Ganglia,它提供了非常不错的图形,但是难以使用并且变化的非常快,特别是在实例变化不断的虚拟化环境中。

6. 没有给数据设置生命周期。在Reddit ,评论并没有一个到期时间。他们已经着手限制老评论的投票,以及旧主题评论。这就导致了数据的一直增长,直到数据库难以支撑热数据的存储。

7. 没有使用一致性哈希。当给缓存哈希时,问题就卡在想为缓存增加容量的情景——因为所有数据都在一个缓存上,或者你需要哈希太多缓存。在缓存增加后,无法再平衡。一致性哈希就是问题的解决方法之一,他们通过迁移到Cassandra解决了这个问题。

经验教训

1. 扩展的关键就在于先用户发现瓶颈所在

2. 使用proxy非常有益于扩展。用户可以通过URL被路由,Reddit拥有一个可以监视每个发送给服务的URL长度。给流量的速度分级,基于响应速度的平均值去拆分流量是个巨大的提升。

3. 自动化一切。如果可以像对待代码一样去对待基础设施,那么工作将非常轻松,所有基础设施最好能自动打开和关闭,并且自动配置。

4. 开始时并不需要建立一个可扩展架构。因为在初期你根本不知道最终的特性集,所以你有很多的时间来解决扩展问题。随着网站的增长,你将清晰的发现问题所在。

5. 在开始时并不需要使用一个面向服务的架构。将它做为目标,在网站发展到中等规模时可以去实现,否则只会带来更多的开销。

6. 不必刻意追逐潮流,但是偶尔试下也不错,比如node.js。

7. 限制一切。时常发生的事情需要加上限制,并根据需求抬高或者放低。如果超出限制,需阻止用户已保证服务的正常运作。

8. 长远的计划。设计时总是假设当下做的事情以后会有更多,应用程序服务器、数据库、缓存。开始时就假设不会只有1个,那么以后的横向扩展会容易很多。

9. 将Python使用C来重新编码。随着Reddit不停扩展以追求更快的速度,他们使用C来重新编码了经常用到的功能(之前用的是Python),特别是过滤器、Markdown渲染以及memcache调用。这时Python作为胶水语言的好处就出来了,调用C时非常简单且效率。

10. 尽量保持无结构化模式,这将让服务很容易添加特性——在不更改表格的情况下就可以增加属性。

11. 数据的生命周期。对旧主题进行锁定,然后建立一个完整的呈现页面并缓存,这样就可以保证数据库不会被旧数据淹没。同时,停止旧评论的投票及旧主题的评论,用户一般很少发现。

12. 将SSD看做便宜的RAM,而不是磁盘。当Reddit将磁盘都换成SSD后,服务器数量从12台减少到了1台,并且还有资源结余。SSD是比磁盘贵4倍,但是得到的却是16倍性能,值得投入。在Netflix与Reddit,一些最大的Cassandra都使用上了SSD,各方面得到了很大的提升。

13. 每个工具都有特定的用例。Memcache无法持久化,但是却非常快,所以投票数据就存储在那里以保证页面的飞速渲染。Cassandra可以持久化并且很快,同时布隆过滤器还提供了快速的反查询,所以当数据不在缓存中时用它来储存投票的副本非常合适。PostgreSQL是可靠的关系型数据库,所以用它来作为Cassandra的备份储存投票数据,以及用作需要相关性的批处理操作。

14. 将未登录用户视为2等公民。开始时这些用户占了网络流量的80%,至今仍有50%之巨。让未注册用户远离缓存,Akamai首当其冲,性能将得到大幅提升。附带的好处是,如果Reddit宕机了,未登录用户甚至毫无所知。

15. 将一切都放到队列中。投票、评论、缩略图创建、预计算查询、垃圾邮件处理及修正,队列可以让你在监视长度时发现问题所在。附加好处是,队列可以让问题对用户透明;比如队列中的投票请求,如果没有立即生效的话不会有任何人注意到。

16. 将数据保存在多个可用区域

17. 避免将网站放到一个单实例上

18. 频繁的抓取EBS磁盘快照

19. 不要在实例上保存秘钥

20. 通过Security Group划分功能

21. 提供一个API。程序员将在你的平台上开发,比如Reddit的iPhone应用就是用户通过API建立的。

22. 在社区中保持一定的活跃度。Reddit管理员经常在论坛现身并参与互动,这点深受其用户的喜爱。

23. 让用户为你做事。人气网站总是不乏欺诈、垃圾邮件等问题,而在Reddit这项工作由上万个志愿者完成,他们仔细的处理了大多数的垃圾邮件问题。这个工作模式顺利的难以置信,同时这也是Reddit的团队可以维持很小的原因。

24. 给用户动手空间,看看他们都在做什么,然后将好的东西加入到特性里面。比如赋予用户给subreddit添加CSS的能力,选择好的功能,并为每个用户都添加。这同样让用户乐于在Reddit上做些东西,让他们满足于这种控制感。

25. 听用户的话,用户将告诉你许多想知道但还不知道的事情。比如,在社区中Reddit Gold服务以笑话的形式开始,但是做成产品后却深受用户喜欢。

责任编辑:王程程 来源: Highscalability
相关推荐

2013-09-25 10:54:03

2014-12-15 14:39:00

Java

2010-05-05 11:40:30

Oracle数据库

2013-04-22 10:07:13

架构设计Pinterest架构

2013-07-11 14:41:16

编程经验

2021-05-27 08:32:27

DevOps开发工具

2017-01-10 19:06:39

Android日常开发技术经验

2011-06-30 15:53:05

SEO外链

2016-12-30 08:46:32

2017-11-09 17:35:21

数据库OracleSQL优化

2011-01-12 17:27:53

2018-07-09 10:55:14

视频系统经验

2016-03-14 11:05:58

数据挖掘数据挖掘模型数据处理

2017-11-17 08:00:03

软件开发程序员前辈经验

2017-03-09 15:05:49

Linux

2010-11-30 11:35:31

2013-05-29 10:33:16

2015-05-20 12:58:43

程序员经验教训

2020-02-10 09:23:09

LinuxReddit命令

2020-06-22 18:54:39

消息队列幂等性
点赞
收藏

51CTO技术栈公众号