Instagram的技术探索(转)
add by zhj: 略有修改
原文:http://www.cnblogs.com/xiekeli/archive/2012/05/28/2520770.html
前一篇翻译了Instagram blog上的一篇文章《What Powers Instagram: Hundreds of Instances, Dozens of Technologies》,让我们对Instagram 的大致技术路线有了一个大体的了解。我觉得Instagram 的工程师能够在Instagram blog上将自己使用的技术和工具进行分享,真是难能可贵。同时,在网上看到了一份Mike Krieger在“AirBnB Tech Talk 2012”上演讲的PPT,见"Instagram创始人:Instagram是如何扩展的.pdf",感觉受益匪浅,有必要整理学习。
- 相关统计
用户规模:30+ million users in less than 2 years(不到2年时间,3000多万用户,注:在他们发布android版本后的10天已经突破4000万了)
在发布android版本的12个小时里,他们就新增了100万用户
- 创建初期
两个联合创始人没有任何后端的实战经验(这也太…)
:)就是这两小子
注:
Mike Kriegerr:之前是一个颇为低调的工程师和用户体验设计师,他在一家名叫Meebo的创业公司工作了1年半。analytics & python @ meebo(在Meebo做分析,使用python );
Kevin Systrom: 毕业后在Google的收购部门工作了一年,今年28岁,随后去到了一家从事旅行业务的创业公司Nextstop,没有计算机学位,没有接受过正式培训, 但他下班后坚持自学编程,在这家创业公司被Facebook以人才收购的方式收购后,Systrom又去早期的Twitter实习了一段时间。
最初存储采用CouchDB(Apache CouchDB 是一个面向文档的数据库管理系统)
最初只有一台服务器(在洛杉矶),比一台比MacBook Pro强不到哪里去。
上线第一天有25000注册用户。
上线初期的问题(总是些微不足道的问题):
1、favicon.ico :因为忘记favicon.ico图标文件,在Django上引起大量404错误;
2、
ulimit -n,设置Linux内核可以同时打开的文件描述符的最大值,例如size为4092。3、
memcached -t 4,设置用于处理请求的线程数.4、prefork/postfork 线程的预加载还是后加载问题,类似于线程池吧?
- 技术迁徙
let’s move to EC2,系统扩展就像对100码速度行驶的汽车更换所有部件;
![]()
![]()
- Instagram 的哲学
保持简单
为了最小的运营负担而优化程序
利用一切能用到的工具
- 一、数据库扩展
早期使用django ORM+postgresql,因为PostGIS,选择了postgresql。(PostGIS在对象关系型数据库PostgreSQL上增加了存储管理空间数据的能力,相当于Oracle的spatial部分)并且数据库部署在独立服务器上。
因为EC2机器的最大内存为68G,随着照片存储量的增加,进行垂直分区(vertical partitioning);
使用django db routers,做垂直分区变得很容易;如下:照片则映射到photodb
def db_for_read(self, model):
if app_label == 'photos':
return 'photodb'
当照片存储量大于60G的时候,采用水平分区(也就是所谓的“分片”sharding)
sharding带来的问题:
1、数据的检索,hard to know what your primary access patterns will be w/out any usage in most cases, user ID
2、当有分片变得太大的时候怎么办?
基于范围的分片策略(就像MongoDB那样)
![]()
![]()
3、性能有下降趋势,尤其在EC2上,原因:disk IO,解决方法:预先切分(pre-split),即预先切分上千个逻辑切片,将它们映射到较少的物理分区节点中去。
关于相关内容,更详细的可以参看这里;
- 二、选择合适工具
进行缓存/反规范化数据设计
用户上传图片时:
1、用户上传带有标题信息和地理位置信息(可选)的照片;
2、同步写到这个用户对应的数据库(分片)中;
3、进行队列化处理
a、如果带有地理位置信息,通过异步的POST请求,将这个图片的信息送到Solr(Instagram 用于geo-search API的全文检索服务器)。
b、跟随者的信息分发(follower delivery),即告诉我的follower ,我发布了新的照片。如何来实现的呢?每个用户都有一个follower 列表,新照片上传时会把照片ID发送给列表中的每一个用户,用Redis 来处理这一业务简直太棒了,快速插入,快速子集化(rapid subsets,什么意思?是指获取部分数据吗)
c、when time to render a feed,we take small # of IDs, go look up info in memcached(当需要生成feed的时候,我们通过ID+#的格式,直接在memcached中查找信息)
Redis适合什么样的场景:
1、数据结构相对有限;
2、对频繁GET的地方,对复杂对象进行缓存;
不要将自己绑定在非得以内存数据库为主要存储策略的方案上(don’t tie yourself to a solution where your in-memory DB is your main data store
关于Follow图谱
第一版:简单的数据库表格(source id, target id, status)
需要来回答如下查询:我关注谁?谁关注我?我是否关注某人?某人是否关注我?当数据库的压力变大时,instagram开始在Redis中并发存储关注图谱,但这也带来了内容一致性(consistency)的问题。
不一致性一度带来缓存失效问题。
PostGIS结合轻量的memcached缓存,可以支撑上万的请求量。
需要注意点:
1、核心数据存储部分有一个万能的组件支撑,就像:Redis;
2、千万不要试想用两种工具去做同一个工作;
- 三、保持敏捷
2010年: 2位工程师
2011年: 3 位工程师
2012年: 5 位工程师
制胜法宝:
1、广泛的单元测试和功能测试
2、坚持DRY(Don’t Repeat Yourself)原则
3、使用通知/信号机制实现解耦
4、我们大部分工作使用Python来完成,只有逼不得已的时候,才会用C
5、频繁的代码复查,尽量保持“智慧共享”。(frequent code reviews, pull requests to keep things in the ‘shared brain’)
6、广泛的系统监控
- 四、往android平台扩展
12小时增加100万新用户
伟大的工具可以使读取更具扩展性,例如:redis: slaveof <host> <port>(SLAVEOF 命令用于在 Redis 运行时动态地修改复制(replication)功能的行为)
更短的迭代周期
不要重复发明轮子,例如想开发一个系统监控的守护进程,完全没有必要,HAProxy完全能胜任这一工作。
周围要有强大的技术顾问;
技术团队保持开放的氛围;
give back; e.g. node2dm(我理解的意思是:回报开源世界,例如:node2dm,一个出自instagram的node.js服务器,用来向安卓C2DM服务提交推送请求)
关注优化,如何是我们的系统速度快上一倍?
staying nimble = remind yourself of what’s important(保持敏捷 = 时刻提醒自己,什么才是你最重要的)
前所未有的时代,两个后端工程师能够支撑3000万用户规模的系统,关键字是: simplicity(简单)
cleanest solution with the fewest moving parts as possible(使用最少部件,最干净的解决方案)
don’t over-optimize or expect to know ahead of time how site will scale(不要过度的优化,除非你提前知道自己的系统将如何扩展)
don’t think “someone else will join & take care of this”
因为这个PPT本身也传承了instagram的simplicity哲学,因此很多信息只能靠猜,同时因为自己对相关技术认识还比较欠缺,无法很好的将其中的内容贯穿起来,整个内容翻译下来有点支离破碎的感觉,欢迎高手拍砖指正。
Instagram的技术探索(转)的更多相关文章
- Instagram的技术探索2(转)
原文:http://www.cnblogs.com/xiekeli/archive/2012/05/28/2520770.html 前一篇翻译了Instagram blog上的一篇文章<What ...
- Instagram的技术架构
http://blogread.cn/it/article/5497 Instagram 被 Facebook 以10亿美金收购.团队规模:13 人.而在被Facebook收购前的一个月,整个团队才7 ...
- webp技术探索
不管是 PC 还是移动端,图片一直是流量大头,以苹果公司 Retina 产品为代表的高 PPI 屏对图片的质量提出了更高的要求,如何保证在图片的精细度不降低的前提下缩小图片体积,成为了一个有价值且值得 ...
- Spring Security框架中踢人下线技术探索
1.背景 在某次项目的开发中,使用到了Spring Security权限框架进行后端权限开发的权限校验,底层集成Spring Session组件,非常方便的集成Redis进行分布式Session的会话 ...
- Quora的技术探索(转)
原文:http://www.cnblogs.com/xiekeli/archive/2012/04/27/2473808.html 关于问答类的应用,最早接触的是stackoverflow和知乎 ,而 ...
- 搜索广告与广告网络Demand技术-探索与利用
探索与利用(Explore and exploit) 点击率预测中还有一个重要的问题,就是探索与利用,它在工程中解决的并不好,我这章把现在论文中的常见的几种方法介绍一下.探索与利用它是所有互联网应用都 ...
- Quora的技术探索
关于问答类的应用,最早接触的是stackoverflow和知乎 ,而Quora作为知乎的原型,因为其创始人来自FaceBook而吸引了我.事实上关于Quora的技术分析,冯大辉和陈皓都已经有所详细的阐 ...
- [转发]Android视频技术探索之旅:美团外卖商家端的实践
美团技术团队 2019-09-12 20:02:11 背景 2013年美团外卖成立,至今一直迅猛发展.随着外卖业务量级与日俱增,单一的文字和图片已无法满足商家的需求,商家迫切需要更丰富的商品描述手段吸 ...
- Acoustic Echo Cancellation (AEC) 回音消除技术探索
回声产生的原因: 本地产生的音频信息通过网络传输到远端, 远端音频信号通过反射再由远端麦克采集到远端系统,再通过IP网络传输本地,本地播放后,在由本地麦克采集到,这就构成了类似闭环正反 ...
随机推荐
- 【Java面试题】16 静态代码块,main方法,构造代码块,构造方法
public class HelloB extends HelloA{ public HelloB() { System.out.println("HelloB"); } { Sy ...
- (转)JavaScript内存模型
JavaScript对象内存模型 转自:http://blog.csdn.net/u010425776/article/details/53617292 推荐-JavaScript作用域链内存模型: ...
- 教您如何在Word的mathtype加载项中修改章节号
在MathType数学公式编辑器中,公式编号共有五部分内容:分别是章编号(Chapter Number).节编号(Section Number).公式编号(Equation Number).括号(En ...
- 怎么解决MathType希腊字母无法显示的问题
MathType是一种常见的数学公式编辑软件,有些用户在编辑论文公式的时候发现,一些希腊字母在公式编辑器中无法打出来,上面显示一个“叉”号,面对这种MathType希腊字母无法显示的问题该如何解决呢? ...
- Asp.net 程序优化js,css合并与压缩
访问时将js和css压缩并且缓存在客户端,采用的是Yahoo.Yui.Compressor组件还完成的,从这里可下载 创建一个IHttpHandler来处理文件 ) }; ) ...
- Java 9的日期时间格式化趋近Unicode区域设置标准
1.JDK-8148947,DataTimeFormatter的模式字母“g”:正如在LDML中定义的,字母“g”指代一个“简化儒略日期”,简化儒略日期与正常儒略日期的差别在于:(1)简化儒略 ...
- 下载mysql server安装包的时候,不登录oracle账号,实现下载
需求描述: 之前下载mysql安装包的时候,都是使用oracle账号进行登录下载,最近看到可以不登录账号 就实现下载的方法,在此记录下. 操作过程: 1.选择mysql linux服务器上的安装包,点 ...
- WPF 跟踪命令和撤销命令(复原)
WPF 命令模型缺少一个特性是复原命令.尽管提供了一个 ApplicationCommands.Undo 命令,但是该命令通常被用于编辑控件(如 TextBox 控件),以维护它们自己的 Undo 历 ...
- BaiduMap 鼠标绘制矩形选框四个顶角坐标的获取
雪影工作室版权全部.转载请注明[http://blog.csdn.net/lina791211] 1.博文产生原因 在使用百度Map开放API进行开发的时候,遇到了一个需求,非常easy的一个需求. ...
- 异常处理----使用 try…catch…finally 处理异常
使用 try…catch…finally 处理异常 异常处理是通过try-catch-finally语句实现的. try { ...... //可能产生异常的代码 } catch( Exception ...


