ElasticJob分布式调度,分布式多个微服务执行只需要执行一个定时任务,基本概念介绍(一)

ElasticJob分布式调度,分布式多个微服务执行只需要执行一个定时任务,基本概念介绍(一)

问题背景

最近的项目中需要做一个定时任务,该项目是一个分布式多节点调度任务,所以里面的定时任务在不同的节点不应该同时进行,应该使用其中一个节点做定时任务,目前寻找的方案为ElasticJob,这个篇章简单介绍一下

ElasticJob简介

1 Elastic-job官网地址:https://shardingsphere.apache.org/elasticjob/current/cn/overview/
Elastic-Job的github地址: https://github.com/elasticjob
2 打开官网可以知道ElasticJob 已于 2020 年 5 月 28 日成为 Apache ShardingSphere 的子项目,所以在这之前我看别人都是使用dangdang的依赖,Elastic-Job 是elastic-job是当当开源的作业框架,在这之前,开发定时任务一般都是使用quartz或者spring-task(ScheduledExecutorService),无论是使用quartz还是spring-task,都会至少遇到两个痛点:

  • 不敢轻易跟着应用服务多节点部署
  • 可能会重复多次执行而引发系统逻辑的错误

3 quartz的集群仅仅只是用来HA(提高可用性),节点数量的增加并不能给我们的每次执行效率带来提升,即不能实现水平扩展
4 Elastic job是当当网基于Zookepper、Quartz开发并开源的一个Java分布式定时任务,解决了Quartz不支持分布式的弊端
5 Elastic job主要的功能有支持弹性扩容,通过Zookepper集中管理和监控job,支持失效转移等。项目由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成
6 分布式:一个大的业务拆分成多个小业务分别部署在服务器,如:订单服务、商品服务和用户服务
7 分布式任务调度:订单服务中定时统计订单信息,商品服务中定时更新商品信息,用户服务定时更新用户信息
8 Elastic-Job的优点:

  • 并行任务调度(多台服务器同时执行任务)
  • 高可用
  • 高扩展
  • 任务管理和检测
  • 避免任务重复执行

单节点的定时任务

1 如果只是一个单节点,定时任务大可使用spring的注解@Scheduled,并在启动类使能定时注解@EnableScheduling注解,此注解才能让定时任务生效

@Scheduled(cron = "0/5 * * * * ? ")  //此为cron表达式,设置定时所需的时间点或周期
 public void timeTask(){
 	//doSomething   
 }

如果任务的数据量为3000W非常大,一台服务器的硬件资源cpu和内存都是有限的,这是就可以使用分布式定时调度,可以分为3个节点分别处理1000W数据

分布式调度

1 使用分布式调度的情况

  • 单机处理极限:原本1分钟内需要处理1万个订单,但是现在需要1分钟内处理10万个订单;原来一个统计需要1小时,现在业务方需要10分钟就统计出来。如果使用多线程、单机多进程处理,多线程并行处理可以提高单位时间的处理效率,但是单机能力有限(主要是CPU、内存和磁盘),始终会有单机处理不过来的情况
  • 高可用:单机版的定式任务调度只能在一台机器上运行,如果程序或者系统出现异常就会导致功能不可用,对于核心功能是不允许的,所以才有集群出现
  • 防止重复执行: 在单机模式下,定时任务是没什么问题的。但当我们部署了多台服务,同时又每台服务又有定时任务时,若不进行合理的控制在同一时间,只有一个定时任务启动执行,这时,定时执行的结果就可能存在混乱和错误了

2 两种情况使用分布式调度

  • 例1:要去对表的数据进行备份的操作,这个表中有1000W条数据,若是我们只是单一去执行这个需求,那么会耗费很多的时间,那么这种情况就有可能会去进行一个集群,但是集群后又会出现一个问题,就是在spring定时器情况下,所有的集群做的都是同样的是事情,而我们需要的就是不同的微服务做的是不同的,但是都是为了去备份这一份数据库的数据,所以无法实现。分布式调度就是分治思想,将大的拆成小的,分成多份各自执行各自的,但是都是为了完成一个需求
  • 例2: 要把mysql数据同步到redis中,比如有两个服务,此时两个服务都有定时任务,这个定时任务就会在两台机器中同时执行,我们可能只想要让其中一个去执行,而不是同时执行,所以使用spring定时器是不行的。使用分布式调度,因为集群中都是同样功能,但是定时器只需要其中一个进行执行就可以

3 ElasticJob功能列表
- 分布式调度
  在分布式环境中,任务能够按照指定的调度策略执行,并且能够避免同一任务多实例重复执行
- 调度策略
  基于成熟的定时任务作业框架Quartz cron表达式执行定时任务
