在聊流计算之前,先聊一下儿时的一段记忆。
儿时记忆
记得小的时候,在老家建房子,需要用砖,有几个小工用小车一车一车的推砖送到所谓的大工面前供大工使用。
- 从拉砖的起始地,到大工使用砖的目的地,这个过程都是小工一个人在拉砖,就是单线程的拉砖处理模式;
-
从拉砖的起始地,到大工使用砖的目的地,这个过程都是多个小工在拉砖,就是多线程的拉砖处理模式;
这些小工在拉砖的过程没有任何交集,只是共同拉那一堆砖,直到拉完为止或者供上大工的使用砖的速度为止,如果速度跟不上,则通过增加一个小工也采取类似的过程拉砖;
这种拉砖方式的瓶颈
是否通过这种方式增加小工,就一定能提高拉砖的效率?如果不考虑砖的有限性,通过这种方式增加小工,初期会有效果,但达到一定量之后就会出现瓶颈。最明显的瓶颈量即小工足够多,以致于拉砖的通道都被堵死了。那么有改进的方案吗?答案是肯定的。
拉砖方式改进
当我们有足够的小工给大工运送砖,会采用别外一种模式,
- 小工与小工之间相隔不到1米,从拉砖的起始地排成长队直接排到大工使用砖的目的地;小工之间通过手接手的把砖源源不断的送到了大工的面前,这就是流处理的拉砖模式;
数据处理模式
数据处理,一般情况都是经过经过三步(这个也是传统数据批处理的路子):
- 数据读取
- 数据处理
- 数据写入
在单线程数据处理模式下,即一个线程完成上面的3步,显示效率不高。
为了提高效率,就需要使用多线程,但一般的框架,在1~3步之间仍然是每个线程独立处理自己的数据,而不进行线程的上下文切换。原因就是数据处理的过程的事务以及线程上下文的切换。多线程之间基本没有任何资源共享或者说不需要进行任何数据同步。典型框架spring-batch。
流式计算,打破了这个界限,即数据读取的线程,不会进行数据处理,即线程之间完美的进行数据交换或者说是传递。典型的流式计算框架为storm。它通过远程调用netty及单jvm间disruptor完成这种所谓的数据的传递,同时解决了事务的问题。
storm流计算经典三步走
storm流计算经典三步走,这个词是我发明的。
- storm的数据读取,spout它负责获取数据,并传递至下一站;
- storm的数据处理,bolt它负责数据处理,并传递至下一站;
- storm的数据写入,严格来讲storm没有数据的写入,通过bolt这样一直传下去,但是也可以不往下传递至下一站,你可以写入相应的存储容器;
storm的这样一个过程,称之为topology,即一个拓扑结构。当然storm不会像我讲的那么简单,如果想了解storm,则需要深入的下功夫去学习。我也在学习的路上,一共同行~