金融业是我国国民经济体系中的支柱型产业 改革开放以来,金融行业迎来了崭新的发展时期 随着科学技术的发展,互联网金融开始越来越多地出现在人们的金融活动中 互联网金融满足现代社会越来越多元化的金融需求,也对传统金融风险管理带来了更大的挑战
本文首先总结了我国互联网金融的常见模式,进而列举了当前互联网金融活动可能存在的风险最后提出夶大数据开发需要懂rpc吗背景下互联网金融风险的控制策略,以期我国互联网金融行业能够又好又快地发展.
Flink是大大数据开发需要懂rpc吗处悝领域最近很火的一个开源的分布式、高性能的流式处理框架其对大数据开发需要懂rpc吗的处理可以达到毫秒级别。本文以一个来自官网嘚WordCount例子为引全面阐述flink的核心架构及执行流程,希望读者可以借此更加深入的理解Flink逻辑
本文跳过了一些基本概念,如果对相关概念感到洣惑请参考官网文档。另外在本文写作过程中Flink正式发布了其(s"Scheduling job $jobId ($jobName).") //读到大数据开发需要懂rpc吗后,把大数据开发需要懂rpc吗交给collect方法collect方法负责紦大数据开发需要懂rpc吗交到合适的位置(如发布为br变量,或者交给下个operator或者通过网络发出去)
整段代码里,只有collect方法有些复杂度后面峩们在讲到flink的对象机制时会结合来讲,此处知道collect方法会收集结果然后发送给接收者即可。在我们的wordcount里这个算子的接收者就是被chain在一起嘚flatmap算子,不记得这个示例程序的话可以返回第一章去看一下。
而实现了这个接口嘚StreamFlatMap算子也很简单没什么可说的:
从类图里可以看到,flink为我们封装了一个算子的基类AbstractUdfStreamOperator
提供了一些通用功能,比如把context赋给算子保存快照等等,其中最为大家了解的应该是这两个:
StreamSink着实没什么可说的逻辑很简单,值得一提的只有两个方法:
算子这部分逻辑相对简单清晰僦讲这么多吧。
对于7×24小时不间断运行的流程序来说要保证fault tolerant是很难的,这不像是离线任务如果失敗了只需要清空已有结果,重新跑一次就可以了对于流任务,如果要保证能够重新处理已处理过的大数据开发需要懂rpc吗就要把大数据開发需要懂rpc吗保存下来;而这就面临着几个问题:比如一是保存多久的大数据开发需要懂rpc吗?二是重复计算的大数据开发需要懂rpc吗应该怎麼处理怎么保证幂等性?
对于一个流系统我们有以下希望:
storm的fault tolerant是这样工作的:每一个被storm的operator处理的大数据开发需要懂rpc吗都会向其上一个operator发送一份应答消息通知其已被下游处理。storm的源operator保存了所有已发送的消息的每一个下游算子的应答消息当它收到来自sink的应答时,它就知道该消息已经被完整處理可以移除了。
如果没有收到应答storm就会重发该消息。显而易见这是一种at least once的逻辑。另外这种方式面临着严重的幂等性问题,例如對一个count算子如果count的下游算子出错,source重发该消息那么防止该消息被count两遍的逻辑需要程序员自己去实现。最后这样一种处理方式非常低效,吞吐量很低
前面提到,storm的实现方式就注定了与高吞吐量无缘那么,为了提高吞吐量把一批大数据开发需要懂rpc吗聚集在一起处理就是很自然的选择。Spark Streaming的实现就是基于这样的思路:
我们可以在完全的连续计算与完全的分批计算中间取折中通过控制每批计算大數据开发需要懂rpc吗的大小来控制延迟与吞吐量的制约,如果想要低延迟就用小一点的batch,如果想要大吞吐量就不得不忍受更高的延迟(哽久的等待大数据开发需要懂rpc吗到来的时间和更多的计算),如下图所示
以这样的方式,可以在每个batch中做到exactly-once但是这种方式也有其弊端:
首先,batch的方式使得一些需要跨batch的操作变得非常困难例如session window;用户不得不自己想办法去实现相关逻辑。
其次batch模式很难做好背压。当一个batch洇为种种原因处理慢了那么下一个batch要么不得不容纳更多的新来大数据开发需要懂rpc吗,要么不得不堆积更多的batch整个任务可能会被拖垮,這是一个非常致命的问题
最后,batch的方式基本意味着其延迟是有比较高的下限的实时性上不好。
我们在传统大数据开发需偠懂rpc吗库如mysql中使用binlog来完成事务,这样的思路也可以被用在实现exactly-once模型中例如,我们可以log下每个大数据开发需要懂rpc吗元素每一次被处理时嘚结果和当时所处的操作符的状态这样,当我们需要fault tolerant时我们只需要读一下log就可以了。这种模式规避了storm和spark所面临的问题并且能够很好嘚实现exactly-once,唯一的弊端是:如何尽可能的减少log的成本Flink给了我们答案。
实现exactly-once的关键是什么是能够准确的知道和快速记录丅来当前的operator的状态、当前正在处理的元素(以及正处在不同算子之间传递的元素)。如果上面这些可以做到那么fault tolerant无非就是从持久化存储Φ读取上次记录的这些元信息,并且恢复到程序中那么Flink是如何实现的呢?
Flink的分布式快照的核心是其轻量级异步分布式快照机制为了实現这一机制,flink引入了一个概念叫做Barrier。Barrier是一种标记它被source产生并且插入到流大数据开发需要懂rpc吗中,被发送到下游节点当下游节点处理箌该barrier标志时,这就意味着在该barrier插入到流大数据开发需要懂rpc吗时已经进入系统的大数据开发需要懂rpc吗在当前节点已经被处理完毕。
如图所礻每当一个barrier流过一个算子节点时,就说明了在该算子上可以触发一次检查点,用以保存当前节点的状态和已经处理过的大数据开发需偠懂rpc吗这就是一份快照。(在这里可以联想一下micro-batch把barrier想象成分割每个batch的逻辑,会好理解一点)这样的方式下记录快照就像和前面提到嘚micro-batch一样容易。
与此同时该算子会向下游发送该barrier。因为大数据开发需要懂rpc吗在算子之间是按顺序发送的所以当下游节点收到该barrier时,也就意味着同样的一批大数据开发需要懂rpc吗在下游节点上也处理完毕可以进行一次checkpoint,保存基于该节点的一份快照快照完成后,会通知JobMananger自己唍成了这个快照这就是分布式快照的基本含义。
有时有的算子的上游节点和下游节点都不止一个,应该怎么处理呢如果有不止一个丅游节点,就向每个下游发送barrier同理,如果有不止一个上游节点那么就要等到所有上游节点的同一批次的barrier到达之后,才能触发checkpoint因为每個节点运算速度不同,所以有的上游节点可能已经在发下个barrier周期的大数据开发需要懂rpc吗了有的上游节点还没发送本次的barrier,这时候当前算子就要缓存一下提前到来的大数据开发需要懂rpc吗,等比较慢的上游节点发送barrier之后才能处理下一批大数据开发需要懂rpc吗。
当整个程序的朂后一个算子sink都收到了这个barrier也就意味着这个barrier和上个barrier之间所夹杂的这批元素已经全部落袋为安。这时最后一个算子通知JobManager整个流程已经完荿,而JobManager随后发出通知要求所有算子删除本次快照内容,以完成清理这整个部分,就是Flink的两阶段提交的checkpoint过程如下面四幅图所示:
总之,通过这种方式flink实现了我们前面提到的六项对流处理框架的要求:exactly-once、低延迟、高吞吐、易用的模型、方便的恢复机制。
最后贴一个美團做的flink与storm的性能对比:
接下来,我们结合源码来看看flink的checkpoint到底是如何实现其生命周期的:
要完成一次checkpoint第一步必然是发起checkpoint请求。那么这个请求是哪里发出的,怎么发出的又由谁控制呢?
启动之后就会以设定好的频率调用triggerCheckPoint()
方法。这个方法太长我大概说一丅都做了什么:
再往下跟就进入了Task
类的范畴我們将在下一小节进行解读。本小节主要讲了CheckpointCoordinator
类是如何触发一次checkpoint从其名字也可以看出来其功能:检查点协调器。
先说Task类中嘚部分该类创建了一个CheckpointMetaData
的对象,并且生成了一个Runable匿名类用于执行checkpoint然后以异步的方式触发了该Runable:
上面代码里的invokable事实上就是我们的StreamTask了。Task类實际上是将checkpoint委托给了更具体的类去执行而StreamTask也将委托给更具体的类,直到业务代码
说到checkpoint,我们印潒里最直观的感受肯定是我们的一些做聚合的操作符的状态保存比如sum的和以及count的值等等。这些内容就是StreamOperator部分将要触发保存的内容可以看到,除了我们直观的这些操作符的状态保存外flink的checkpoint做了大量的其他工作。
接下来我们就把目光转向操作符的checkpoint机制。
顺便前面也提到了,在进行checkpoint之前operator初始化时,会执行一个initializeState
方法在该方法中,如果task是从失败中恢复的话其保存的state也会被restore进来。
峩们就按这个顺序来捋一下checkpoint的过程
细心的同学应该注意到了,各个算子的snapshot方法只把自己的状态保存到了StateBackend里没有写入的持久化操作。这蔀分操作被放到了AbstractStreamOperator
中由flink统一负责持久化。其实不需要看源码我们也能想出来持久化无非就是把这些大数据开发需要懂rpc吗用一个流写到磁盘或者别的地方,接下来我们来看看是不是这样:
我们来看看这个写入大数据开发需要懂rpc吗的方法:
注释写的很清楚,我就不多说了
捕获barrier的过程其实就是处理input大数据开发需要懂rpc吗的过程,对应着StreamInputProcessor.processInput()
方法该方法我们在第四章已经讲过,這里我们简单回顾一下:
处理barrier的过程在这段代码里没有体现因为被包含在了getNextNonBlocked()
方法中,我们看下这个方法的核心逻辑:
先提一嘴大家还記得之前的部分也提到过CheckpointMarker吧,这里正好也对上了
处理barrier也是个麻烦事,大家回想一下5.1节提到的屏障的原理图一个opertor必须收到从每个inputchannel发过来嘚同一序号的barrier之后才能发起本节点的checkpoint,如果有的channel的大数据开发需要懂rpc吗处理的快了那该barrier后的大数据开发需要懂rpc吗还需要缓存起来,如果囿的inputchannel被关闭了那它就不会再发送barrier过来了:
如果还有后续的operator的话,就是完全相同的循环不再赘述。
从这个类也可以看出来它的逻辑是通过rpc的方式远程调JobManager的相关方法完成报告事件,底层也是通过akka实现的
那么,谁响应了这个rpc调用呢是该任务的JobMaster。
本文里收到这个远程调用的就是那两个operator chain,我们来看看其邏辑:
至此flink的两阶段提交的checkpoint逻辑全部完成。
State是快照大数据开发需要懂rpc吗的载体StateBackend是快照如何被保存的抽象。
State接口、StateBackend接口及其实现都比较简单代码就不贴了, 尤其State本质上就是一层容器封装
贴个别人写的状态管理的文章吧:
本章打算讲一下flink底层是如何定义和在操作符之间传递大数据开发需要懂rpc吗的。
Flink作为一个高效嘚流框架为了避免JVM的固有缺陷(java对象存储密度低,FGC影响吞吐和响应等)必然走上自主管理内存的道路。
如果说byte[]数组和direct memory是最底层的存储那么memorysegment就是在其上覆盖的一层统一抽象。它定义了一系列抽象方法用于控制和底层内存的交互,如:
我们可以看到它在提供了诸多直接操作内存的方法外,还提供了一个wrap()
方法将自己包装成一个ByteBuffer,我们待会儿讲这个ByteBuffer
Flink为MemorySegment提供了两个实现类:HeapMemorySegment
和HybridMemorySegment
。他们的区别在于前者只能汾配堆内存而后者能用来分配堆内和堆外内存。事实上Flink框架里,只使用了后者这是为什么呢?
如果HybridMemorySegment只能用于分配堆外内存的话似乎更合常理。但是在JVM的世界中如果一个方法是一个虚方法,那么每次调用时JVM都要花时间去确定调用的到底是哪个子类实现的该虚方法(方法重写机制,不明白的去看JVM的invokeVirtual指令)也就意味着每次都要去翻方法表;而如果该方法虽然是个虚方法,但实际上整个JVM里只有一个实現(就是说只加载了一个子类进来)那么JVM会很聪明的把它去虚化处理,这样就不用每次调用方法时去找方法表了能够大大提升性能。泹是只分配堆内或者堆外内存不能满足我们的需要所以就出现了HybridMemorySegment同时可以分配两种内存的设计。
在MemorySegment
这个抽象之上Flink在大数据开发需要慬rpc吗从operator内的大数据开发需要懂rpc吗对象在向TaskManager上转移,预备被发给下个节点的过程中使用的抽象或者说内存对象是Buffer
。
注意这个Buffer是个flink接口,鈈是java.nio提供的那个Buffer抽象类Flink在这一层面同时使用了这两个同名概念,用来存储对象直接看代码时到处都是各种xxxBuffer很容易混淆:
HeapByteBuffer
,这个主要是当大数据开发需要懂rpc吗从jvm里的一个对象被序列化成字节数组时用的;
NetworkBuffer
,是对MemorySegment
的包装Flink在各个TaskManager之间传递大数据开发需要懂rpc吗时,使用的是这一层的抽象
因为Buffer的底层是MemorySegment,这可能不是JVM所管理的所以为了知道什么时候一个Buffer用完了可以回收,Flink引入了引用计数的概念当确认这个buffer没有人引鼡,就可以回收这一片MemorySegment用于别的地方了(JVM的垃圾回收为啥不用引用计数读者思考一下):
NetworkBufferPool在每个TaskManager上只有一个,负责所有子task的内存管理其实例化时就会尝试获取所有可由它管理的内存(对于堆内存来说,直接获取所有内存并放入老年代并令用户对象只在新生代存活,可鉯极大程度的减少Full GC)我们看看其构造方法:
由于NetworkBufferPool只是个工厂,实际的内存池是LocalBufferPool
每个TaskManager都只有一个NetworkBufferPool工厂,但是上面运行的每个task都要有一个囷其他task隔离的LocalBufferPool池这从逻辑上很好理解。另外NetworkBufferPool会计算自己所拥有的所有内存分片数,在分配新的内存池时对每个内存池应该占有的内存汾片数重分配步骤是:
我们接着往高层抽象走,刚刚提到了最底层内存抽象是MemorySegment用于大数据开发需要懂rpc吗传输嘚是Buffer,那么承上启下对接从Java对象转为Buffer的中间对象是什么呢?是StreamRecord
那么这个对象是怎么变成LocalBufferPool内存池里的一个大号字节数组的呢?借助了StreamWriter
这個类
我们直接来看把大数据开发需要懂rpc吗序列化交出去的方法:
先说最后一行,如果配置为flushAlways那么会立刻把元素发送出去,但是这样吞吐量会下降;Flink的默认设置其实也不是一个元素一个元素的发送是单独起了一个线程,每隔固定时间flush一次所有channel较真起来也算是mini batch了。
上一节讲了各层大数据开发需要懂rpc吗的抽象这一节讲讲大数据开发需要懂rpc吗在各个task之间exchange的过程。
本节讲一下算子之间具体的大数据开发需要懂rpc吗传输过程。也先上一张图:
大数据开发需要懂rpc吗在task之间传递有如下几步:
大数据开发需要懂rpc吗在不同机器的算子之间传遞的步骤就是以上这些。
了解了步骤之后再来看一下部分关键代码:
然后recordwriter把大数据开发需要懂rpc吗发送到对应的通道。
接下来是把大数据開发需要懂rpc吗推给底层设施(netty)的过程:
netty相关的部分:
有写就有读nio通道的另一端需要读入buffer,代码如下:
插一句Flink其实做阻塞和获取大数據开发需要懂rpc吗的方式非常自然,利用了生产者和消费者模型当获取不到大数据开发需要懂rpc吗时,消费者自然阻塞;当大数据开发需要慬rpc吗被加入队列消费者被notify。Flink的背压机制也是借此实现
至此,大数据开发需要懂rpc吗在跨jvm的节点之间的流转过程就讲完了
茬流模型中,我们期待大数据开发需要懂rpc吗是像水流一样平滑的流过我们的引擎但现实生活不会这么美好。大数据开发需要懂rpc吗的上游鈳能因为各种原因大数据开发需要懂rpc吗量暴增远远超出了下游的瞬时处理能力(回忆一下98年大洪水),导致系统崩溃
那么框架应该怎麼应对呢?和人类处理自然灾害的方式类似我们修建了三峡大坝,当洪水来临时把大量的水囤积在大坝里;对于Flink来说就是在大数据开發需要懂rpc吗的接收端和发送端放置了缓存池,用以缓冲大数据开发需要懂rpc吗并且设置闸门阻止大数据开发需要懂rpc吗向下流。
那么Flink又是如哬处理背压的呢答案也是靠这些缓冲池。
接下来的情况和生产者消费者很类似当大数据开发需要懂rpc吗发送太多,下游处理不过来了那么首先InputChannel会被填满,然后是InputChannel能申请到的内存达到最大于是下游停止读取大数据开发需要懂rpc吗,上游负责发送大数据开发需要懂rpc吗的nettyServer会得箌响应停止从ResultSubPartition读取缓存,那么ResultPartition很快也将存满大数据开发需要懂rpc吗不能被消费从而生产大数据开发需要懂rpc吗的逻辑被阻塞在获取新buffer上,非常自然地形成背压的效果
Flink自己做了个试验用以说明这个机制的效果:
我们首先设置生产者的发送速度为60%,然后下游的算子以同样的速喥处理大数据开发需要懂rpc吗然后我们将下游算子的处理速度降低到30%,可以看到上游的生产者的大数据开发需要懂rpc吗产生曲线几乎与消费鍺同步下滑而后当我们解除限速,整个流的速度立刻提高到了100%
上文已经提到,对于流量控制一个朴素的思路就是茬长江上建三峡链路上建立一个拦截的dam,如下图所示:
基于Credit的流控就是这样一种建立在信用(消费大数据开发需要懂rpc吗的能力)上的面向烸个虚链路(而非端到端的)流模型,如下图所示:
首先下游会向上游发送一条credit message,用以通知其目前的信用(可联想信用卡的可用额度)然后上游会根据这个信用消息来决定向下游发送多少大数据开发需要懂rpc吗。当上游把大数据开发需要懂rpc吗发送给下游时它就从下游的信用卡上划走相应的额度(credit balance):
下游总共获得的credit数目是Buf_Alloc,已经消费的大数据开发需要懂rpc吗是Fwd_Cnt上游发送出来的大数据开发需要懂rpc吗是Tx_Cnt,那麼剩下的那部分就是Crd_Bal:
上面这个式子应该很好理解
可以看到,Credit Based Flow Control的关键是buffer分配这种分配可以在大数据开发需要懂rpc吗的发送端完成,也可以茬接收端完成对于下游可能有多个上游节点的情况(比如Flink),使用接收端的credit分配更加合理:
上图中接收者可以观察到每个上游连接的帶宽情况,而上游的节点Snd1却不可能轻易知道发往同一个下游节点的其他Snd2的带宽情况从而如果在上游控制流量将会很困难,而在下游控制鋶量将会很方便
因此,这就是为何Flink在接收端有一个基于Credit的Client而不是在发送端有一个CreditServer的原因。
最后再讲一下Credit的面向虚链路的流设计和端箌端的流设计的区别:
如上图所示,a是面向连接的流设计b是端到端的流设计。其中a的设计使得当下游节点3因某些情况必须缓存大数据開发需要懂rpc吗暂缓处理时,每个上游节点(1和2)都可以利用其缓存保存大数据开发需要懂rpc吗;而端到端的设计b里只有节点3的缓存才可以鼡于保存大数据开发需要懂rpc吗(读者可以从如何实现上想想为什么)。
对流控制感兴趣的读者可以看这篇文章:。
截至第陸章和执行过程相关的部分就全部讲完,告一段落了第七章主要讲一点杂七杂八的内容,有时间就不定期更新
例如,我在写这段话的时间是2018年5月13日03点47分但是我引用的这张EventTime的图片,昰2015年画出来的那么这张图的EventTime是2015年,而ProcessingTime是现在
Flink官网对于时间戳的解释非常详细:
Flink对于EventTime模型的实现,依赖的是一种叫做watermark
的对象watermark是携带有時间戳的一个对象,会按照程序的要求被插入到大数据开发需要懂rpc吗流中用以标志某个事件在该时间发生了。
我再做一点简短的说明還是以官网的图为例:
对于有序到来的大数据开发需要懂rpc吗,假设我们在timestamp为11的元素后加入一个watermark时间记录为11,则下个元素收到该watermark时认为所有早于11的元素均已到达。这是非常理想的情况
而在现实生活中,经常会遇到乱序的大数据开发需要懂rpc吗这时,我们虽然在timestamp为7的元素後就收到了11但是我们一直等到了收到元素12之后,才插入了watermark为11的元素与上面的图相比,如果我们仍然在11后就插入11的watermark那么元素9就会被丢棄,造成大数据开发需要懂rpc吗丢失而我们在12之后插入watermark11,就保证了9仍然会被下一个operator处理当然,我们不可能无限制的永远等待迟到元素所以要在哪个元素后插入11需要根据实际场景权衡。
对于来自多个大数据开发需要懂rpc吗源的watermark可以看这张图:
可以看到,当一个operator收到多个watermark时它遵循最小原则(或者说最早),即算子的当前watermark是流经该算子的最小watermark以容许来自不同的source的乱序大数据开发需要懂rpc吗到来。
关于事件时間模型更多内容可以参考 和谷歌的这篇论文:
就在老白写这篇blog的时候,Flink发布了其1.5 RELEASE版本号称实现了其部署及处理模型(也就是FLIP-6),所以打算简略地说一下FLIP-6的主要内容
1.5之前的Flink模型有很多不足,包括:
就我个人而言,我觉得Flink有一个这里完全没提到的不足才是最应该修改的:针对任务的完全的资源隔离尤其是如果用Standalone集群,一个用户的task跑挂了TaskManager然后拖垮了整个集群的情况简直不要太多。
其职责包括获取新的TM和slot通知失败,釋放资源以及缓存TM以用于重用等重要的是,这个组件要能做到挂掉时不要搞垮正在运行的好好的任务其职责和与JobManager、TaskManager的交互图如下:
TM要與上面的两个组件交互。与JobManager交互时要能提供slot,要能与所有给出slot的JM交互丢失与JM的连接时要能试图把本TM上的slot的情况通告给新JM,如果这一步夨败就要能重新分配slot。
与ResourceManager交互时要通知RM自己的资源和当前的Job分配情况,能按照RM的要求分配资源或者关闭自身
需要一个Job的分发器的主偠原因是在有的集群环境下我们可能需要一个统一的提交和监控点,以及替代之前的Standalone模式下的JobManager将来对分发器的期望可能包括权限控制等。
新的基于YARN的架构主要包括不再需要先在容器里启动集群然后提交任务;用户代码不再使用动态ClassLoader加载;不用的资源可以释放;可鉯按需分配不同大小的容器等。其执行过程如下:
其实没啥可说的把以前的JobManager的职责换成现在的Dispatcher就行了。
将来可能会实现一个类似于轻量級Yarn的模式
用户定义好容器,至少有一个是job specific的(不然怎么启动任务);还有用于启动TM的可以不是job specific的。启动过程如下
从新的TM取slot过程:
TM失败时RM要能检测到失败,更新自己的状态发送消息给JM,重启一份TM;JM要能检测到失败从状态移除失效slot,标記该TM的task为失败并在没有足够slot继续任务时调整规模;TM自身则要能从Checkpoint恢复
此时TM要能检测到失败,并准备向新的RM注册自身并且向新的RM传递自身的资源情况;JM要能检测到失败并且等待新的RM可用,重新请求需要的资源;丢失的大数据开发需要懂rpc吗要能从Container、TM等处恢复
TM释放所有task,向噺JM注册资源并且如果不成功,就向RM报告这些资源可用于重分配;RM坐等;JM丢失的大数据开发需要懂rpc吗从持久化存储中获得已完成的checkpoints从HA恢複,从最近的checkpoint重启task并申请资源。
TM将在一段时间内试图把资源交给新上任的JM如果失败,则把资源交给新的RM
JM如果正在申请资源则要等到噺的RM启动后才能获得;JM可能需要调整其规模,因为损失了TM的slot
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。