- 弹性扩容所容
  当集群中增加一个实例,它应当能够被选举被执行任务;当集群减少一个实例时,他所执行的任务能被转移到别的示例中执行
- 失效转移
  某示例在任务执行失败后,会被转移到其他实例执行
- 错过执行任务重触发
  若因某种原因导致作业错过执行,自动记录错误执行的作业,并在下次次作业完成后自动触发
- 支持并行调度
  支持任务分片,任务分片是指将一个任务分成多个小任务在多个实例同时执行
- 作业分片一致性
  当任务被分片后,保证同一分片在分布式环境中仅一个执行实例
- 支持作业生命周期操作
  可以动态对任务进行开启及停止操作
- 丰富的作业类型
  支持Simple、DataFlow、Script三种作业类型,elasticJob会把定时任务的信息存放到zookeeper中,zookeeper不单单是注册中心,也可以作为一个存数据的容器
- 系统架构图

从图中可以看到,通过注册中心zookeeper去监听app应用,当出现节点数据及状态变化,可以进行通知,可以进行故障转移

分片的概念

1 作业分片是指任务的分布式执行,需要将一个任务拆分为多个独立的任务项,然后由分布式的应用实例分别执行某一个或者几个分布项

例如:有两台服务器,每台服务器分别跑一个应用实例,为了快速执行作业,可以将任务分成4片,那么每个应用实例都执行两片。作业遍历数据逻辑应为:实例1查找text和image类型文件执行备份,实例2查找radio和vedio类型文件执行备份。如果由于服务器扩容应用实例数量增加为4,则作业遍历数据的逻辑应为: 4个实例分别处理text,image,radio,video类型的文件。

通过对任务的合理分片化,从而达到任务并行处理的效果.
分片机制:多台机器执行一个任务,想要的效果就是一个大的任务拆分为很多小的任务并在多台机器中执行

2 分片项与业务处理解耦

Elastic-Job并不直接提供数据处理的功能,框架只会将分片项分配至各个运行中的作业服务器,开发者需要自行处理分片项与真实数据的对应关系

3 最大限度利用资源

将分片项设置大于服务器的数据,最好是大于服务器倍数的数量,作业将会合理利用分布式资源,动态的分配分片项.
例如: 3台服务器,分成10片,则分片项结果为服务器A=0,1,2;服务器B=3,4,5;服务器C=6,7,8,9;如果 服务器C崩溃,则分片项分配结果为服务器A=0,1,2,3,4;服务器B=5,6,7,8,9;在不丢失分片项的情况下,最大限度利用现有的资源提高吞吐量

Dataflow类型调度任务

1 Dataflow类型的定时任务需要实现Dataflowjob接口,该接口提供2个方法供覆盖,分别用于抓取(fetchData)和处理(processData)数据
2 Dataflow类型用于处理数据流,他和SimpleJob不同,它以数据流的方式执行,调用fetchData抓取数据,知道抓取不到数据才停止作业
3 simpleJob相当于生活中的搬家时一次性把所有东西都搬过去,Dataflowjob相当于分几次把东西搬走

例如:我们需要查询1000W条的数据库数据并备份,而我们若是一次性查出1000W的数据去统一做备份,那么可能效率就会比较低。若是使用dataflowjob 那么我们可以一次查询20W条数据备份完后再去处理后面的20W条数据,依次如此,一点点处理完

总结




作为程序员第 108 篇文章,每次写一句歌词记录一下,看看人生有几首歌的时间,wahahaha …

