add by zhj:html
对译文略有修改。原文发表时,Instagram还没被Facebook收购,读完只感受Instagram这三个后台工程师真牛逼。python
三我的就能够搞定1400万注册用户。不过,另外一方面,咱们也看到,这三我的其实使用的都是现成的技术,至少从文章中看不出他nginx
们有什么技术上的创新,固然就三我的搞创新也难了点,并且若是现有技术能基本上解决问题,对这样一个小团队而言,就不必git
本身开发新技术。最后,对他们愿意把方案分享出来表示很是感谢。github
该文章写的比较早了,因此有些技术已经进行了更新,好比到2013年时,Instagram已经再也不使用gearman,而改成Celery+Rabbitmq,参见redis
他们在PyCon 2013上的演讲PPT,messaging-at-scale-at-instagram。apache
译文:http://www.cnblogs.com/xiekeli/archive/2012/05/23/2514108.html缓存
当咱们与其余工程师偶遇和交流的时候,有一个问题常常被问及,“大家的技术架构(technology stack)是怎么样的”?咱们以为从较高的层次来描述Instagram的全部构成系统是一件有趣的事情;将来你能够期待更深刻的描述这些系统。这就是咱们的系统,仅仅1年时间,而且咱们活了下来,其中有一部分咱们一直在修改。一个小型团队的初创公司,能够在一年多一点时间发展到1400多万用户规模。 咱们选择一种技术的核心原则是:服务器
咱们将自顶向下进行介绍:
咱们在亚马逊的 EC2上跑Ubuntu Linux 11.04 (“Natty Narwhal”)。咱们发现以前的版本在EC2上高流量的时候都会出现各类不可预测的问题( freezing episodes),但11.04已经稳定了。咱们只有3名工程师,咱们的需求依然在不断的变化中,所以自托管主机不是咱们的选择,也许将来当用户量空前增加的时候,咱们会考虑。
每个对Instagram 服务器的访问都会经过负载均衡服务器;咱们使用2台nginx机 器作DNS轮询。这种方案的缺点是当其中一台退役时,须要花时间更新DNS。最近,咱们转而使用亚马逊的弹性负载均衡器,使用3个NGINX 实例能够实现调入调出(若是有哪一个NGINX健康检查失败,则自动剔除);咱们同时在 ELB 层停掉了 SSL , 以缓解nginx的 CPU 压力。咱们使用亚马逊的Route53做为DNS,他们最近在AWS控制台上为Route53增长了一个很好的GUI工具。
接下来是应用服务器用来处理咱们的请求。咱们在亚马逊的High-CPU Extra-Large机器上运行了Django ,随着使用量的增加,咱们已经在25台主机上跑Django实例了(幸运地,由于是无状态的,因此很是便于水平扩展)。咱们发现咱们的特定工做负载是属于CPU bound而不是memory bound,所以High-CPU Extra-Large类型的实例恰好提供了合适的比重(CPU和内存)。
咱们使用 http://gunicorn.org/ 做为咱们的WSGI服务器;咱们曾经使用mod_wsgi 和Apache,可是发现Gunicorn 更容易配置,且对CPU的要求更低。为了一次在多个实例上执行命令(像部署代码),咱们使用Fabric,Fabric最近增长了并行模式,所以部署只须要花费几秒钟。
咱们大部分数据(用户信息,照片的元数据、标签等)存储在PostgreSQL中;咱们 以前已经说了关于如何基于不一样的Postgres 实例进行切分的。咱们的主要分片集群包含12个Quadruple Extra-Large内存云主机(每一个都有副本,且主副在不一样区域);
咱们发现亚马逊的网络磁盘系统(EBS)每秒的寻道能力不够,所以,将咱们全部工做集放在内存中就变得尤其重要。为了得到合理的性能,建立了软 RAID 以提高 IO 能力,使用的 Mdadm 工具进行 RAID 管理;
顺便提一下,咱们发现vmtouch用来管理内存数据是个极好的工具,尤为是在故障转移时,从一台机器到另外一台机器,甚至没有活动的内存概要文件的状况。这里是脚本,用来解析运行于一台机器上的vmtouch 输出并打印出相应vmtouch命令,在另外一台机器上执行,用于匹配他当前的内存状态;
咱们全部的PostgreSQL实例都是运行于主-备模式,基于流复制,而且咱们使用EBS快照常常备份咱们的系统。为了保证咱们的快照的一致性(原始灵感来源于ec2-consistent-snapshot)咱们使用XFS做为咱们的文件系统,经过XFS,当进行快照时,咱们能够冻结&解冻RAID阵列。为了进行流复制,咱们最爱的工具是repmgr 。
对于从咱们的应用服务器链接到数据,咱们很早就使用了Pgbouncer作 链接池,此举对性能有巨大的影响。咱们发现Christophe Pettus的博客 有大量的关于Django、PostgreSQL 和Pgbouncer 秘诀的资源。
照片直接存储在Amazon S3,当前已经存储了几T的照片数据。咱们使用亚马逊的CloudFront 做为咱们的CDN,这加快了全世界用户的照片加载时间(像日本,咱们第二最受欢迎的国家)
咱们也普遍的使用了Redis ; 咱们的main feed、activity feed、sessions系统(这里是咱们的Django session backend),和其余 相关系统 都使用了Redis。 由于全部的Redis数据都须要放在内存中,所以咱们最后使用了几个Quadruple Extra-Large Memory云主机用于跑Redis。咱们的Redis也是运行于主-备模式,而且经 常将DB保存到磁盘,最后使用EBS快照备份这些数据(咱们发如今主机上进行导出太费劲了)。因为Redis 容许写入备份,使得在线故障转移很是方便,转移到一台新的Redis 机器,而不须要停机。
对于咱们的geo-search API,咱们一直使用PostgreSQL了不少个月,不事后来迁移到了Apache Solr.他有一套简单的JSON接口,这样咱们的应用程序相关的,只是另外一套API而已。
最后,和任何现代Web服务同样,咱们使用了Memcached 作缓存,而且当前已经使用了6个Memcached 实例,咱们使用pylibmc & libmemcached进行链接。亚马逊最近发布了一个弹性缓存服务,可是它并不比运行咱们本身的实例便宜,所以咱们尚未切换上去;
当一个用户决定分享一张Instagram 的照片到Twitter 或Facebook,或者是当咱们须要通知一个 实时订阅者有一张新的照片贴出,咱们将这个任务推到 Gearman, 一个任务队列系统。经过任务队列异步执行意味着媒体上传能够很快完成(即发一条instagram很快),而“重担”能够在后台运行。咱们大约有200个消费者(都用Python写的),它们消费队列中的任务。咱们的feed fan-out也使用了Gearman,这样posting就会响应新用户,由于他有不少followers。
对于消息推送,咱们找到的最划算的方案是https://github.com/samuraisam/pyapns,一个开源的Twisted 服务,已经为咱们处理了超过10亿条通知,而且绝对可靠。
对于100多个实例,监控变得很是重要。咱们使用Munin进行图形化度量,若是有什么超出了正常范围,那会提醒咱们。咱们基于 Python-Munin,也写了不少Munin 插件。用于图形化度量非系统级的东西(例如,每分钟的签入人数,每条照片发布数等)咱们使用Pingdom做为外部监控服务,PagerDuty 用于处理通知和事件。
对于Python错误报告,咱们使用Sentry,它是由Disqus的工程师们写的,是一个极好的开源的Django app。在任什么时候间,咱们能够实时的查看系统发生了什么错误。
若是你对咱们系统的这篇描述感兴趣,或者你正跃跃欲试的想告诉咱们关于系统你有什么不一样的看法,咱们都静候佳音。We’re looking for a DevOps person to join us and help us tame our EC2 instance herd.