Flink/Blink 原理漫谈(一)时间,watermark详解

本文深入探讨Flink/Blink中的时间概念,包括Event Time、Ingestion Time和Processing Time。重点讲解Watermark机制,用于处理数据乱序问题,保证Event Time的一致性。通过实例解释Watermark如何触发窗口关闭,以及在多流处理中的单调递增策略。

系列文章目录

Flink/Blink 原理漫谈(零)运行时的组件

Flink/Blink 原理漫谈(一)时间,watermark详解

Flink/Blink 原理漫谈(二)流表对偶性和distinct详解

Flink/Blink 原理漫谈(三)state 有状态计算机制 详解

Flink/Blink 原理漫谈(四)window机制详解

Flink/Blink 原理漫谈(五)流式计算的持续查询实现 详解

Flink/Blink 原理漫谈(六)容错机制(fault tolerance)详解



一、 时间

一共有三种时间:event time,ingestion time,processing time

Event time:事件发生的时间
Ingestion time:数据进入flink的时间
Processing time:执行操作算子的本地系统时间
在这里插入图片描述
Watermark就是基于Event Time产生的,Blink系统正是利用Event Time和Watermark机制处理数据乱序问题的。Processing Time并不能提供确定性,因为它容易受到Event到达系统的速度(例如来自消息队列)以及记录在Blink系统内部的处理先后顺序的影响。Ingestion Time在概念上位于Event Time和Processing Time之间。

目前Blink SQL 层面向用户开发的时间类型是 Event Time和Processing Time.

二、 watermark

概念

通常来说,数据都是按照event time进入operator中的,但是由于分布式,网络延迟等等原因,先发生的事情反而会在后面传入。
在这里插入图片描述
这就出问题了啊,如果我们只是根据event time来决定是否关闭当前窗口,就可能永远也无法知道什么时候应该关闭当前窗口,因为我们总是无法明确什么时候,当前窗口的所有数据都到位了。这时候就要引入watermarks的概念。

很多网上的文章描述的wa