Lyric: 就算没有结果

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ElasticJob 是面向互联网生态和海量任务分布式调度解决方案,由两个相互独立的子项目 ElasticJob-Lite 和 ElasticJob-Cloud 组成。 它通过弹性调度、资源管控、以及作业治理的功能,打造一个适用于互联网场景的分布式调度解决方案,并通过开放的架构设计,提供多元化的作业生态。 它的各个产品使用统一的作业 API,开发者仅需一次开发,即可随意部署。 使用 ElasticJob 能够让开发工程师不再担心任务的线性吞吐量提升等非功能需求,使他们能够更加专注于面向业务编码设计; 同时,它也能够解放运维工程师,使他们不必再担心任务的可用性和相关管理需求,只通过轻松的增加服务节点即可达到自动化运维的目的。 功能列表 1、弹性调度 支持任务分布式场景下的分片和高可用 能够水平扩展任务的吞吐量和执行效率 任务处理能力随资源配备弹性伸缩 2、资源分配 在适合的时间将适合的资源分配给任务并使其生效 相同任务聚合至相同的执行器统一处理 动态调配追加资源至新分配的任务 3、作业治理 失效转移 错过作业重新执行 自诊断修复 4、作业依赖(TODO) 基于有向无环图(DAG)的作业间依赖 基于有向无环图(DAG)的作业分片间依赖 5、作业开放生态 可扩展的作业类型统一接口 丰富的作业类型库,如数据流、脚本、HTTP、文件、大数据等 易于对接业务作业,能够与 Spring 依赖注入无缝整合 6、可视化管控端 作业管控端 作业执行历史数据追踪 注册中心管理 环境要求: Java 请使用 Java 8 及其以上版本。 ZooKeeper 请使用 ZooKeeper 3.6.0 及其以上版本。 Mesos(仅 ElasticJob-Cloud 使用) 请使用 Mesos 1.1.0 及其兼容版本。
### 回答1: Redis 支持通过使用 Lua 脚本实现分布式锁。可以使用 Redis 的 SET 命令,并在设置锁时设置过期时间,以避免死锁。 以下是 Redisson 库中实现分布式锁的示例代码: ```java // 创建 RedissonClient 客户端 RedissonClient redisson = Redisson.create(); // 获取锁对象 RLock lock = redisson.getLock("lockName"); // 加锁,设置锁最长占用时间为10s lock.lock(10, TimeUnit.SECONDS); try { // do something } finally { // 释放锁 lock.unlock(); } ``` 注意: 1. 获取锁时需要捕获异常,确保释放锁,防止死锁 2. 为了保证锁能尽可能少时间持有,建议锁的持有时间尽可能短 以上代码使用redission来实现分布式锁,用于解决定时任务不重复执行的问题。 ### 回答2: Redission是一个开源的分布式锁框架,可以用于解决定时任务不重复执行的问题。下面是一个用Redission实现分布式锁的示例。 在使用Redission之前,需要在项目中添加对Redission依赖的引用。可以在项目的构建文件中添加相关依赖,然后按照文档的指示进行安装和配置。 首先,创建一个任务类,用于执行定时任务的逻辑。在任务类中,可以使用Redission获取分布式锁,并在获取到锁之后执行任务逻辑。在任务逻辑执行完成后,释放锁,以便其他节点能够获取锁执行任务。 下面是一个示例的任务类: ```java import org.redisson.Redisson; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.redisson.config.Config; public class ScheduledTask implements Runnable { private static final String LOCK_NAME = "myLock"; private static final String REDIS_HOST = "127.0.0.1"; private static final int REDIS_PORT = 6379; @Override public void run() { // 创建 Redisson 配置 Config config = new Config(); config.useSingleServer().setAddress("redis://" + REDIS_HOST + ":" + REDIS_PORT); // 创建 Redisson 客户端 RedissonClient redissonClient = Redisson.create(config); // 获取分布式锁 RLock lock = redissonClient.getLock(LOCK_NAME); try { // 尝试获取锁 if (lock.tryLock()) { // 执行任务逻辑 System.out.println("执行定时任务"); } } finally { // 释放锁 lock.unlock(); } } } ``` 在任务逻辑中,首先创建一个Redission的配置对象,并指定Redis的连接地址。然后创建一个Redission客户端对象。 接下来,通过Redission客户端对象获取一个分布式锁,使用tryLock方法尝试获取锁。如果成功获取到锁,则执行任务逻辑。 任务执行完成后,需要手动释放锁,以便其他节点能够获取锁执行任务。 在实际项目中,可以结合Spring的定时任务功能,将上述代码作为一个定时任务执行逻辑。这样就可以实现定时任务分布式环境中的不重复执行。 希望以上内容对您有帮助! ### 回答3: Redission是一个基于Redis的分布式Java框架,可用于解决分布式系统中的各种问题,包括分布式锁。要使用Redission解决定时任务不重复执行的问题,可以按照以下步骤进行操作: 1. 引入Redission依赖:在项目的pom.xml文件中添加Redission的依赖,确保项目可以使用Redission相关的类和方法。 2. 创建Redission客户端:使用Redission提供的配置信息,创建一个Redission客户端对象,并与Redis实例建立连接。 3. 获取分布式锁:在每个定时任务开始执行前,通过调用Redission的分布式锁方法获取锁。 4. 判断锁的状态:在获取锁成功后,在定时任务的代码中加入判断锁的逻辑,确保只有第一个获取到锁的任务可以继续执行,其他任务则放弃执行并等待下次定时。 5. 释放锁:在定时任务执行完成后,调用Redission的释放锁方法,释放之前获取的锁资源,以便其他任务可以获取到锁并执行。 通过以上步骤,使用Redission可以实现分布式锁,确保定时任务不会被重复执行需要注意的是,在使用分布式锁时,应该关注锁的超时时间,以避免某个任务异常退出或崩溃导致锁一直占用而无法释放。另外,还要确保Redis的高可用性,以及Redission客户端与Redis实例之间的网络通信稳定性,以保证分布式锁的可靠性和正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值