- 博客(281)
- 收藏
- 关注
原创 深入理解Flink Mailbox线程模型
作为StreamTask的子类,SourceStreamTask会额外启动另一个独立的LegacySourceFunctionThread线程来执行SourceFunction中的循环(生产无界流),Mailbox线程(主线程)依然负责处理Mail和默认操作。负责为Source生产无界流数据的LegacySourceFunctionThread线程启动后,不管是启动成功 or 出现异常,都会封装对应的Mail并发送给Mailbox,而Mailbox线程的processMail一直在等待处理Mail。
2023-08-15 20:38:43
1307
原创 深入理解Flink IntervalJoin源码
接着会经历嵌套for循环,判断哪些StreamRecord是满足Join条件的:以当前StreamRecord的Timestamp和指定的上、下界组成时间过滤条件,对当前StreamRecord的“对方MapState”内的每个Timestamp(作为Key)进行比对。接着将当前StreamRecord写入到对应的MapState中。先取出当前StreamRecord中的Timestamp检查它是否已经迟到了,判断依据为:当前StreamRecord中的Timestamp是否小于当前Watermark。
2023-08-11 11:59:07
1065
原创 深入理解Flink异步I/O原理
当StreamElement被添加到指定的StreamElementQueue队列后,接着就该调用用户自定义处理函数AsyncFunction#asyncInvoke()方法来对队列中的StreamElement执行异步处理逻辑。回顾demo,在自定义处理函数的最后,手动调用了ResultFuture.complete()方法。作为ResultFuture接口的实现子类,ResultHandler提供了对“执行完异步处理逻辑的结果”进行后续处理的具体实现逻辑/**
2023-05-16 17:23:32
1178
原创 RecordWriter核心设计实现
根据创建得到的RecordWriter组件的数量,构建出RecordWriter代理(到底是哪个)RecordSerializer是RecordWriter组件的核心之一,负责将StreamRecord(数据元素,也就是理解意义上的“砖”)序列化成二进制(粒度更细的“沙子”),临时暂存到ByteBuffer(缓冲区,也就是理解意义上的“拖拉机”)上。RecordWriter定义了获取指定InputChannel所对应的BufferBuilder的抽象方法,而它的2个抽象实现子类为其提供了具体的实现逻辑。
2023-04-20 10:19:53
569
原创 JobMaster和ResourceManager建立RPC连接
JobMaster要想跟ResourceManager建立RPC连接,首先得准备好连接所需的RegisteredRpcConnection,它代表了2个RPC节点之间建立的RPC连接。所谓建立RPC连接,就是注册。拿着目标RPC节点的Gateway,将自己注册给它,并拿到注册结果–RegistrationResponse。
2023-04-03 16:27:06
443
原创 构建Transformation树
Transformation表示从一个DataStream生成另一个DataStream的转换操作,就好像一张纸经过一番折叠操作就会成为一个纸飞机,而这个“一番折叠操作”正是Transformation。后面对“虚拟Transformation”进行解析时,会添加虚拟节点,其本质操作就是按照映射关系:“虚拟节点id:Tuple3(Transformation ID,Partitioner,ShuffleMode)”,将其保存到Map结构中。
2023-03-25 16:38:50
213
原创 OperatorChain设计
在递归调用过程中,会捎带着一并创建好OperatorChain内的StreamOperator(HeadOperator除外,它会在最后单独添加),并保存到List集合中。在递归的最底层,会创建(上游算子为单输出类型的)ChainingOutput或CopyingChainingOutput,并会被像RecordWriterOutput一样,和对应的StreamEdge一并包装成Tuple2后,添加到List集合中。在OperatorChain的构造方法中,最核心的就是构建对应类型的Output组件。
2023-03-20 16:19:01
421
原创 完成Checkpoint发送ACK给CheckpointCoordinator
CheckpointCoordinator收到AcknowledgeCheckpoint后,会根据checkpointId,从映射关系为“checkpointId:PendingCheckpoint”的Map集合中取出对应的PendingCheckpoint,并判断是否收到了ACK消息。SchedulerNG收到后,会将ACK消息包装成AcknowledgeCheckpoint,并将其交给传递给CheckpointCoordinator组件处理。于是,ACK消息就名正言顺的到了JobMaster手里。
2023-03-17 15:53:04
625
原创 解析开启Checkpoint流程源码
能够看出,ExecutionGraph开启Checkpoint的本质就是准备好用来控制Source节点触发Checkpoint的CheckpointCoordinator组件,并向JobManager注册一个能够监听到Job状态变化的监听器JobStatusListener。一旦监听到Job运行状态为RUNNING,会触发CheckpointCoordinator组件的启动,就此,奔流不息的Checkpoint就正式揭开帷幕了…
2023-03-17 14:25:36
203
原创 解析创建KeyedState流程源码
由于在(StreamTask反射)beforeInvoke的“状态初始化”阶段已经把StateInitializationContext(保存了可以创建xxxState的xxxStateStore)交给了StreamOperator的自定义RichFunction,并且AbstractStreamOperator也已经通过成员变量的方式“持有”了KeyedStateStore。各种类型的State则为StateFactory#createState()提供了各自的实现逻辑,此时,
2023-03-16 17:05:06
351
原创 状态初始化源码解读
然后将StateInitializationContext传递给AbstractUdfStreamOperator中的CheckpointedFunction,如果有自定义需求,就可以在CheckpointedFunction接口定义的接口方法initializeState()的具体实现中,利用StateInitializationContext取出StateStore,并完成“状态初始化”操作!开发者可以在自定义Function中,使用上下文来灵活的获取各种State。
2023-03-16 14:50:13
383
原创 StreamTask异步执行Checkpoint操作
AsyncCheckpointRunnable负责执行“快照持久化操作”,容纳所有的OperatorSnapshotFutures对象的Map集合都已经被保存到这个Runnable中了。
2023-03-15 15:33:40
359
原创 源码剖析通过Barrier对齐触发Checkpoint流程
*上游Task实例发送的数据元素和事件,会发送到下游Task节点的InputGate中。**当Task实例接收到上游节点发送来的所有的CheckpointBarrier后,当前Task实例就会触发当前节点的Checkpoint操作。CheckpointBarrierAligner就是能够保证Exactly-Once的实现子类,它会对所有InputChannel中的CheckpointBarrier事件严格控制对齐,视情况决定Task实例中的InputChannel的block和打开的时机。
2023-03-14 13:55:08
238
原创 CheckpointCoordinator触发执行Checkpoint流程
TaskExecutor收到Execution发送的“触发执行Checkpoint”请求后,会根据尝试执行Execution的唯一标识,从TaskSlotTable中取出对应的Task实例,让Task执行具体的Checkpoint操作。至此,CheckpointCoordinator就完成了它“触发执行Checkpoint”的使命,并将其交给每个Source节点所对应的Execution来完成具体的执行。最终,由StreamTask提供“触发执行Checkpoint”操作的具体实现。
2023-03-13 20:55:37
645
原创 RDB持久化机制
文章目录RDB文件保存数据库状态1. RDB文件的创建和载入2.间隔执行BGSAVE命令RDB文件保存数据库状态服务器中的非空数据库及其键值对,统称为数据库状态。Redis的RDB持久化,将数据库状态保存到磁盘,避免内存数据掉电易失。RDB持久化既可以手动执行,也可以通过配置定期执行。它会将某个时间点的数据库状态保存到一个RDB文件(压缩的二进制文件)中,以便后期方便借此还原数据库状态。1. RDB文件的创建和载入RDB文件的创建由rdbSave函数负责,SAVE命令和BGSAVE命令会以不同的形
2022-05-19 23:11:00
622
原创 volatile对原子性、可见性、有序性的保证
1.原子性volatile对原子性的保障有限,32位jvm中的long、double类型的变量赋值操作不是原子的,volatile可以保证它俩的原子性。2.可见性、有序性volatile在写操作的前后加上Release屏障、Store屏障;在读操作前后加Load屏障、Acquire屏障。volatile boolean isRunning = true;//线程1Release屏障,保证写和上面的读写不会指令重排isRunning = false;Store屏障,保证写完后会立马执行flu
2021-08-09 09:44:15
575
原创 synchronized同时对原子性、可见性、有序性的保证
原子性:基本复制写操作都能保证原子性,复杂操作无法保证可见性:MESI协议的flush、refresh配合使用,解决可见性有序性:3个层次,最后1个层次有4中内存重排序synchronized可同时保证:原子性:有加锁和释放锁的机制,加锁后,同一段代码只有他能执行可见性:加内存屏障,在同步代码块做变量写操作,在释放锁时,会强制执行flush操作。在获取锁进入同步代码块时,会对变量读强制执行refresh操作。有序性:加各种内存屏障,解决4种内存重排序1.synchronized保证原子性的
2021-08-09 09:43:16
2030
1
原创 ThreadLocal内存泄漏问题
ThreadLocal可以存取各线程专属的变量副本,底层是通过ThreadLocalMap实现,存的K-VK:WeakReference弱引用V:变量副本一旦某线程长期存活,但ThreadLocal里的K是弱引用,万一内存不够,进行GC,就会自动把很多线程寄存在ThreadLocal中的key(弱引用)进行回收。Key —> Value 就成了 null —> Value此时已经没办法获取到Value了,但是Value还在真真实实的占用内存空间。于是就内存泄漏了JDK团队的解决方
2021-08-09 09:41:49
210
原创 内存屏障在硬件层面的实现原理
解决可见性问题Store屏障:强制要求对一个写操作,必须阻塞等待到其他处理器返回invalidate ack后,对数据加独占锁。强制执行flush操作,修改数据到高速缓存或主内存中Load屏障:从高速缓存中读取数据时,如果发现无效队列中有invalidate消息,强制将自己高速缓存的数据状态设为 I过期。然后执行Refresh操作,发送read消息,从其他处理器的高速缓存中刷新最新的值解决有序性问题Acquire屏障、Release屏障 = StoreStore屏障 + StoreLoad屏障…可以
2021-08-09 09:41:13
405
原创 MESI协议为何会引发 有序性、可见性的问题
引发可见性case1:处理器将数据写入到写缓冲器,发送invalidate消息到总线bus,就认为成功了。此时数据并未到高速缓存中。case2:处理器1在嗅探到invalidate之前,就去读取高速缓存的数据。如果有,就从自己高速缓存中取出旧值;如果没有,就发送read消息,去处理器0的高速缓存读。处理器0提供的就是旧值。case3:处理器1收到invalidate消息,放到无效队列。还没来得及将自己的数据状态设为 I过期。此时读,就是旧值原因:写缓冲器+无效队列 导致的。写数据不一定立马写入自己的
2021-08-09 09:40:29
390
原创 写缓冲器 + 无效队列,优化MESI协议的性能
MESI协议,处理器0想写一条数据,需要向总线bus发送invalidate消息,并确认收到invalidate ack消息后,才能动手执行写操作。读阻塞,效率低。处理器将数据写入到写缓冲器,发送invalidate消息出去,就认为成功了、去干别的事了。处理器1嗅探到invalidate消息,将invalidate放到无效队列中,直接返回invalidate ack。过段时间,再从无效队列取出invalidate消息、消费,将自己的状态设为 I过期 。收到所有 处理器return的invalidate
2021-08-09 09:38:32
512
原创 MESI缓存一致性协议
每个处理器,在自己的高速缓存中都有变量副本,这就有了缓存不一致问题,因此有了MESI协议。MESI协议将缓存行状态flag分为4种:invalid:无效的,标记为I,当前cache entry无效,数据不能使用shared:共享的,标记为S,当前cache entry有效,数据在各个处理器中都有副本,且副本值都和主内存一致exclusive:独占的,E,当前处理器对这个数据独占,只有它有数据副本,其他处理器没有modified:修改过的,M,只能有1个处理器对共享数据更新处理器0读取某个变
2021-08-09 09:37:08
655
1
原创 高速缓存的数据结构:拉链散列表
高速缓存的底层数据结构:拉链散列表,很多bucket,挂了很多cache entry(tag + cache line + flag)。cache line就是缓存的数据,包含多个变量的值tag指向了缓存数据在主内存中的地址flag表示了缓存行的状态处理器读取高速缓存时,会根据变量名执行内存地址解码的操作。解析出 index(定位到bucket) + tag(定位到cache entry) + offset(定位到变量在cache line的位置)如果能成功定位到高速缓存中的数据,且flag.
2021-08-09 09:35:34
343
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人