放翁(文初)的一亩三分地

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  210 随笔 :: 1 文章 :: 320 评论 :: 0 Trackbacks
Author:文初

Blog: http://blog.csdn.net/cenwenchu79/

问题

         小丹同学在旺旺上问我是否可以用Memcached实现简易消息中间件类似的功能。觉得这个需求很奇怪,就问了一下具体的应用场景,然后小丹就上来和我具体的谈了究竟需求是什么。其实小丹的应用场景是这样的:客户需要分析一些业务数据,但是业务数据又是很庞大的,在原有系统每天晚上都有一次日分析,将业务数据分析并且归档,但是如果要产生即时分析的效果,用原有系统无法实现,因为当天的数据内容没有被分析,同时如果即时的去分析并且累加到历史分析数据上,性能也不能满足需求,因此考虑通过消息机制来实现异步分析,至于异步处理的时间容忍度,可以通过配置来实现,同时希望异步分析是可线性扩展的,支持集群,提高效率。为什么不直接使用中间件呢?高并发的稳定性,维护的成本,性能要求,使用成本,这些直接就排出了直接去使用中间件的想法。

起始方案的讨论

         在回到小丹最初提到是否可以通过Memcached来实现类似于简易消息中间件的问题上来。首先是否将消息队列作为一个对象保存在Memcached中,这种做法明显不支持高并发的情况,因为Cache本身的get,put无法保证事务。在Memcached中只有计数器是支持高并发的操作,因此考虑是否使用计数器并且按照一定规则来生成key,通过对计数器的增减来让不同消费者获取到不同的消息,这种机制最大的问题在于:1.轮询的压力不小(小丹希望是订阅者模式,Push过去而不是Pull)。2.计数器增减不论怎么做都实现的是栈而不是队列。那么是否使用我扩展的MemcachedKeySet,这点我自己就反对了,这个功能效率很低,而且对于Memcached本身在高并发下操作是否有影响还不得而知。问题越绕越走向死胡同了。

方案的转变

         转换思路,重新分析小丹的需求,究竟哪几点是他真实需要的:1.通过消息方式解耦Web应用和业务分析处理。2.消息必须较为及时的传递到业务分析模块。3.业务分析模块需要支持集群方式线性扩展性能。实现这些需求真的需要简单的消息中间件或者集中式存储么?看看下图的结构:





         从图上可以看出这么几个问题:1.消息中间件本身处于单点,如果需要扩展或者消息本地化增加了复杂度。2.对于消息的获取是采用push还是pull,如果是push那么需要中间件支持订阅者的维护,如果是pull,则需要考虑并发以及性能问题。3.消息的即时性,这个还是依赖于消息中间件的实现机制。总的来说,如果要通过集中式缓存方式实现消息中间件的简单功能,还是有很多问题。那是否直接使用消息中间件的第三方支持呢,其实又回到了最初提出的不使用的缘由。这么设计是否太复杂呢?

回过头来看看Memcached的使用情况,突然发现其实事情可以简单来说,我记得写过一些说明来解释为什么我说Memcached是集中式缓存而不是分布式缓存,其实是客户端的分发算法让很多人觉得好像分布了数据和可无限扩展。其实这种技术结合Hadoop HDFS的部分设计思路,可以给出一个比较好的解决方案。看看下图的结构设计:



上图去掉了消息中间件的角色,增加了Asyn Processor Manager的角色,但是此角色也可以去掉,更为简化的实现需求,增加Asyn Processor Manager的功能仅仅是为了提供动态增减Asyn Processor的功能。具体说一下流程:

1.              Web应用启动时,读取本地配置获取Asyn Processor列表载入内存,同时根据Asyn Processor Manager的配置去发起请求获取Asyn Processor最新的可用列表(如果无法获取,则以本地的为准)。

2.              Web应用根据本地实现的分发算法(最简单就是采用key hash),来选择Asyn Processor,发送请求处理的消息。

3.              如果Asyn Processor Manager不存在,Web应用也可以实现定时发起query status请求来确认Asyn Processor的存活状态,并且更新,保证消息的正常发送。如果Asyn Processor Manager存在,那么确认Asyn Processor状态是否存活可以由Asyn Processor Manager来做(Push或者Pull),而Web应用则可以使用对Asyn Processor Manager的定时查询来获得最新的Asyn Processor列表。

4.              Asyn Processor Manager可以提供增加和删除Asyn Processor的接口,这样就可以支持Asyn Processor的增加和删除,但也正因为Asyn Processor Manager的单点易于注册和管理Asyn Processor,也增加了单点的风险,因此每一台Web应用需要对Asyn Processor Manager不可用作好本地化配置的后备策略。

5.              使用Http协议作为消息传输协议,这样避免SA去维护端口的麻烦,同时也能够充分利用REST的方式来完成业务逻辑(Options方法可以用于心跳,PutDelete可以用于Processor的增减(设置Http Head认证方式即可解决安全问题),Get方式获取信息(xml,json等等格式可以很容易处理))。

上面的方案可以看出,如果去掉Asyn Processor Manager,其实方案很简化,就是每一个客户端有一层类似于Memcached客户端的分发机制,同时比Memcached免去了对于连接池维护的复杂性,仅仅只需要维护状态标示即可。

最后还嘱咐小丹对于Asyn Processor的设计需要合理化,这部分需要支持消息接受和处理的并行处理,提高Asyn Processor的处理能力,同时通过分页批量处理消息的方式减少对于DB的压力(当然需要根据具体的时效性设置消息页的大小以及消息页Flush的时间)。

后话

         上面的方案可能不是最好或者最优的,这里仅仅只是分享一下自己解决这个问题的一些心得。这此的方案讨论也走了一些弯路,有时候在做任何选择以前首先需要考虑的是到底自己需求是什么,然后再去考虑选择什么技术去实现。同时尽量还是那句老话”Make it Simple”,做技术的人总是喜欢做的很复杂,功能很强大,但是最后迷失了最初的目标,忙于去完善那些80%没有用的功能,却没有去做好那20%客户最Care的功能。化繁为简,见招拆招,才能四量拨千斤。
posted on 2008-12-12 11:49 岑文初 阅读(1767) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: