https://www.xiaolincoding.com/redis/base/redis_interview.html#redis-%E4%BD%BF%E7%94%A8%E7%9A%84%E8%BF%87%E6%9C%9F%E5%88%A0%E9%99%A4%E7%AD%96%E7%95%A5%E6%98%AF%E4%BB%80%E4%B9%88

Agent限流

使用ZSET实现,member为标识,score为时间戳。

用户级别限流

每个用户任意连续 10 秒最多请求 3 次。使用ZSET保存用户的请求记录。可以把 ZSET 想象成一条自动按时间排列的请求时间轴:

1s          4s                    9s
A-----------B---------------------C

用于判断允许还是拒绝。

调用前

  1. 清理超时成员
  2. 检查当前数量
  3. 未超过上限则 ZADD

调用后

ZREM 调用 ID

任务去重、消息重复消费问题

通过 SETNX 判断是否已经执行,SET NXSET 命令配合 NX(Not eXists)参数的一种用法。它的核心作用是:只有当指定的键(Key, 这里指的是唯一任务id)不存在时,才执行设置操作;如果键已经存在,则不执行任何操作*。

异步 Agent 通过 MQ 返回结果时,使用Redis防止消息重复消费,保证幂等姓。

熔断器

  • {agentId}:window
    • 作用:滑动窗口计数器。
    • 理解:用来记录最近一段时间内(比如最近10秒)该 Agent 的成功和失败调用次数。Redis 的 List 或 ZSet 结构非常适合做这种时间窗口统计。当失败次数超过阈值(比如50%的请求都失败了),就会触发状态变更。
  • {agentId}:openuntil
    • 作用:熔断截止时间戳。
    • 理解:这是一个“禁令”标记。一旦进入 OPEN 状态,系统会写入一个未来的时间戳。在这个时间点之前,所有请求直接拒绝,不再调用下游 Agent。
  • {agentId}:halfopen_probe
    • 作用:半开状态的探针锁。
    • 理解:这是为了解决“集群惊群效应”。当熔断时间结束进入 HALF_OPEN 状态时,如果集群有100个节点,不能让100个节点同时去试探下游是否恢复。利用 Redis 的原子性(如 SETNX),只允许抢到锁的那 1 个节点去发探测请求。

熔断器生命周期

  • CLOSED (闭合/正常态)
    • 含义:一切正常,请求正常转发给 Agent。
    • 触发条件:在 window 窗口期内,统计到的失败率超过了设定的阈值。
    • 动作:系统判定 Agent 不可用,状态切换为 OPEN。
  • OPEN (开启/熔断态)
    • 含义:Agent 已“挂掉”,停止发送请求,直接返回错误或默认值(快速失败)。
    • 触发条件:预设的熔断冷却时间(openuntil=30)结束。
    • 动作:状态切换为 HALF_OPEN,准备尝试恢复。
  • HALF_OPEN (半开/探测态)
    • 含义:小心翼翼地尝试恢复。
    • 触发条件:放行的探测请求调用成功。
    • 动作:确认 Agent 已恢复,状态切回 CLOSED;如果探测失败,则重新回到 OPEN 状态并延长冷却时间。

分布式锁

为什么需要分布式锁

假设 Octopus 部署三个节点:

节点 A:原来执行任务 T1,后来宕机 
节点 B:SchedulerX 扫描到 T1 
节点 C:Callback 到达,也发现 T1 需要恢复

此时 B 和 C 都可能尝试恢复同一个任务。

没有锁时可能发生:

B 恢复 T1 → 调用 Agent C 恢复 T1 → 再次调用 Agent

后果包括:

  • 外部 Agent 被调用两次;
  • 最终消息重复推送;
  • Checkpoint 相互覆盖;
  • TaskCenter 重复上报;
  • 产生重复业务副作用。

获取锁的方法

SET lockKey ownerToken NX PX 60000

  • NX:Key 不存在时才写入;
  • PX:设置毫秒级过期时间;
  • ownerToken:当前持有者的唯一身份。

callback bridge

外部 Agent 的结果是异步返回的,而且可能回调到任意 Octopus 节点,如何把结果交给原来的执行流程,不能使用内存,因此需要借助Redis。

Callback Bridge 的核心需求是低延迟、按 correlationId 动态唤醒;消息已经存入 Redis,Pub/Sub 只做可丢失的通知。若改用 MQ,仍需共享存储和节点路由,复杂度更高、收益有限。

callback bridge传递三类消息:

中间事件

对于中间结果,它需要

  • 多条事件排队;
  • 保持到达顺序;
  • 被等待线程逐条消费;
  • 新事件到达时立即唤醒线程;
  • 消费后及时清理。

最终结果

短期保留,供等待/恢复读取

回调到达
  ↓
写 Redis
  ↓
Pub/Sub 通知
  ↓
等待线程立即醒来

唤醒通知

项目会先把数据写进 Redis,再执行 Publish。如果pub失败,模型仍可以通过定期扫描获取数据;如果写入失败,模型会通过agent run进行重试。

Redis 心跳

Agent执行过程中,要通过Redis 心跳告诉Scheduler巡检员自己没有宕机。