Storm在这个问题上失误了,它让开发者自己管理对持久状态的访问。在Storm中有两种访问持久状态的方法。第一种是,在Storm中每个工作过程都 能够通过增加本地第三方存储来存储自己的状态。Memcached和Redis是如今非常流行的本地存储解决方案。增加本地存储使得每个状态的数据元组能 够顾忌之前的数据元组,这样,整个工作过程就变得一目了然了。但是这种“自我构建”的方法有它的负面效果:它无法集成到Storm的容错代码机制当中。 Storm必须通过在一个正在运行的机器上重启工作过程并将数据元组从之前的作业迁移到新的工作过程中,来处理运行失败的工作过程或出错的硬件问题。这种 迁移不包含任何本地状态,无论它是驻留在这个过程中,还是在像Memcached这样的系统中。新的工作过程将失去失败作业中所有的上下文信息。
并且,也很难甚至不可能直接查询那些分散在所有工作进程中的分布式状态。如果每个进程想要一直聚集统计,这些统计数据必须推到另一个系统,使用强大 查询工具进行查询。使用Storm的分布式RPC(远程过程调用)功能来对一些数据进行直接抓取也许是可行的。但是,与如今的SQL和NoSQL数据存储 技术的查询功能相比,这些数据获取的功能被严格限制了。
第二种访问状态的方法是将Storm的工作进程连接到一个集中式的或者分布式的持久化存储 当中,例如Cassandra或HBase。采用这种方法,Storm的处理代码能够访问GB或者TB级别的状态信息,并且能够简单地、独立地从 Storm系统中查询持久化存储的数据。这解决了本地化存储的如上问题:状态不能在唤醒失败进程后重建,并且存储可能以后将要支持更强大的查询。虽然该方 法解决了这些问题,但它大大增加了复杂性,并带来了可靠性的问题。
值得注意的是,Storm 与分离存储结合可能会削弱性能。在内存中处理元组是很容易达到以惊人的速度。为了方便查询冗余状态而使用索引来维护其存储,同时尽可能提供一致性保证,要 付出更多的代价。Storm 系统将被分布式存储的性能所制约。如果处理每个元组时使用外部存储来查询,会造成大量的网络延迟。隐藏这种延迟需要更多的并行性,更多的管理,意味着更多 的复杂性。而现在你可能会有两个系统可能失败。
当分布式存储不可用时,Storm 的工作进程需要处理,这无疑增加来了复杂性。如果这是可能的,即使没有复杂的用户代码,当在 Storm 中使用至少一次语义的时候,开发着也需要在分布式存储中使用至少一次语义。
SQL拓展和快速数据处理
在当今的存储中,兼容ACID,SQL关系型数据库能够比Sorm和其它可代替产品更简单和容易地运行以前不能运行的应用。伴有ACID事务关系型数据库简化数据获取在至多一次或至少一次语义的的时候是有要求的。因为操作是简单的,要么完全完成或回滚。
大 多数关系型数据库允许数据库托管,事务逻辑:一些甚至允许使用Java代码,像Storm。因此,Storm在使用关系型的系统中提供更多的逻辑与灵活 性。但是不像在Storm中,在一个有着直接并且精心安排的路径状态数据的关系型数据库中,消除出现在混合Storm和一个分布或分区的持久性存储中问 题。
既然已经有了像PostgreSQL这种数据库存储系统,Nathan Marz为什么要创造Storm呢?因为PostgreSQL及其分支既不是横向可扩展的,也没有像Storm那样处理元组数据的吞吐量。但是最近五年一些新的项目进入事务性存储领域,致力于横向扩展、容错和原始吞吐量。这些系统方案有着和Storm一样的扩展性和容错性,并在处理时结合直接的状态操作提供了强大的处理事务语义的功能。
总之,这些新平台提供了Storm的处理流程和逻辑,Cassandra的状态能力,Kafka的摄入语义等。更重要的是,一个分布式的,事务性的(ACID),SQL关系型数据库能够每秒处理成千上万个输入的事务或应用请求。
对于数据快速增长的应用,开发者们仍在寻求一个比 Storm 和其他流处理方案更完整的流处理平台。Storm 需要一个伙伴数据库去处理它所产出的任何分析内容。相比之下,对比已经有一定规模的SQL数据库,开发者可以从数据库中直接进行计算、存储并做实时的查询 分析。