大数据的Reactive之道

这是一篇可能来自股票高频交易的系统架构文章,主要讲解如何基于EventSourcing建立一个高性能大数据的实时查询系统。

当前IT正在从基于查询的面向批处理系统转向实时更新系统,虽然目前这只是发生在金融领域(量化交易模式,互联网金融等等),但是还是有其他例子,比如 Just-In-Time的物流系统,航空公司根据乘客座位实时定价,如Ebay的C2C拍卖系统,实时交通控制等等,这种趋势将会继续发展下去,因为信息的价值随着时间变化,时间越久,价值越低,互联网金融交易是这方面的一个先行者,因为有些微妙时间的优势可以获利数百万美元,其实时处理系统发展得非常迅速。

传统的IT不是很适应Reactive即时反应的事件系统,从数据库查询到基于请求和响应的Http协议,通用的范式是存储数据然后在需要时查询数据。

当前的数据库是静态的面向查询的
当前的数据管理方法,如SQL和NOSQL数据库侧重于数据处理和数据的静态查询。数据库提供便利的切片和切块的数据,但它们不支持实时的复杂更新查询。NOSQL数据库仍然集中在计算一个静态的结果。数据库显然不是“reactive即时反应” 。

当前的消息产品缺乏查询过滤的强大选项
查询/过滤是目前消息产品的薄弱。消息被分成不同的流(或主题topic),这样客户可以在接收到数据时实现数据原料的预选工作。例如做一个'on-top'过滤,通常意味着一个客户端应用程序接收大于所需10倍以上的数据。Topic的缺点是,通常要根据系统的数据设计指定不同的Topic,假设是一个股票系统,每个股票是一个Topic,那么客户端订阅所有这些股票Topic频道,然后再进行根据活跃程度排序,而这需要反复查询,这又意味着要重新搜索所有历史消息。带来的复杂性和负载是很大的。

解决方案
基于event sourced的实时处理系统,一种能处理大量高扩展的查询处理系统,EventSourced就意味做用交易事件的日志实现通常状态的持久,系统状态保存在内存中,如果需要进行历史分析,或崩溃时需要恢复,通过交易日志重播实现,客户端并不是主动查询,而是监听事件流。

事件源系统的一个问题是"late joining client", 客户端为了获得系统的某个时刻的状态,将得重播整个系统的历史事件,为了解决这个问题,一种称为"Last value Cache"(LVC)的组件可以解决,LVC保持的是当前系统状态,并允许后来者late joining通过查询启动,当客户端数量增加时,LVC组件将又变成瓶颈。

在一个持续查询的系统中,查询结果将自动根据日期缓存,使用订阅取代查询:


subscribe * from Orders where
symbol in ['ALV', 'BMW'] and
volume > 1000 and
owner='MyCompany'

创建一个消息流,其最初执行查询操作,然后无论影响结果集的数据改变什么时候发生,就更新结果集,(透明到客户端应用程序)。该系统可保证每个订阅用户收到确切必要的更改通知,以保持这些客户端的“活”的新鲜的查询结果。


该图展示一个分布式连续查询系统:采用LVC节点保存数据。交易通过消息总线(红色)被发送到他们。该LVC节点计算交易引起的实际差异并通过消息总线(蓝色)发送更改通知。这使得“processing nodes”以保持他们的相关数据分区的镜像实时更新。外部客户端通过TCP/ HTTP连接并不监听消息总线(因为多播是不是在广域网中的选项)。 "Subscription processors"通过监听(蓝色)消息总线保持客户端的连续查询是最新数据,并且分发更改通知。

与传统静态数据管理的区别
1. 高写入量
一次真正的创建一个高容量的数据写访问/改变的系统。

2.较少的全表扫描。
只有后期加入(late-joining)的客户端或查询的条件变化需要一个完整的数据扫描。读/写比率: 1:1。

3.大多数负载是在评估订阅每个数据变化的活动查询时产生。考虑一个交易是每秒100.000变化,并且有10.000活动连续查询,这需要每秒查询条件100.000 * 10.000 = 1亿的评估。这仍然是一个低估:当一个记录被更新,但它必须经过验证其更新前的查询条件是否匹配更新后匹配。 一个记录的更新可能会导致添加或删除一个交易到查询订阅上。


这种架构下,数据是在一个面向列族的表中,每个表的数据均匀地分割在所有数据网格节点(=最后一个值缓存节点=“LVC节点”)。通过增加数据节点的集群,容量增加,快照查询也是并发地加快由增加。有三种网格节点处理的基本交易/消息由数据:
AddRow(表,NewRow),
RemoveRow(表,ROWID)
UpdateRow(表,ROWID,Diff)。

数据网格节点提供行迭代一个酷似lambda(行迭代器)接口(使用纯java代码)。这可以被用来执行map-reduce作业,满足新订阅客户端需要初始查询。

由于连续查询的计算是在“网关”节点完成,数据节点的负载和客户端的数量只有弱相关。

通过数据网格节点处理的所有交易使用多播播出“更改通知”的消息。

网关节点[gateway nodes
网关节点跟踪所有客户端应用程序的订阅/连接。他们倾听全局事件流中的变更通知,检查是否有一个影响持续查询结果的改变发生,这是CPU密集型的。

做两件事:

1.通过使用简单的Java从JIT编译定义查询和查询条件,无需分析和解释的查询语言。HotSpot是这个星球上最好的优化的JIT编译器之一。

2.由于组播用于全局变化的数据流,可以在不影响集群吞吐量下增加额外的网关节点。

处理器节点Processor (or Mutator) Nodes
这些节点实现在最上层集群数据逻辑。例如一个统计处理器为每个表实现连续查询,递增每个表中行数计数数目,并将结果写回一个“统计”表,所以监视客户端应用程序可以订阅当前表的实时数据。另一个例子是在证券交易所上市的“Matcher匹配器处理器”,监听一个股票的订单,如果订单匹配,则删除它们,并增加了交易到“交易”表。如果将整个集群作为一种“巨人电子表格”,处理器是此电子表格中的公式。

总结
这种支持持续查询系统的实时处理软件特点是:
1.是一个大型MVC模型 - 视图 - 控制器。
这个模式在GUI应用程序使用了几十年都没有扩展到后端的数据存储系统。

2.任何服务器端的处理可以以一种自然的方式进行分配。处理器节点使用连续查询创建一个数据分区的内存镜像。处理结果发送回的数据网格。计算密集的工作,例如投资衍生物的风险计算可通过添加处理器实例订阅数据的不同分区(“分片”)进行缩放。

3. 代码库的规模显著减少(包括业务逻辑和前端)。
传统系统中大量的代码用于处理数据以保持最新状态。

[该贴被banq于2014-01-05 21:15修改过]