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
用于判断允许还是拒绝。
调用前
- 清理超时成员
- 检查当前数量
- 未超过上限则 ZADD
调用后
ZREM 调用 ID
任务去重、消息重复消费问题
通过 SETNX 判断是否已经执行,SET NX 是 SET 命令配合 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巡检员自己没有宕机。