00:00
接下来我们就要把自己当成架构师,当成一个系统的设计者,来考察一下留数据,或者说整个数据处理领域它的发展和演变的过程,那首先我们就得来想一想。传统的数据处理怎么去处理的呢?啊,这就涉及到传统数据的两种非常经典的处理模型,一种叫做事物处理,另外一种叫做分析处理,啊其实这个大家都不陌生啊,因为现在企业里边数据越来越多了,攒的多了之后,那就会考虑到我需要把这些数据收集起来,去做一些,做一些事儿,那有一些事儿呢,是我业务系统就要求的,比如说我有一个后台管理系统,我给一个前端页面有一个网站打开,那肯定就是说点击某一个按钮点一下,比方说我这里边就添加了一个客户,或者说点一下就对某个用户的权限就做了一个提升,做了一个改变,这都是前台发送一个请求,发送一个操作。
01:02
然后后台系统接收到之后呢,就要做出一个响应,那在这个响应的过程当中,可能就会涉及到要去更改一些用户的数据,比方说你要更改它的权限,那是不是你应该先从数据库里边查找到他之前的权限是什么,然后呢,做一个更改之后,再把这个权限数据写入到数据库里面去,所以大家看到传统的事物库里就是对于事物进行响应,来一个事物就结合当前。在数据库里边的状态去做一个更新和计算,然后返回一个响应,所以它的处理流程就是来数据,然后查找这个数据库啊,进行读写操作,然后再返回进行响应,那所有的需要的这个外部数据都是存储在传统的关系型数据库里。之前如果要是做过传统的网站的话,做过后台,那肯定对这个架构是非常非常熟悉啊,整体来讲就分成了计算层和存储层啊,计算层这就是我们的后台服务器,那存储层呢就是数据库。
02:12
当然了,传统不光是这个后台管理系统,比方说订单系统,就是我们的后台业务嘛,用户那边网站上下了一个订单,那发到后台服务器的话,他就要去啊,肯定也是要去查找数据库了,至少他要把这个订单对应的数据要写入到对应的那个表里面去嘛,诶所以跟数据库要有关系,最后再返回一个响应,到底是写入成功了没有呢?或或者说订单状态是不是发生了更改呢?这是要有这个一来一回的响应的。另外还有像我们更加常见的web应用啊,我们的一个APP,用户那边做了一个点击,这边就要做相应的逻辑处理,然后给一个返回,这都是最为经典的事物处理。啊,所以对于事物处理而言,传统来讲啊,它是非踌快的,它是实时的来一个数据就处理一次,但是它的受限呢,就是受限在数据要存储在传统的关系型数据库,传统关系型数据库那肯定就是呃,基于这种关系表,基于这个CQ查询的这些数据库嘛,啊my CQ Oracle投资gra CQ这类的东西,后来呢,又发展出了各种各样的所谓的no CQ,非关系型的这些数据库,比方说像mongo DB,或者像这个red k的这种内存级的数据库,它的响应速度就会快一些啊,或者说还有其他一些应用场景下,HS这种列存储啊,还有像这个ES这种文档型的这种存储,这些都是其他的一些变种,但是呢,它整体来讲。
03:43
除了red的响应速度确实是快,因为它是内存级的嘛,但是red的这个成本是非常高的,所以在数据量更大的时候,它就会受到一些制约了。那另外的一种处理方式呢,就是传说中的分析处理啊,那这就是在这个数据量非常大的场景下应用的嘛,我们就把所有的数据先收集起来,做一个这个ETL,放到我们相应的存储空间里面去,先有一些基本的这些存储,然后把它提取出来,放到分层级设计好的这些表里边去,一般情况我们可能就把它扔到这个have里边去了。
04:19
那然后呢,想要做处理的时候,那那我们就基于have啊,可以用Spark Spark on have去做一个查询,然后用CQ直接去查询里边的相关的想要的统计信息和数据就可以了。这是大家更加熟悉的分析处理,这个呢,它的特点就是数据量可以处理的很大,但是。不够实时啊,所以在传统数据的处理领域可能也听过这样的,呃,两个概念啊,一个叫做OLTP。就是在线的、实时的事物的处理,Transaction交易的处理。另外一个就叫o lap。在线的大量的这个分析处理,所以传统来讲啊,这种事物或者交易的处理和分析处理是两大块儿,事物处理呢,就是数据量可能没有办法太大,造价会比较高,它的响应速度比较快嘛,所以说这个就造价比较高,整个这个数据量不会太大,而分析处理呢,那就是数据量可以非常大,但是它就是离线的。
05:22
响应比较慢。啊,那问题就来了,我们现在想要的是什么呢?想要又快,数据量又大,低延迟还要高吞吐,那那现在该怎么办呢?哎,所以我们自然就想到了这个,我们可以。既然要快,那就要借鉴事物处理的这种架构,还是来一个就处理一下,而如果说这个事物处理这里用关心数据库,它变成了一个瓶颈,扩展起来之后速度也会变慢,造价也会变高,那我们怎么办呢?一个基本的想法就是。直接把它变成一个本地状态存在内存里边,不就很方便可以做扩展了吗?哎,所以基于这样的想法呢,就提出了一个有状态的流处理这样的一个基本的概念啊,那什么叫做有状态的流处理呢?简单来讲,看这个图,它其实就是把事物处理的这个过程,每一个数据来了之后啊,还是这里边我们有一个应用逻辑,要做处理,要做计算,只不过呢。
06:25
存储层没有单独的分开。前我们在这里是分开了计算层和存储层,现在呢,存储层就是在本地的状态里面,所以大家看,既然就是在本地内存里边,我们把它叫做一个状态,这就取代了我们之前的数据库,那这个存取当然就非常的快速了,就是本地的内存里边一一读一取,当然就很快嘛,然后得到的结果呢,就及时的更新,我们这里的数据,得到了响应,就变成了一个输出。所以我们看所谓的流处理,只是把之前的事物处理的这个一来一回的这个响应看成了一个流式的管道输出而已。整体来讲的话,你如果把它要这个箭头写回到里边去,其实就跟之前完全一样吧,区别只是在于用本地内存里面的状态取代了关系数据库。
07:18
但是这样会有问题啊,这个存在本地内存里边,那这个这不就一药店什么东西都没有了吗?你怎么保证之前我们不是讲要有这个良好的容错性吗?那一定要练故障恢复的时候什么东西都没了,那你难道得从从头开始计算吗?这显然不行,所以为了能够发生故障之后能够正常的恢复。那我们要可以不定时的,也可以定期的去对本地的状态做一个存盘保存。那这个保存就要放到远程的持久化的存储空间去,Spark里面也有类似的概念啊,这个东西叫做checkpoint啊,就是所谓的检查点。就相当于是把我们当前的状态做了一个保存,如果发生故障恢复,从这里直接恢复出来就可以了,这就是所谓的有状态的流处理的一个基本的架构。
08:11
这种方式其实看起来非常简单,所以fair这个项目,2010年的时候研究项目啊,就是基于这样的一个架构搭起来的,这也就是叫做所谓的第一代流处理器啊,另外一个商业化应用非常好的一个代表就是stop,这是流处理的,可以说是先锋啊,它就是第一代流处理器,那它有没有什么问题呢?当然也是有的,我们可以简单的想一下,对于这样一个有状态的流失处理,当前是只有单独的一个节点。那假如数据量很大的时候,你怎么去做扩展呢?哎,之前说了数据量很大,那你扩展集群嘛,所以那就相当于我这里有一个机器,这里面本地保存一些状态,然后处理一些数据,那接下来呢,集群的话就还得有其他的一些机器同样去。保存。
09:01
他自己的这个本地状态,然后读取自己的这些数据,那这里就会发现这两个状态。显然应该是互不相通,各自处理各自的,他们是各自为政的,那这里边传进来的数据也就相当于只是各自处理各自的了。如果要是说想要最后把处理的结果再汇总在一起的话,这里处理的结果要传给另外的一个,比方说这里边处理的一个节点有一个处理的任务。要传给他,那下面的这个分支处理的结果也要传给他,这个时候汇总,这就来了问题了,之前数据的顺序还能保证吗?我们仔细一想的话,就会发现保证不了啊,因为当前分布式的处理架构就必然会产生一个问题,就是数据在传输和处理的过程当中,时间是不确定的。特别是假如前面我们全是分布式啊,就在这一步操作之前,还是一个分布式的操作,那甚至是不是有可能会出现。
10:08
前的一步操作,它同时会向下游,这是同一步操作啊,然后有两个节点都在做这一步操作,那上一步操作呢,有可能同时会往这两个节点传输数据。它传输数据的时候是通过网络传输的呀,那网络传输本身就有延迟,那传到不同的节点是不是这个延迟时间也会不一样啊,有快有慢吧,然后传过来之后呢,在本地做操作的时候,可能也会有快有慢。本地的这个状态不一样嘛,所以就会导致本来这边快的一个数,经过传输处理之后,到这边汇总可能就变慢了。这就会导致之前我们说的数据产生了乱序,有可能会导致我们的结果不准确。那这个问题怎么解决呢?看起来第一代有状态的流式处理没有办法直接解决,那对于这样的一个问题,在批处理里边能够解决吗?
11:08
诶,批处理里边是能够解决的,因为批处理不需要来一个就处理一个呀,要做处理的所有数据我都把它先攒着,都攒起来,那接下来我在汇总想要做计算的时候,那谁前谁后再做个排序就可以了,所以这种方式的话就非常的简单,那我们自然就想到了,你如果要想保证最后处理是正确的,那我再加一个批处理是不是就能保证了呢?啊基于这样的想法。就出现了第二代流处理器。所谓的拉姆达架构。它相当于是在同一个系统里边,同一个架构里边有两套系统。首先数据来了,这是一个数据流,它分成了两层,一层叫批处理层,另外一个叫实时层,其实实时层就是流处理层了啊,就是P处理层,用的是一个P处理器,实时层呢,用的是一个流处理器,那么P处理器我们知道这里边需要去攒一批再处理它,其实就不够快。
12:09
它其实就比较慢,但是它能够保证最终的结果是正确的,而流处理器呢,哎,这边的实时处理的结果可能不太准确,但是它很快来一个数据就会更新一次,来一个数据就会更新一次,所以这样结合起来之后,我们再把它得到的这个处理表再做一个合并处理提交给应用,那么应用那边看到的效果就是什么呢?它就是实时的就在做数据的更新,但是这个这个数据呢,可能不是最终的结果啊,就是假如说我们这个应用有一个有一个屏幕显示,有一个界面显示,那就会发现啊当前的某一个数据。某一个数据的值不停的变化,实时的变化,但是呢,哎,不是最终我们想要的那个值,最终统计的值是到某一个节点的时候,批处理这里的数据全都攒齐了,然后把这个数据都已经统计出来了,诶,这个数据就不再变了。
13:06
比方说我们要统计的是过去一天之内的所有的用户的数量,PV或者UV,那么在之前我们实时统计的时候,可能他不停的在变,不停的在变。那等到批处理结果出来之后,他最终就得到了一个稳定的结果,最后正确的结果,这就是所谓的拉姆达架构,它是用了两套系统,同时保证了结果的延迟和高吞吐。那么拉姆达架构大家就会想到有没有什么问题呢?哎,这个问题其实也非常的明显,简单来讲就是太麻烦了,因为你要实现一个需求,同时要维护两套系统,对于我们这个程序员而言,这种是非常非常难受的一件事,对于很多大数据处理框架而言,对于这个批处理和流处理本身的API是不一样的。就有可能是你做批处理的时候使用了一套API,做流处理的时候呢,要用另外一套API,甚至是用另外一个框架,整个的这个处理方式都不一样,那我们的开发任务不就相当于翻了一倍吗?
14:12
同样的需求,你得付出双倍的工作,而且之后如果有任何的bug,有任何的项目的更新,有任何需求的扩展,我们都要同时去修改两套系统,这个太痛苦了。那所以拉姆达架构,尽管它最后实现的效果还是不错,但是现在呢,基本上有了更好替代方案之后,就渐渐的不再被使用了,尽管如此,有一些公司里边还在使用,因为他最后的结果还是不错的嘛,那有些公司可能之前就已经搭起了拉姆达架构,它这个业务非常的庞大,如果要是做这个更新换代重构的话,代价比较高,那有可能他就只好还是维护之前的这个系统了,所以如果遇到这样的架构的话,也不要怕,它其实就是所谓的。拉姆达架构,我们可以把它叫做第二代流处理架构。
15:04
那真正更好的流处理器是什么样的呢?当然就是用一套系统直接把这个拉姆达架构的两套全部搞定,那什么样的架构能够搞定呢?哎,其实最好的方式就是直接用流处理器来做,因为它快呀,如果在流处理器里边,它又提供了一套可以做攒一批处理的这一套机制,它可以处理批数据,诶,那这不就结了吗?啊,所以很多流处理器是可以很容易的扩展出这样的一整套系统,处理拉姆达架构的两套系统这样的一套方案的。这就是我们所说的新一代流处理器,第三代流处理器,那就是用一套系统把拉姆达架构的两套事情全部搞定。其中的代表就是flink,大家如果看一些文章的话,有些文章可能会把这种架构叫做。阿帕架构啊。
16:01
这个只是一个概念而已,他只要知道link是用一套系统实现了拉姆拉架构的里边的两套功能就可以了。所以flink呢,所有的东西都实现了,那么它有哪些特点呢?它的核心特点就是同时做到了。低延迟和高吞吐,对于link而言,他能够做到每秒钟处理百万个事件,毫秒级别的延迟,那另外就是它还可以保证结果的准确性。这是靠什么保证的呢?这里可以先提一句,就是flink里边呢,它提供了不同的所谓时间语义。直间的语义。也就是说,时间可以有不同的概念。那么对于弗link而言,主要提供的时间语义有制件时间和处理时间两种。哎,那什么叫事件时间,什么叫处理时间呢?后面我们讲到之后会详细展开,那么事件时间就是。
17:02
用来专门保证处理乱序数据的最后结果正确的一套时间语义。那另外呢,弗林格还可以保证精确一次的状态一致性保证,这主要是说什么呢?主要就是说如果发生故障之后,恢复到故障之前的状态,哎,那么是完全一致的,就好像没有发生故障一样。外部看起来,所有的数据都还是处理了一次,而且只处理了一次,这样就叫精确一次。也是一个最后结果正确性的保证,可以把这个看成一个结果正确性和容错性,就故障恢复的时候的容错性结合起来的一种保证。另外就是弗link可以跟众多的常用存储系统进行连接啊,它还支持这个高可用,支持动态扩展,它真正能够以极少的停机时间实现七乘24小时全天候运器啊,所以弗林可是一个非常强大的新一代流处理器。
我来说两句