分布式任务调度的几种实现(Redis实现分布式锁 MySQL实现任务调度 负载均衡)

需求背景

现在有一个计算搜索词热榜的任务,该服务部署在了多个节上,希望只有一个节点在执行这个任务。

常见方案

使用Redis实现分布式锁方案

使用一个分布式锁,确保整个分布式环境下,只有一个节点能够拿到锁。节点先抢占分布式锁,如果抢到了分布式锁的话,就执行计算搜索词热榜的任务,否则的话,就跳过该任务。

使用Redis实现的话,可以使用SexNX命令,SETNX task1_key pod1表示节点pod1正在尝试抢任务task1的分布式锁。设置的时候需要设置过期时间。如果上锁成功的话,说明该节点可以执行任务task1。

解锁的话,采用lua脚本完成。这个脚本检查一个键的值是否等于给定的参数值,如果相等,则删除该键;否则,返回0。传入的KEYS[1] = "task1_key",ARGV[1]="pod1"。

lua 复制代码
if redis.call('get', KEYS[1]) == ARGV[1] then  
    return redis.call('del', KEYS[1])  
else  
    return 0  
end

使用MySQL实现任务调度

在MySQL的数据库里创建一张表,里面是所有等待运行的定时任务。所有的节点都试着从表里抢占任务,如果成功的话就执行该任务。

这里的抢占,可以使用乐观锁来更新状态实现。先找到符合条件的任务,假设任务执行状态为等待开始,对应的数据库表字段为status=waiting_start,假设此时的version=1。然后尝试更新状态为update status = running。那么对于更新成功的节点来说,就相当于抢占到了该任务。如何保证更新的时候,没有其他节点抢占呢?更新的时候同时判断status=waiting_start,version=1,就能保证单节点抢占。

这里会存在的一个问题就是,如果已经抢占到任务但是任务还没执行完,该节点就异常退出了,但是其他节点都会认为该节点依旧在执行任务,就会陷入死锁的局面。想了一下解决方案就是,引入续约机制,对于MySQL实现而言,就是该节点需要不断地更新数据库的update_time字段,也就是更新时间,证明自己的状态正常;对于Redis实现而言,相当于延长锁的过期时间。

开源框架 XXL-JOB

XXL-JOB 是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习门槛低、功能强大并且轻量级。它支持自定义任务调度策略,支持多种执行模式,并且支持动态分片。

XXL-JOB主要由调度中心和执行器两部分组成。调度中心负责管理调度信息,按照调度配置发出调度请求,但自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块。执行器则负责接收调度请求并执行任务逻辑。

退一步而言,如果引入XXL-JOB的成本过高,可以考虑起一个单独的服务执行定时任务,运行在单pod上,这样的好处是开发快捷方便,缺点可能在于修改任务需要服务发版。

负载均衡

前两种方案在设计的时候,都是看哪个节点先抢占到任务,没有结合节点的情况考虑,如果一个本身就负载高的节点抢占到了任务,那么可能会影响到其他的业务逻辑,甚至引发节点OOM或崩溃。这种情况下,应该在调度的时候就引入一些负载均衡策略,

  • 检查节点的负载情况,超出健康阈值后就不抢占任务,比如内存使用率>=80%或CPU使用率>=80%,就不抢占该定时任务,同时设置一个定时任务未执行的报警,方便监控。
  • 每次选取负载最低的节点来进行,可以是内存最低也可以是CPU利用率最低,这就要求有一个控制中枢检测各个节点的负载情况,感觉需要借助中间件实现
  • 如果某个节点正在运行该任务,但是运行中的负载较高,就要及时中断并更换节点,做容错处理
  • 如果定时任务运行需要的资源较多,可以考虑使用XXL-JOB这种分布式任务调度框架
相关推荐
虹科网络安全8 小时前
Redis Radar:在统一视图中掌握 Redis 部署、健康与容量
经验分享·redis·艾体宝·艾体宝it·艾体宝redis
大大大大晴天9 小时前
每天认识一个组件:Redis
redis
这个DBA有点耶15 小时前
函数索引的“完全一致”有多苛刻:写法、字符集、类型,差一处就失效
数据库·mysql·代码规范
星恒随风15 小时前
MySQL 从零入门(三):表的约束详解
linux·服务器·数据库·笔记·mysql
Alluxio16 小时前
Alluxio + OCI:为 AI 工作负载实现亚毫秒访问延迟与可扩展吞吐
运维·数据库·人工智能·分布式·缓存·ai·语言模型
虹科网络安全20 小时前
Search on Flex:用分层存储承载更大规模的 Redis 搜索索引
经验分享·redis·艾体宝·艾体宝it
青瓦梦滋20 小时前
Redis主从复制
服务器·数据库·redis·缓存·bootstrap
阿卡好可爱21 小时前
Lua 热更新不生效:改完文件线上仍是旧逻辑,package.loaded 与 upvalue 重绑定详解
数据结构·分布式·后端·架构·lua
Joy T1 天前
Redis Lua 原子限流:Lua 脚本、竞态条件与并发控制
数据库·redis·lua·限流·竞态条件·redis scripting