<think>我们正在讨论NuttX中TCB的flinkblink指针如何用于实现优先级继承机制。优先级继承是种解决优先级反转问题的技术,当高优先级任务因低优先级任务持有共享资源而阻塞时,临时提升低优先级任务的优先级至与高优先级任务相同,使其尽快执行并释放资源。 在NuttX中,优先级继承机制(Priority Inheritance)主要通过互斥锁(mutex)实现。当任务尝试获取已被持有的互斥锁时,如果持有者优先级低于当前任务,系统会提升持有者优先级以避免优先级反转。而flinkblink指针作为双向链表的连接件,在就绪任务队列中用于快速调整任务的位置(因为就绪队列是按优先级排序的)。 具体实现步骤: 1. **检测优先级反转**:当高优先级任务(H)尝试获取低优先级任务(L)持有的互斥锁时,内核发现L的优先级低于H。 2. **提升持有者优先级**:系统临时将L的优先级提升到与H相同(或略低,具体取决于策略)。 3. **调整就绪队列**:由于L的优先级提升,需要将其在就绪队列中的位置前移(因为就绪队列是按优先级从高到低排序的双向链表)。这里就用到`flink``blink`指针: - 将L从当前链表中移除(通过修改相邻节点的`flink``blink`指针) - 根据新优先级将L插入到就绪队列的合适位置(同样通过调整链表指针) 4. **任务调度**:调度器下次调度时,由于L的优先级已提升,会优先执行L,使其尽快释放互斥锁。 5. **恢复原优先级**:当L释放互斥锁后,系统将其优先级恢复为原值,并调整其在就绪队列中的位置。 关键代码逻辑(以互斥锁获取为例): ```c // 当任务H尝试获取已被L持有的互斥锁时 if (H->priority > L->priority) { // 提升L的优先级至H的优先级 nxsched_set_priority(L, H->priority); // 调整L在就绪队列中的位置(使用flink/blink指针) sched_remove_readytorun(L); // 从原位置移除 sched_add_readytorun(L); // 按新优先级插入 } ``` 在调整链表位置时,`sched_remove_readytorun``sched_add_readytorun`函数内部会操作`flink``blink`指针,实现$O(1)$复杂度的链表节点删除插入。例如: ```c void sched_remove_readytorun(FAR struct tcb_s *tcb) { // 获取前驱后继 FAR struct tcb_s *prev = tcb->blink; FAR struct tcb_s *next = tcb->flink; // 更新前驱的后继指针 if (prev != NULL) { prev->flink = next; } // 更新后继的前驱指针 if (next != NULL) { next->blink = prev; } } ``` **总结**:`flink``blink`指针在优先级继承中的作用是**动态调整任务在就绪队列中的位置**,确保因优先级提升而需要提前执行的任务能被快速调度。这种机制有效缓解了优先级反转问题,提高了系统的实时性。</think>### NuttX中如何利用`flink/blink`实现优先级继承机制 在NuttX中,`flink``blink`指针通过**动态调整任务在就绪队列中的位置**来实现优先级继承机制。该机制主要用于解决优先级反转问题,具体实现过程如下: #### 1. **优先级继承触发条件** 当高优先级任务($T_{high}$)因等待低优先级任务($T_{low}$)持有的资源(如互斥锁)而阻塞时,系统触发优先级继承: ```c /* 互斥锁获取函数片段 */ if (mutex->holder && mutex->holder->sched_priority < current->sched_priority) { nxsched_priority_inherit(mutex->holder, current->sched_priority); // 触发继承[^1] } ``` #### 2. **优先级提升的核心操作** 通过`flink/blink`动态调整任务在就绪队列中的位置: ```mermaid graph LR A[检测优先级反转] --> B{提升持有者优先级} B --> C[从就绪队列移除T_low] C --> D[按新优先级插入队列] D --> E[更新调度指针] ``` 具体实现步骤: 1. **移除原优先级位置** 通过`flink/blink`将$T_{low}$从当前队列位置移除: ```c void sched_remove_readytorun(FAR struct tcb_s *tcb) { // 更新前驱节点的flink if (tcb->blink) tcb->blink->flink = tcb->flink; // 更新后继节点的blink if (tcb->flink) tcb->flink->blink = tcb->blink; } ``` 2. **插入新优先级位置** 使用优先级排序算法重新插入: ```c void sched_add_readytorun(FAR struct tcb_s *tcb) { // 遍历就绪队列(g_readytorun) FAR struct tcb_s *prev = NULL; FAR struct tcb_s *next = g_readytorun.head; // 按优先级查找插入点 while (next && next->sched_priority > tcb->sched_priority) { prev = next; next = next->flink; // 通过flink遍历 } // 更新flink/blink指针 tcb->flink = next; tcb->blink = prev; if (next) next->blink = tcb; if (prev) prev->flink = tcb; } ``` #### 3. **调度器行为变化** 优先级提升后: 1. 就绪队列头部`g_readytorun.head`指向$T_{low}$(因其临时拥有最高优先级) 2. 调度器通过`flink`遍历时优先执行$T_{low}$: ```c FAR struct tcb_s *next = g_readytorun.head; // 获取最高优先级任务 while (next->flink && !ready_to_run(next)) { // 通过flink遍历 next = next->flink; } up_switchcontext(current, next); // 切换到继承优先级的任务 ``` #### 4. **优先级恢复机制** 当$T_{low}$释放资源后: 1. 通过`flink/blink`将其移出当前队列位置 2. 按原始优先级重新插入队列 3. 恢复$T_{high}$到就绪队列头部 #### 设计优势 1. **$O(1)$时间复杂度**:指针操作确保优先级调整高效完成 2. **无锁设计**:单核环境下通过开关中断保证原子性 3. **动态响应**:实时调整`g_readytorun.head`指向当前最高优先级任务 4. **资源优化**:复用TCB现有指针,无需额外存储 > 示例:当I²C驱动(HPWORK)持有资源时,其优先级可临时提升至与等待任务相同,确保实时性要求[^1]。 #### 总结 NuttX通过`flink/blink`实现: 1. **动态队列重组**:快速调整任务在双向链表中的位置 2. **优先级提升**:使资源持有者获得请求者的优先级 3. **实时调度**:确保高优先级任务最小化等待时间 4. **自动恢复**:资源释放后优先级自动回退 这种机制有效解决了嵌入式系统中的优先级反转问题,同时保持调度器的高效性(平均$O(1)$操作复杂度)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值