应该用bind+function bind取代虚函数吗

c++11 使用c++11改进我们的程序系列 - 随笔分类 - qicosmos(江南) - 博客园
随笔 - 93, 文章 - 0, 评论 - 476, 引用 - 0
随笔分类 - c++11 使用c++11改进我们的程序系列
使用c++11改进我们的程序系列
摘要: 引子 最近准备重构一下我的kapok库,让meta函数可以返回元素为kv的tuple,例如: 类似这个META的实现我在msgpack的库里看到了,在这里: msgpack中仅仅是宏元的代码就数百行了,看起来非常复杂,msgpack之所以用这么复杂的方式去实现恐怕是为了支持c++98/03标准。本来
摘要: 实现动机 工厂方法是最简单地创建派生类对象的方法,也是很常用的,工厂方法内部使用switch-case根据不同的key去创建不同的派生类对象,下面是一个伪代码。Message* create(int type){ switch (type) { case MSG_PGSTATS:...
摘要: 检查类里是否存在某种类型的几种方法,以检查xxx类型为例:方法1:templateclass has_member_type_Type{ struct big { char a[2]; }; template static big probe(typename C::xxx*); //...
摘要: AOP介绍 AOP(Aspect-Oriented Programming,面向方面编程),可以解决面向对象编程中的一些问题,是OOP的一种有益补充。面向对象编程中的继承是一种从上而下的关系,不适合定义从左到右的横向关系,如果继承体系中的很多无关联的对象都有一些公共行为,这些公共行为可能分散在不同...
摘要: 1.概述 关于C++11模板元的基本用法和常用技巧,我在程序员2015年2月B《C++11模版元编程》一文(后称前文)中已经做了详细地介绍,那么C++11模版元编程用来解决什么实际问题呢,在实际工程中又该如何应用呢?本文将侧重介绍C++11模板的一些具体应用,向读者展示模版元编程的具体应用。 我...
摘要: boost中有一个lexical_cast可以用统一的方式来做基本类型之间的转换,比如字符串到数字,数字到字符串,bool和字符串及数字之间的相互转换。boost::lexical_cast的用法比较简单:#include #include #include #define ERROR_LEX...
摘要: 用bind+function取代虚函数在好几年前就有人提出了,曾引起广泛的讨论,有支持的有反对的,可能赞成的人占大多数。这个话题挺有趣,本来是作为技术沙龙的开放性话题来讨论的,由于时间关系并没有讨论。今天就来具体探讨一下这个问题,我将做两个实验来验证一下这两种做法,具体是实现两个模式:策略模式和责任...
摘要: KapokFAQ1.Kapok的特点简单,易用,header-only,只需要引用Kapok.hpp即可;高效,初步测试性和messagepack相当。它是纯c++11实现,因此需要支持C++11的编译器。2.主要功能对对象进行自动化的序列化和反序列化,用起来非常简单,先来看个序列化/反序列化一个t...
摘要: 1.概述 模版元编程(template metaprogram)是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序。模版元编程完全不同于普通的运行期程序,它很独特,因为模版元程序的执行完全是在编译期,并且模版元程序操纵的数据不能是运行时变量,只能是编译期常量,不可修改,另外它
摘要: 1概述&!--?xml:namespace prefix = &o& ns = &urn:schemas-microsoft-com:office:office& /--& C++11的新特性--可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高
摘要: 从4行代码看右值引用 概述 右值引用的概念有些读者可能会感到陌生,其实他和C++98/03中的左值引用有些类似,例如,c++98/03中的左值引用是这样的: int i = 0; int& j = 这里的int&是对左值进行绑定(但是int&却不能绑定右值),相应的,对右值进行绑定的引用就是右
摘要: c++11新增加了一些便利的算法,这些新增的算法使我们的代码写起来更简洁方便,这里仅仅列举一些常用的新增算法,算是做个总结,更多的新增算法读者可以参考/w/cpp/algorithm。 算法库新增了三个用于判断的算法all_of、any_of...
摘要: c#中格式化字符串很简单,比如我们可以这样格式化一个字符串:string str = string.format(&test {0}, {1}, {2}, {1}, {0} sample&, 1, 2.3, &ok&);Console.WriteLine(str);将输出:test 1, 2.3, ...
摘要: 引子 前些时候,我在群里出了一道题目:将变参的类型连接在一起作为字符串并返回出来,要求只用函数实现,不能借助于结构体实现。用结构体来实现比较简单:template struct Ctemplatestruct Connect{ static string GetName() ...
摘要: 对象池对于创建开销比较大的对象来说很有意义,为了避免重复创建开销比较大的对象,我们可以通过对象池来优化。对象池的思路比较简单,事先创建好一批对象,放到一个集合中,以后每当程序需要新的对象时候,都从对象池里获取,每当程序用完该对象后,都把该对象归还给对象池。这样会避免重复的对象创建,提高程序性能。...
摘要: c++11提供了日期时间相关的库chrono,通过chrono相关的库我们可以很方便的处理日期和时间。c++11还提供了字符串的宽窄转换功能,也提供了字符串和数字的相互转换的库。有了这些库提供的便利的工具类,我们能方便的处理日期和时间相关的转换和格式输出。chrono chrono库主要包含了...
摘要: 结构体自动化转换为char数组这个需求,来自于一个最近开发的一个项目,在项目开发过程中遇到一个小问题,需要将各种结构体拷贝到char数组中,这对于一个简单的结构体来说是很简单的事情,比如下面这个只有整形字段的结构体:struct A{};char buf[100];A a = {1,2};memcpy(buf, &a, sizeof(A)); 一句memcpy就能将结构体a拷贝到char数组中去了,直接通过memcpy拷贝结构体只对于内存连续的结构体有效。如果结构体内存不连续,结构体中含有double、string、指针甚至嵌套结构体时,直接拷贝是...
摘要: c++14中将包含一个std::optional类,它的功能和用法和boost的optional类似。optional内部存储空间可能存储了T类型的值也可能没有存储T类型的值,只有当optional被T初始化之后,这个optional才是有效的,否则是无效的,它实现了未初始化的概念。optional的应用场景函数返回无效对象 有时根据某个条件去查找对象时,如果查找不到对象时就会返回一个无效值,这不表明函数执行失败,而是表明函数正确执行了,但是结果却不是有用的值,这时就可以返回一个未初始化的optional对象出去,在外面判断这个optional对象是否有效对象是否被初始化,如果没有被初始...
摘要: python中的range函数表示一个连续的有序序列,range使用起来很方便,因为在定义时就隐含了初始化过程,因为只需要给begin()和end()或者仅仅一个end(),就能表示一个连续的序列。还可以指定序列产生的步长,如range(0,10,8)产生的序列为[0, 8], 默认的步长为1,...
摘要: TaskCpp简介 TaskCpp是c++11开发的一个跨平台的并行task库,它的设计思路来源于微软的并行计算库ppl和intel的并行计算库tbb,关于ppl和tbb我在前面有介绍。既然已经有了这两个大公司开发的并行计算库,我为什么还要开发自己的并行计算库。有两个原因:ppl只能在window...
摘要: c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的:void f(int n);std::thread t(f, n + 1);t.join(); 但是线程毕竟是属于比较低层次的东西,有时候使用有些不便,比如我希望获取线程函数的返回结果的时候,我就不能直接通过thread.join()得到结果,这时就必须定义一个变量,在线程函数中去给这个变量赋值,然后join,最后得到结果,这个过程是比较繁琐的。c++11还提供了异步接口std::async,通过这个异步接口可以很方便的获取线程函数的执行结果。std::async会自动创建一个线程去调用线程函数,它返回一个st...
摘要: 关于链式调用,比较典型的例子是c#中的linq,不过c#中的linq还只是一些特定函数的链式调用。c++中的链式调用更少见因为实现起来比较复杂。c++11支持了lamda和function,在一些延迟计算的场景下,这个链式调用的需求更强烈了。链式调用要实现的目是,将多个函数按照前一个的输出作为下一个输入串起来,然后再推迟到某个时刻计算。c++中,目前看到PPL中有这样的用法。PPL中链式调用的例子:int wmain(){ auto t = create_task([]() -& int { return 0; }); // Create a lam...
摘要: 在上一篇博文中提到asio的异步发送稍微复杂一点,有必要单独拿出来说说。asio异步发送复杂的地方在于: 不能连续调用异步发送接口async_write,因为async_write内部是不断调用async_write_some,直到所有的数据发送完成为止。由于async_write调用之后就直接返回了,如果第一次调用async_write发送一个较大的包时,马上又再调用async_write发送一个很小的包时,有可能这时第一次的async_write还在循环调用async_write_some发送,而第二次的async_write要发送的数据很小,一下子就发出去了,这使得第一次发送的数据和..
摘要: 在.net 4.0中增加一个延迟加载类Lazy,它的作用是实现按需延迟加载,也许很多人用过。一个典型的应用场景是这样的:当初始化某个对象时,该对象引用了一个大对象,需要创建,这个对象的创建时需要较长的时间,同时也需要在托管堆上分配较多的空间,这样可能会在初始化时变得很慢,尤其是UI应用时,会导致用户体验很差。其实狠多时候并不需要马上就获取大数据,只是在需要时获取,这种场景就很适合延迟加载了。先看看c#中Lazy如何使用的吧:class LargeObject{ public int InitializedBy { get { return initBy; } } int ini...
摘要: 模式虽然精妙,却难完美,比如观察者模式中观察者生命周期的问题;比如访问者模式中循环依赖的问题等等;其它很多模式也存在这样那样的一些不足之处,如使用场景受限、实现复杂、不够简洁、不够通用等。但我觉得不足之处大都是可以采取一些手法去弥补去改进的,比如用c++11的新特性来改进。因此,便有了c++11...
摘要: 本次要讲的是右值引用相关的几个函数:std::move, std::forward和成员的emplace_back,通过这些函数我们可以避免不必要的拷贝,提高程序性能。move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。如图所示是深拷贝和move的区别。 这种移动语义是很有用的,比如我们一个对象中有一些指针资源或者动态数组,在对象的赋值或者拷贝时就不需要拷贝这些资源了。在c++11之前我们的拷贝构造函数和赋值函数可能要这样定义:假设一个A对象内部有一个资源m_A& A::operator=(const A& rhs){//
摘要: 本次主要讲c++11中的右值引用,后面还会讲到右值引用如何结合std::move优化我们的程序。c++11增加了一个新的类型,称作右值引用(R-value reference),标记为T &&,说到右值引用类型之前先要了解什么是左值和右值。左值具名,对应指定内存域,可访问;右值不具名,不对应内存域,不可访问。临时对像是右值。左值可处于等号左边,右值只能放在等号右边。区分表达式的左右值属性有一个简便方法:若可对表达式用 & 符取址,则为左值,否则为右值。1.简单的赋值语句如:int i = 0;在这条语句中,i 是左值,0 是临时值,就是右值。在下面的代码中,i 可以被引
摘要: 本次介绍一种调用dll函数的通用简洁的方法,消除了原来调用方式的重复与繁琐,使得我们调用dll函数的方式更加方便简洁。用过dll的人会发现c++中调用dll中的函数有点繁琐,调用过程是这样的:在加载dll后还要定义一个对应的函数指针类型,再调用GetProcAddress获取函数地址,再转成函数...
摘要: 先简单说说ORM的优点:提高开发效率,减少重复劳动,只和业务实体打交道,由业务实体自动生成sql语句,不用手写sql语句。简单易用, 可维护性好。隔离数据源,使得我们更换数据源时不用修改代码。SmartDB基础库 java和c#中有很多ORM框架,如c#中的entity framework、Linq to Sql、NHibernate等,java中有Hibernate、Mybatis等等,其它各种开源的ORM库多如牛毛。这应该得益于托管语言在这方面的优势。然而,c++的世界中,却鲜有ORM框架,c++中比较知名的ORM库应该是ODB了,但是ODB的使用比较麻烦,需要三个库,写的ORM代码还需.
摘要: 本次要讲的是如何通过泛型函数来简化我们的程序。 泛型函数除了之前介绍的一些优点外还有两个重要的优点1.消除重复逻辑,提高程序的内聚性和健壮性 泛型函数在某种程度上用来弥补泛型类型的不足。通过泛型类型T可以消除一些重复代码,当不同的类型具有相同的行为时,通过泛型擦除类型,达到消除重复简化代码的目的。例如:templateauto Add(T a, T b)-&decltype(a+b){ return a +}void TestAdd(){ auto r1 = Add(1, 2); //3 auto r2 = Add(1.2, 3.5); //4.7 aut...
摘要: 这次要讲的内容是:c++11中的tuple(元组)。tuple看似简单,其实它是简约而不简单,可以说它是c++11中一个既简单又复杂的东东,关于它简单的一面是它很容易使用,复杂的一面是它内部隐藏了太多细节,要揭开它神秘的面纱时又比较困难。 tuple是一个固定大小的不同类型值的集合,是泛化的std...
摘要: 这次要讲的内容是:c++11中的lamda表达式。 lamda表达式是我最喜欢的一个c++11特性之一,在我的代码中随处可见它的身影,其实在c#3.5中就引入了lamda,java中至今还没引入,要等明年的java8中才有lamda表达式,lamda来源于函数式编程的概念,也是现代编程语言的一个特点。c++11这次终于把lamda加进来了。也许有人要问,lamda有什么好处,为什么要加到c++中来?lamda表达式有这些优点:声明式编程风格:就地匿名定义你的目标函数或函数对象,不需要额外的写一个命名函数或者函数对象。以更直接的方式去写程序,好的可读性和可维护性。简洁:不需要额外再写一个函...
摘要: 这次要讲的是:c++11中的bind和functionstd::function它是函数、函数对象、函数指针、和成员函数的包装器,可以容纳任何类型的函数对象,函数指针,引用函数,成员函数的指针。以统一的方式处理函数、函数对象、函数指针、和成员函数。允许保存和延迟执行函数。函数和成员函数作为functionvoid G();struct A{void H(){}};std::function f = G; //全局函数Astd::function f 1= std::bind(&A::H, a); //成员函数可以用function取代函数指针。因为它可以保存函数延迟执行,所以比较
摘要: 这次要讲的是:c++11统一初始化、统一begin()/end()和for-loop循环如何简化我们的程序初始化列表c++11之前有各种各样的初始化语法,有时候初始化的时候还挺麻烦,比较典型的如vector和map的初始化。for(int i=0;for(int i=0;i v = {0,1,2,3,4,5,6,7,8,9};map map = {{0,0},{1,1},{2,2,{3,3}};不用再手动去push_back或者insert了,这样写很简单也很直观。不仅仅是容器的初始化可以这样,普通的数组也可以这样写:int int_array[3] = {1,2
摘要: 这次要讲的是:C++11如何通过组合函数来简化我们的程序。关于组合函数,大家可能对这个概念有点陌生。组合函数是将N个一元函数组成一种更复杂的函数,每个函数的返回值作为参数传给下一个函数,直到传到最后一个函数结束。这种组合函数的能力可以使我们以一种更直观的方式去完成复杂的链式执行行为。例如有三个函...
摘要: C++11在很多方面可以简化我们的程序开发,我会在“简化我们的程序”这一系列的博文中一一讲到,敬请关注。这次要讲的是:C++11如何通过获取函数模板的返回值类型来简化我们的程序。在谈到简化之前,我们先看一个问题,这个问题也是我前段时间在开发C++版本的linq时遇到的。假设我们现在需要将集合按某种属性分组,就是类似于sql语句中的group by,我们知道group by后面的字段会组成一个唯一的键,得到的结果是按照这个唯一键值的分组。关于group by具体看一个例子就清楚了。struct Person{};vector vt
摘要: c#和java中有自动垃圾回收机制,.net运行时和java虚拟机可以管理分配的堆内存,在对象失去引用时自动回收,因此在c#和jva中, 内存管理不是大问题。c++语言没有垃圾回收机制,必须自己去释放分配的堆内存,否则就会内存泄露。 我相信大部分c++开发人员都遇到过内存泄露的问题,而查找内存...
摘要: c++11 boost技术交流群:,欢迎大家来交流技术。关于类型擦除,可能很多人都不清楚,不知道类型擦除是干啥的,为什么需要类型擦除。有必要做个说明,类型擦除就是将原有类型消除或者隐藏。为什么要擦除类型?因为很多时候我不关心具体类型是什么或者根本就不需要这个类型,通过类型擦除我们可以获取很多好处,比如使得我们的程序有更好的扩展性、还能消除耦合以及消除一些重复行为,使程序更加简洁高效。归纳一下c++中类型擦除方式主要有如下五种:第一种:通过多态来擦除类型第二种:通过模板来擦除类型第三种:通过某种容器来擦除类型第四种:通过某种通用类型来擦除类型第五种:通过闭包来擦除类型第一种类型
摘要: c++11 boost技术交流群:,欢迎大家来交流技术。本次要讲的时候如何改进代理模式,具体来说是动态代理模式,动态代理模式一般实现AOP框架,不懂AOP的童鞋看这里。我前面的博文也实现了一个AOP框架(可以参考我前面的博文:(原创) C++ 轻量级AOP框架),但是那个AOP框架...
摘要: 所谓表驱动法(Table-Driven Approach),简单讲是指用查表的方法获取值。表驱动是将一些通过较为复杂逻辑语句来得到数据信息的方式,通过查询表的方式来实现,将数据信息存放在表里。对于消除长的switch-case和if-else-if语句来说很有效,比如下面的代码:string Get...
摘要: 和单例模式面临的是同样的问题,主题更新的接口难以统一,很难做出一个通用的观察者模式,还是用到可变模板参数解决这个问题,其次还用到了右值引用,避免多余的内存移动。c++11版本的观察者模式支持注册的观察者为函数、函数对象和lamda表达式,也避免了虚函数调用,更简洁更通用。直接看代码。template...
摘要: 本次讲c++11改进我们的模式之改进访问者模式访问者模式是GOF23个设计模式中比较复杂的模式之一,但是它的功能也很强大,非常适合稳定的继承层次中对象的访问,可以在不修改被访问对象的情况下,动态添加职责,这正是访问者模式强大的地方,但是它的实现又造成了两个继承层次的强烈耦合,这也是被人诟病的地方,可以说是让人爱又让人恨的模式。c++11实现的访问者模式将会解决这个问题。我们将在c++11版本的访问者模式中看到,定义新的访问者是很容易的,扩展性很好,被访问者的继承层次也不用做任何修改。具体代码:templatestruct Vtemplatestruct Visitor : Vis
摘要: 我会写关于c++11的一个系列的文章,会讲到如何使用c++11改进我们的程序,本次讲如何改进我们的模式,会讲到如何改进单例模式、观察者模式、访问者模式、工厂模式、命令模式等模式。通过c++11的改进,我们的模式变得更通用、更简洁、更强大。本次讲如何改进单例模式。在c++11之前,我们写单例模式的时候...京 东 价:
[定价:¥]
PLUS会员专享价
您购买此商品可享受专属价
增值业务:
重  量:
搭配赠品:
选择套装:
服务支持:
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
Linux多线程服务端编程 使用muduo C++网络库
商品介绍加载中...
扫一扫,精彩好书免费看
京东商城向您保证所售商品均为正品行货,京东自营商品开具机打发票或电子发票。
凭质保证书及京东商城发票,可享受全国联保服务(奢侈品、钟表除外;奢侈品、钟表由京东联系保修,享受法定三包售后服务),与您亲临商场选购的商品享受相同的质量保证。京东商城还为您提供具有竞争力的商品价格和,请您放心购买!
注:因厂家会在没有任何提前通知的情况下更改产品包装、产地或者一些附件,本司不能确保客户收到的货物与商城图片、产地、附件说明完全一致。只能确保为原厂正货!并且保证与当时市场上同样主流新品一致。若本商城没有及时更新,请大家谅解!
权利声明:京东上的所有商品信息、客户评价、商品咨询、网友讨论等内容,是京东重要的经营资源,未经许可,禁止非法转载使用。
注:本站商品信息均来自于合作方,其真实性、准确性和合法性由信息拥有者(合作方)负责。本站不提供任何保证,并不承担任何法律责任。
印刷版次不同,印刷时间和版次以实物为准。
价格说明:
京东价:京东价为商品的销售价,是您最终决定是否购买商品的依据。
划线价:商品展示的划横线价格为参考价,该价格可能是品牌专柜标价、商品吊牌价或由品牌供应商提供的正品零售价(如厂商指导价、建议零售价等)或该商品在京东平台上曾经展示过的销售价;由于地区、时间的差异性和市场行情波动,品牌专柜标价、商品吊牌价等可能会与您购物时展示的不一致,该价格仅供您参考。
折扣:如无特殊说明,折扣指销售商在原价、或划线价(如品牌专柜标价、商品吊牌价、厂商指导价、厂商建议零售价)等某一价格基础上计算出的优惠比例或优惠金额;如有疑问,您可在购买前联系销售商进行咨询。
异常问题:商品促销信息以商品详情页“促销”栏中的信息为准;商品的具体售价以订单结算页价格为准;如您发现活动商品售价或促销信息有异常,建议购买前先联系销售商咨询。
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
浏览了该商品的用户还浏览了
加载中,请稍候...
七日畅销榜
新书热卖榜
iframe(src='///ns.html?id=GTM-T947SH', height='0', width='0', style='display: visibility:')Instagram的技术架构
Instagram 被 Facebook 以10亿美金收购。团队规模:13 人。而在被Facebook收购前的一个月,整个团队才7名员工。
2010年: 2位工程师
2011年: 3 位工程师
2012年: 5 位工程师
制胜法宝:
广泛的单元测试和功能测试
坚持DRY(Don’t Repeat Yourself)原则
使用通知/信号机制实现解耦
我们大部分工作使用Python来完成,只有逼不得已的时候,才会用C
频繁的代码复查,尽量保持“智慧共享”。(frequent code reviews, pull requests to keep things in the ‘shared brain’)
广泛的系统监控
Instagram的两个创始人
Mike Kriegerr:之前是一个颇为低调的工程师和用户体验设计师,他在一家名叫Meebo的创业公司工作了1年半。analytics & python @ meebo(在Meebo做分析,使用python );
Kevin Systrom:毕业后在Google的收购部门工作了一年,今年28岁,随后去到了一家从事旅行业务的创业公司Nextstop,没有计算机学位,没有接受过正式培训, 但他下班后坚持自学编程,在这家创业公司被Facebook以人才收购的方式收购后,Systrom又去早期的Twitter实习了一段时间。
下面一起来看下这个奇迹是怎样搭建的?Instagram的技术实现是什么?以下内容来自翻译。
当我们与其他工程师偶遇和交流的时候,有一个问题经常被问及,“你们的技术架构(technology stack)是怎么样的”?我们觉得从较高的层次来描述Instagram的所有构成系统是一件有趣的事情;未来你可能期待更深入的描述这些系统。这就是我们的系统,仅仅1年时间,并且我们活了下来,其中有一部分我们一直在修改。一个小型团队的初创公司,可以在一年多一点时间发展到1400多万用户规模。
Instagram 开发团队奉行的三个核心原则:
Keep it very simple (极简主义)
Don’t re-invent the wheel (不重复发明轮子)
Go with proven and solid technologies when you can(能用就用靠谱的技术)
操作系统/主机
我们在Amazon EC2上跑Ubuntu Linux 11.04 (“Natty Narwhal”),这个版本经过验证在 EC2 上够稳定。我们发现之前的版本在EC2上高流量的时候都会出现各种不可预测的问题( freezing episodes)。因为只有3名工程师,我们的需求依然在不断的变化中,因此自托管主机不是我们的选择,也许未来当用户量空前增长的时候,我们会考虑。
每一个对Instagram 服务器的访问都会通过负载均衡服务器;我们使用2台机器做DNS轮询。这种方案的缺点是当其中一台退役时,需要花时间更新DNS。最近,我们转而使用Amazon的ELB(Elastic Load Balancer)负载均衡器,使用3个NGINX 实例可以实现调入调出(and are automatically taken out of rotation if they fail a health check);我们同时在 ELB 层停掉了 SSL , 以缓解nginx的 CPU 压力。我们使用Amazon的Route53服务作为DNS服务,他们最近在AWS控制台上增加了一套很好的GUI工具。
应用服务器
接下来是应用服务器用来处理我们的请求。我们在Amazon的High-CPU Extra-Large机器上运行了 ,随着用户的增长,我们已经在上面跑了25个实例了(幸运地,因为是无状态的,所以非常便于水平扩展)。我们发现我们的个别工作负载是属于计算密集型而非IO密集型,因此High-CPU Extra-Large类型的实例刚好提供了合适的比重(CPU和内存)。
作为 WSGI 服务器。过去曾用过 Apache 下的 mod_wsgi 模块,不过发现 Gunicorn 更容易配置并且节省 CPU 资源。使用
加速部署。最近增加了并行模式,因此部署只需要花费几秒钟。
我们大部分数据(用户信息,照片的元数据、标签等)存储在PostgreSQL中;我们 已经说了关于如何基于不同的Postgres 实例进行切分的。我们的主要分片集群包含12个四倍超大内存云主机(且12个副本在不同的区域);
我们发现亚马逊的网络磁盘系统(EBS)每秒的寻道能力不够,因此,将我们所有工作放到内存中就变得尤为重要。为了获得合理的性能,创建了软 RAID 以提升 IO 能力,使用的
工具进行 RAID 管理;
顺便提一下,我们发现用来管理内存数据是个极好的工具,尤其是在故障转移时,从一台机器到另一台机器,甚至没有活动的内存概要文件的情况。,用来解析运行于一台机器上的vmtouch 输出并打印出相应vmtouch命令,在另一台机器上执行,用于匹配他当前的内存状态;
我们所有的PostgreSQL实例都是运行于主-备模式(Master-Replica),基于流复制,并且我们使用EBS快照经常备份我们的系统。为了保证我们的快照的一致性(原始灵感来源于)我们使用XFS作为我们的文件系统,通过XFS,当进行快照时,我们可以冻结&解冻RAID阵列。为了进行流复制,我们最爱的工具是。
对于从我们的应用服务器连接到数据,我们很早就使用了做连接池,此举对性能有巨大的影响。我们发现有大量的关于Django、PostgreSQL 和Pgbouncer 秘诀的资源。
照片直接存储在亚马逊的S3,当前已经存储了几T的照片数据。我们使用亚马逊的CloudFront作为我们的CDN,这加快了全世界用户的照片加载时间(像日本,我们第二最受欢迎的国家)
我们也广泛的使用了 ; 我们的main feed、activity feed、sessions系统(),和其他
都使用了。因为所有的Redis数据都需要放在内存中,因此我们最后使用了几个四倍超大内存云主机用于跑Redis。我们的Redis也是运行于主-备模式(Master-Replica),并且经常将DB保存到磁盘,最后使用EBS快照备份这些数据(我们发现在主机上进行导出太费劲了)。由于Redis 允许写入备份,使得在线故障转移非常方便,转移到一台新的Redis 机器,而不需要停机。
为了我们的,我们一直使用PostgreSQL了很多个月,不过后来迁移到了.他有一套简单的JSON接口,这样我们的应用程序相关的,只是另一套API而已。
最后,和任何现代Web服务一样,我们使用了Memcached 做缓存,并且当前已经使用了6个Memcached 实例,我们使用pylibmc & libmemcached进行连接。Amzon最近启用了一个灵活的缓存服务(Elastic Cache service),但是它并不比运行我们自己的实例便宜,因此我们并没有切换上去;
任务队列&推送通知
当一个用户决定分享一张Instagram 的照片到Twitter 或Facebook,或者是当我们需要通知一个 有一张新的照片贴出,我们将这个任务推到 ,一个任务队列系统能够写于Danga。这样做的任务队列异步通过意味着媒体上传可以尽快完成,而“重担”可以在后台运行。我们大概有200个工作实例(都用Python写的)在给定的时间内对队列中的任务进行消费,并分发给不同的服务。我们的feed feed fan-out也使用了Gearman,这样posting就会响应新用户,因为他有很多followers。
对于消息推送,我们找到的最划算的方案是,一个开源的Twisted 服务,已经为我们处理了超过10亿条通知,并且绝对可靠。
对于100多个实例,监控变得非常重要。我们使用进行图形化度量。我们基于,也写了很多Munin 插件。用于图形化度量非系统级的东西(例如,每秒的签入人数,每条照片发布数等)我们使用作为外部监控服务, 用于事件通知。
Python错误报告,我们使用,一个Disqus的工程师写的令人敬畏的开源的Django app。在任何时间,我们可以开始工作,并实时的查看我们的系统发生了什么错误。
以上内容翻译自:
Instagram的技术变迁
创业初期:
初存储采用CouchDB(Apache CouchDB 是一个面向文档的数据库管理系统)
最初只有一台服务器(在洛杉矶),比一台比MacBook Pro强不到哪里去。
一、数据库扩展
早期使用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),即预先切分上千个逻辑切片,将它们映射到较少的物理分区节点中去。
关于相关内容,更详细的可以参看。
二、选择合适工具
进行缓存/反规范化数据设计
用户上传图片时:
用户上传带有标题信息和地理位置信息(可选)的照片;
同步写到这个用户对应的数据库(分片)中;
进行队列化处理
a、如果带有地理位置信息,通过异步的POST请求,将这个图片的信息送到Solr(Instagram 用于的全文检索服务器)。
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适合什么样的场景?
数据结构相对有限;
对频繁GET的地方,对复杂对象进行缓存;
不要将自己绑定在非得以内存数据库为主要存储策略的方案上(don’t tie yourself to a solution where your in-memory DB is your main data store
参考链接:
Instagram的技术架构

我要回帖

更多关于 boost bind function 的文章

 

随机推荐