上一篇我们花了大部分的口水去说MQ,现在我们要言归正传说说twitter的架构了。
我们说到我们要应付的事情出了大量的消息要转发要处理,还有突然爆发的流量等等。解决这样的问题,思路应该是要提高服务器每秒对请求的响应数。通常我们是将Memcached作为Fragment Cache放在我们前端服务器上。当收到用户请求的时候我们的Router会去判断这样的Fragment Cache是否存在,如果存在的话则直接返回。这样的做法是有效率的,而且就memcahced而言,命中率很高,我们很难去确定请求的来源位置,所以我们不如把预先计算好的数据放在网络前端的RAM上面。
当然在这个之后我们还会有很多的问题,并且在twitter向我们展示的宏大架构中我们找到了一些有用的东西。
首先我们看看twitter用到的这些中间件。
memcached,这个就不说了。
Varnish,是取代Squid的一个HTTP缓存,也就是一个Page Cache,据说性能至少是Squid的四倍。这个数据来源也是据说挪威的在线报纸vg.no,用三台Varnish替代了12台Squid,效果还比之前要好。
Kestrel,是twitter团队开发的一个开源的MQ,持久存储效果不错,听说代码写得也很漂亮1200来行,Kestrel是基于Memcached的文本协议,并对这些协议有所优化和完善。这个东西最初是用Ruby搞的后来又在Scala上实现了一遍。Ruby下的那个版本伸缩性不强,特别是Ruby的GC(垃圾处理)不是分代的,这意味这GC在处理完一个队列之后就会把自己给kill掉,然后MQ就崩溃了。后来移植到Scala上,它有成熟的JVM GC这个机制,而且代码还可以更简要。
Comet,一种服务器push的技术,之前facebook貌似也在用。简单的说,就是Client发送一条请求,然后Server接收到之后进入一个无限循环,将Client需要的数据push到一个response里面并且刷新它,这个response并不会被关闭,而是不断的被push数据然后刷新。知道Client断开连接之后才跳出这个循环。正是这样,我们可以说,Ajax解决了单用户的响应,而Comet则在保障性能的前提下,解决了协同多用户的响应。Comet的优点是它可以随时向客户端发送数据而不是仅仅响应用户的输入请求。而且这个数据是在现有的一个单连接上面进行,所以大大降低了发送数据的延迟时间(建立链接的开销和用户发送请求的开销)。
按照twitter自己的说法,最初他cache的策略简单到无敌,有点让人蛋疼,除了在API那里有一个Page Cache之外,然后啥都没有了。不过还好他80%的流量是来自API的。后来随着发展,twitter进行了强有力的架构的建设,其中cache策略的发展也是飞速。
一、Vector Cache,直接放在Data Pool的上面。存放了tweetID和tweetID之间的关系,tweetID是序列化的64位整数。而直写式的设计保证了极高的命中率,使得程序在Data Pool中工作的效率大大的提高,并且极大程度上加大了Data Pool和上层Cache的关联。
二、再往上是一个Row Cache,存放了数据库信息,主要是用户和tweet详细信息的相互对应。同样是直写式,并且使用了一个叫做Cache-money的程序,这是一个针对rail的ActiveRecord的直写式缓存实现。Rail的ActiveRecord具有很强的灵活性,完全不亚于hibernate,而且使用简单,效率也很高。
三、接着往上依次便是用memcached做的Fragment Cache和用Varnish做的Page Cache。其中Fragment Cache是直接消费Row甚至是Vector中的数据,打包成JSON或者XML。虽然这是一个直读式的Cache,但是由于特殊的层级关系和工作特性,他的命中率依然能达到95%以上。
这样的缓存策略下,数据库的大部分压力都被转到了后端程序中,而后端程序对资源的占用较为平滑,可预估性也比较强。
另外twitter还提到要为Page Cache提供一个独立的池,理由很简单,他们希望能够为Page Cache提供一个永远不会自毁的Cache的,而是一种按时间来划分的键值模式,以致于可以根据HTTP的协议头来对数据进行切片。我不喜欢这样的方式,虽然它应该会很有用,但是当所有的流过的页面都要在留下痕迹时,情况也许就会变得不太可控。
这样的Cache的架构也有他的问题,因为底层的两个直写式的Cache总是要去修补上面直读式Cache中的数据,这必然会造成MQ的压力。但毕竟有舍才有得,或许这才是架构的魅力吧。
Full story »
今天看了twitter关于cache的策略,领略了cache的威力,抒发了一下情感。
Everything runs from memory in Web 2.0.
优化Cache的策略是为了什么,不外乎三点:
减少IO,减少传输,减少CPU计算,减少同时工作的服务器的数量。
对结果进行共享,比如搜索,通常我们将关键词和结果串化进行Cache,然后在时间范围内使用Cache来对分享服务器工作结果。
更快。这永远都是终极的目标。
通常的架构,对于Cache而言,我们有两层,最前端是一个Page Cache,然后是Memcached,最下来就是Data Pool。
这样的架构下我们能够解决大部分的问题,特别是在处理更多常态化的需求时,访问量平稳,数据提交远小于数据读取。但是这么做有瓶颈特别是对于2.0的网站,我们要应付越来越多的用户数据,要不断的缩短Page Cache的有效时间,我们还得应付更多的异常的流量爆发,于是这样的简单的策略就不顶用了。除非我们不计成本的增加我们的服务器,加大我们的带宽,但也许你的老板会说找你还不如请IDC的人吃饭。我们是架构师嘛,为了不让老板这么说,那我们就得找出策略来。
对于无穷无尽的用户数据的提交,我们通常会想到MQ。说说MQ是个什么东西。他是一种消息队列的处理方式,消息列队是分布式应用间交换数据的一种技术,队列被存在磁盘或者RAM里,队列里面是消息,消息直到它被app读走才被删除。这种机制使得app可以独立的运行,它们不必知道各自的位置和状态,执行过程中也不需要等待其他app的响应。
MQ的最上层是一个消息管理器,下面是队列,队列里存放消息。中间是通道,这里是通道是消息传递的管道,是建立在物理网络中的概念,可以说通道MQ整个概念的精华。通道通常被分为三种,消息通道,MQI,Cluster通道。消息通道是一个单向的通道,有Post, Get, Request, Server等不同的类型,一般是建立在MQ服务器与其他事务服务器之间;MQI是建立在app与MQ之间的,是双向的通道;而Cluster通道则是建立在不同的MQ服务器或者同一MQ集群下的不同消息管理器之间。
MQ的工作原理差不多可以来说。
我们先看看单个系统的情况。app1发送一条消息到MQ,并告诉它消息属于队列1,于是MQ则将消息放到队列1里面,app2便可以读取这个消息然后MQ等待app2读取后把这条消息del掉。
下面这个便要复杂一些。app1发送一条消息到MQ,并告诉它消息属于队列2,然而MQ将消息放到队列2之后发现,这个队列其实是在sysB里面的,这时候MQ会把消息放到一个特殊的传输队列中,然后我们建立一个cluster通道,这个通道更像是一个代理app,这个代理app读到数据并传输到sysB,而在确认sysB真正获取到消息之后MQ才释放掉这条消息。在这里我们意识到MQ在确保消息的准确传输,并且一条消息只有一次这样的传输。
移步:缓存,缓存,缓存(二)—— 言归正传说twitter
Full story »
学习JAVA的过程中,最让我郁闷的恐怕就是接口这个东西了。这个Interface,一度让我觉得是个鸡肋,看清楚,是鸡肋不是基类。在我一直的意识中,OO就是抽象,继承,再抽象,再继承。而这个接口在我看来无非是一个继承的替代品,一个多重继承的替代品。
可以为什么,我们要做接口而不是直接实现多重继承呢,JAVA开发组毕竟不是傻的。我带着疑问询问了google和还有一些前辈。
interface,可以说是class的类别,也可以说是对class的定义的一种规范。把不同的对象放到不同的接口里面,然后更好的管理它们。是一种对对象的抽象。
抽象这个词在这里额外的重要。其实对于继承来说,继承的意义也并不是完全在于我想要复用代码,而是在抽象。假设我们有类A里面有一函数run,类B也想用这个方法。于是有些人就class B extends A,这样的做法是不经过大脑的。其实我们有办法来实现而不造成更大的负担,比如:
class B {
function run() {
A a = new A();
A.run();
}
}
这种想要靠继承来完成代码复用的思想可以说是对继承的滥用,而Java取缔多重继承实际上也是在制止这样的滥用继承,体现更好的设计模式。实际上,当我们想要去抽象对象的行为,而不考虑对象的本身属性的时候,我们就应该使用接口来处理对象与对象直接的通信。
另外,接口还能帮助我们更快的开发,而不用在父类与父类之上在建立一个父类,从而面对多级继承带来的负担。比如我们这时候要描述一个吃东西的行为。我们只需要有这样的一个接口。
interface eat {
function go() {}
}
这时候我们就不用去考虑是人还是狗,是黑人还是白人,吃东西前会做祈祷还是会先喝汤,即便他是个火星人,即便他吃饭前会玩一次躲猫猫,只要你觉得它要吃东西,那么你就让他使用这个接口,然后具体的实现它。这样如果我们把这些类的实例化放到一个工厂里,就能更好的体现出一个接口的抽象化。
Full story »