Randy用了两个例子来解释Message Dispatch。分别是Event Streams和Search Feeder Infrastructure。
Event Streams
- Primary use case produces event
- E.g.,ITEM.NEW, BID.NEW, ITEM.SOLD, etc.
- Event typically created transactionally with insert/update of primary table.
- Consumers subscribe to event
- Multiple logical consumers can process each event.
- Each logical consumer has its own event queue.
- Within each logical consumer, single consumer instance processes event.
- Guaranteed at least once delivery; no guaranteed order.
- Managing timing conditions
- Idempotency: processing event N times should give same results as processing once.
- Readback: consumer typically reads back to primary database for latest data.
用一个常见的例子来说明上面的文字。让用户list an new item或者bid an item的时候,会在数据库表中插入或者更新一些记录,于此同时,一个相应的事件Event创建了。
我们有很多的Logical Event Consumers在侦听他们所感兴趣的事件,比如刚才的Item.New事件,我们有Image Processing的Consumer来处理用户上传的图片;我们有用于Summary Update的Consumer…很多很多。这些逻辑Event Consume都有自己的Event Queue。这就是说Consumer之间是独立的。这样的设计也非常容易Scale,只需要增加更多的Consumer就可以了。
接下来就是时序的问题,因为异步往往不能保证时序。事件的处理有可能是out of order的。这里有两个概念:
Idempotency:http://en.wikipedia.org/wiki/Idempotent ,而在这里,我们更关心的是 the ability of a system to produce the same outcome, even if an event or message is received more than once.
ReadBack这个概念也很精巧,类似于By Reference,其实所有的Event本身都不carry database data。他们总是去数据库拿最新的数据。
<注:关于时序问题,我觉得Randy这里的解释还是比较抽象的,最好有一个实际的例子能够帮助我们理解,我再去问问,不知道CDC有没有做Messaging的group。>
Async Everywhere[Search Feeder Infrastructure]
这篇Blog给出了eBay Search Engine的整个架构。而这个架构正是Message Dispatch的另一个非常好的实例。要不是Randy来给我们做演讲而促使我去网上搜索eBay Architecture的文章,我还真没有想到这样的架构也是公开的。
先看一下架构图:
简单来说,Search Feeder的工作就是从存放Item信息的Primary DB中提取数据,处理后填入Search Infrastructure中。Feeder会不停的(定时的)查看Primary DB中是不是有数据更新,将更新数据提取(constantly polling)出来,做一些内部的处理以后,把“更新”publish给所有的search nodes。而每个search nodes会侦听自己感兴趣的更新信息来更新自己,如果search nodes发现自己有“更新”"漏听"了的话,他们会要求feeder重发更新。
从使用的技术的概念上讲,其实就是Message Dispatching。
- Feeder reads item updates from primary database
- Feeder publishes updates via reliable multicast
- Persist messages in intermediate data store for recovery
- Publish updates to search nodes
- Resend recovery messages when messages are missed
- Search nodes listen to updates
- Listen to assigned subset of messages
- Update in-memory index in real time
- Request recovery
这里有一些我想补充一下,怎么理解Listen to assigned subset of messages?看看上面的图,search nodes是划分(Partition)成一个个Column的,Column的切分方式是预定义好的,一个Column中的Search Nodes是完全一样的,所以Search Nodes只关心划分在自己所在的Column中的更新。还有就是eBay的搜索引擎一个重要的特征就是real time。item的更新应该迅速反反映到搜索引擎中去,不能出现搜索结果上说当前的竞价已经到了200元,而用户点进去一看已经到250元了。更不能说搜索结果上显示物品还没有卖掉,用户点进去看发现已经卖掉了…
图中还有一个细节,就是Search DB。一般不是做Backend的人还不会注意到这点。这个Search DB很重要,目的是为了保留Persistency的信息。整个系统是很精巧的,聚集了当年eBay第一代自主开发自己的搜索引擎的那些元老们的智慧。从个人来说,我很佩服那帮人,他们真的是因为有激情,才做成了这件事情的!我听过这个故事,当年eBay使用的是一个第三方的搜索引擎,一直出问题,情况已经到了很难应付 eBay日益加大的Traffic的地步了,这时候有几个"年轻人"站出来对公司的领导说:"给我们一年时间,我们可以做一个全新的,能够应付将来好多年的搜索引擎!", 领导也很有魄力,于是这些"年轻人"加班加点,最后真的把这件事情做成了!很敬佩他们。
Async Everywhere[Batch]
Batch是Randy在他的演讲中提到的异步处理的技术中的最后一个例子。Randy是这么引入Batch这个话题的:
"如果你去互联网上看热门的技术文章,人们似乎并不再热衷于Batchle ,大家更多谈论的是Message Driven或者Event Driven的系统,但是实际使用中,有太多的情况Batch是最好的选择。"比如说 Scheduled Process,那些每个小时运行一次,或者每天运行一次的任务,每周运行一次的任务…还有一种情况Batch也很适用,就是那些要处理所有的或者一大批数据的,而不是只处理特定的一个两个或者一小部分的时候。Randy叫做"Full Table Scan"的任务。
Pattern: Periodic Batch
- Scheduled offline batch process
- Most appropriate for
- Infrequent, periodic, or scheduled processing (once per day, week, month)
- Non-incremental computation (a.k.a. “Full Table Scan”)
Batch在eBay中应用的典型例子有:从第三方导入数据,比如Catalog信息,汇率信息…产生推荐信息,推荐物品(item)啦,产品(products)啦,等等等等….
- Examples
- Import third-party data (catalogs, currency, etc.)
- Generate recommendations (items, products, searches, etc.)
- Process items at end of auction
这里提到一个例子:Process items at end of auction! Auction是eBay的核心业务之一,Seller登录一个物品,设定一个时间,比如说7天,在这7天里面大家去竞价,7天时间到,价高者得之。在7天结束的那个时间点,没有Event被产生,eBay处理这种情况的方法是 定时跑Batch来发现所有的已经end of action的物品,然后统一产生一个Event来处理。
- Often drivers further downstream processing through Message Dispatch
<注:
说实话,对最后一点Often drivers further downstream processing我并没有完全理解,说没有完全理解是因为来一个项目,我目前无法判断在downstream processing的时候是不是要使用Batch,比如上面的end of action的情况,怎么来处理time of end action和batch runnung的时间差呢?怎么就不能再end of action的时候发一个Event呢?
>