小工具      在线工具  汉语词典  dos游戏  css  js  c++  java

elastic-job的原理简介和使用

Java 额外说明

收录于:52天前

基本概念
1. 分片概念
任务的分布式执行需要将一个任务拆分为多个独立的任务项,然后分布式服务器分别执行一个或多个分片项。

例如:有一个作业需要遍历数据库中的某个表,目前有2台服务器。为了快速执行作业,每个服务器应该执行50%的作业。为了满足这个要求,可以将作业分为2个片,每个服务器执行1个片。作业遍历数据的逻辑应该是:服务器A遍历ID以奇数结尾的数据;服务器B遍历ID以偶数结尾的数据。如果分成10片,则作业遍历数据的逻辑应为:每片分到的分片项应为ID%10,而服务器A被分配到分片项0,1,2,3,4;服务器B被分配到分片项5,6,7,8,9,直接的结果就是服务器A遍历ID以0-4结尾的数据;服务器B遍历ID以5-9结尾的数据。

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

3. 个性化参数的适用场景
个性化参数即shardingItemParameter,可以和分片项匹配对应关系,用于将分片项的数字转换为更加可读的业务代码。

例如:按照地区级别拆分数据库,数据库A是北京的数据;数据库B是上海的数据;数据库C是广州的数据。如果只按照分片项配置,开发者需要知道0代表北京; 1 指上海; 2 指广州。合理使用个性化参数可以使代码更具可读性。如果配置为0=北京、1=上海、2=广州,那么代码中可以直接使用北京、上海、广州的枚举值来完成分片项与业务逻辑的对应关系。

核心理念
1. 分布式调度
Elastic-Job-Lite并无作业调度中心节点,而是基于部署作业框架的程序在到达相应时间点时各自触发调度。

注册中心仅用于作业注册和监控信息存储。主作业节点仅用于处理分片、清理等功能。

2. 作业高可用
Elastic-Job-Lite 提供了最安全的作业执行方式。将分片总数设置为 1,并使用 1 台以上服务器来执行作业。作业将以1主n从的方式执行。

一旦执行作业的服务器崩溃,等待执行的服务器将在下次作业启动时被替换。最好开启故障转移功能,这样可以保证如果作业在执行过程中崩溃,备份机会立即启动备份执行。

3. 最大限度利用资源
Elastic-Job-Lite 还提供了最灵活的方法来最大化执行作业的吞吐量。设置分片项大于服务器数量,最好是服务器的倍数。该作业将合理利用分布式资源,动态分配分片项。

例如: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。在不丢失分片项的情况下,最大限度的利用现有资源提高吞吐量。

elastic-job是当当开源的一款非常好用的作业框架,在这之前,我们开发定时任务一般都是使用quartz或者spring-task(ScheduledExecutorService),无论是使用quartz还是spring-task,我们都会至少遇到两个痛点:
1.不敢轻易跟着应用服务多节点部署,可能会重复多次执行而引发系统逻辑的错误。
2.quartz的集群仅仅只是用来HA,节点数量的增加并不能给我们的每次执行效率带来提升,即不能实现水平扩展。
本篇博文将会自顶向下地介绍elastic-job,让大家认识了解并且快速搭建起环境。

elastic-job产品线说明
elastic-job在2.x之后,出了两个产品线:Elastic-Job-Lite和Elastic-Job-Cloud。我们一般使用Elastic-Job-Lite就能够满足需求,本文也是以Elastic-Job-Lite为主。1.x系列对应的就只有Elastic-Job-Lite,并且在2.x里修改了一些核心类名,差别虽大,原理类似,建议使用2.x系列。写此博文,最新release版本为2.0.5。
 

elastic-job-lite原理
举个典型的job场景,比如余额宝里的昨日收益,系统需要job在每天某个时间点开始,给所有余额宝用户计算收益。如果用户数量不多,我们可以轻易使用quartz来完成,我们让计息job在某个时间点开始执行,循环遍历所有用户计算利息,这没问题。可是,如果用户体量特别大,我们可能会面临着在第二天之前处理不完这么多用户。另外,我们部署job的时候也得注意,我们可能会把job直接放在我们的webapp里,webapp通常是多节点部署的,这样,我们的job也就是多节点,多个job同时执行,很容易造成重复执行,比如用户重复计息,为了避免这种情况,我们可能会对job的执行加锁,保证始终只有一个节点能执行,或者干脆让job从webapp里剥离出来,独自部署一个节点。
elastic-job就可以帮助我们解决上面的问题,elastic底层的任务调度还是使用的quartz,通过zookeeper来动态给job节点分片。
我们来看:
很大体量的用户需要在特定的时间段内计息完成
我们肯定是希望我们的任务可以通过集群达到水平扩展,集群里的每个节点都处理部分用户,不管用户数量有多庞大,我们只要增加机器就可以了,比如单台机器特定时间能处理n个用户,2台机器处理2n个用户,3台3n,4台4n...,再多的用户也不怕了。
使用elastic-job开发的作业都是zookeeper的客户端,比如我希望3台机器跑job,我们将任务分成3片,框架通过zk的协调,最终会让3台机器分别分配到0,1,2的任务片,比如server0-->0,server1-->1,server2-->2,当server0执行时,可以只查询id%3==0的用户,server1执行时,只查询id%3==1的用户,server2执行时,只查询id%3==2的用户。
任务部署多节点引发重复执行
在上面的基础上,我们再增加server3,此时,server3分不到任务分片,因为只有3片,已经分完了。没有分到任务分片的作业程序将不执行。
如果此时server2挂了,那么server2的分片项会分配给server3,server3有了分片,就会替代server2执行。
如果此时server3也挂了,只剩下server0和server1了,框架也会自动把server3的分片随机分配给server0或者server1,可能会这样,server0-->0,server1-->1,2。
这种特性称之为弹性扩容,即elastic-job名称的由来。
代码演示
我们搭建环境通过示例代码来演示上面的例子,elastic-job是不支持单机多实例的,通过zk的协调分片是以ip为单元的。很多同学上来可能就是通过单机多实例来学习,结果导致分片和预期不一致。这里没办法,只能通过多机器或者虚拟机,我们这里使用虚拟机,另外,由于资源有限,我们这里仅仅只模拟两台机器。

节点说明:
本地宿主机器
zookeeper、job
192.168.241.1

虚拟机
job
192.168.241.128

环境说明:
Java
请使用JDK1.7及其以上版本。
Zookeeper
请使用Zookeeper3.4.6及其以上版本
Elastic-Job-Lite
2.0.5(2.x系列即可,最好是2.0.4及其以上,因为2.0.4版本有本人提交的少许代码,(*^__^*) 嘻嘻……)

需求说明:
通过两台机器演示动态分片

步骤1。引入框架的jar包

<!-- 引入elastic-job-lite核心模块 -->
<dependency>
    <groupId>com.dangdang</groupId>
    <artifactId>elastic-job-lite-core</artifactId>
    <version>2.0.5</version>
</dependency>
<!-- 使用springframework自定义命名空间时引入 -->
<dependency>
    <groupId>com.dangdang</groupId>
    <artifactId>elastic-job-lite-spring</artifactId>
    <version>2.0.5</version>
</dependency>

第2步。写作业

package com.fanfan.sample001;
 
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
 
import java.util.Date;
 
/**
 * Created by fanfan on 2016/12/20.
 */
public class MySimpleJob implements SimpleJob {
    @Override
    public void execute(ShardingContext shardingContext) {
        System.out.println(String.format("------Thread ID: %s, 任务总片数: %s, 当前分片项: %s",
                Thread.currentThread().getId(), shardingContext.getShardingTotalCount(), shardingContext.getShardingItem()));
        /**
         * 实际开发中,有了任务总片数和当前分片项,就可以对任务进行分片执行了
         * 比如 SELECT * FROM user WHERE status = 0 AND MOD(id, shardingTotalCount) = shardingItem
         */
    }
}

步骤3.弹簧配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:reg="http://www.dangdang.com/schema/ddframe/reg"
       xmlns:job="http://www.dangdang.com/schema/ddframe/job"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.dangdang.com/schema/ddframe/reg
                        http://www.dangdang.com/schema/ddframe/reg/reg.xsd
                        http://www.dangdang.com/schema/ddframe/job
                        http://www.dangdang.com/schema/ddframe/job/job.xsd">
    <!--配置作业注册中心 -->
    <reg:zookeeper id="regCenter" server-lists="192.168.241.1:2181" namespace="dd-job"
                   base-sleep-time-milliseconds="1000" max-sleep-time-milliseconds="3000" max-retries="3" />
 
    <!-- 配置作业-->
    <job:simple id="mySimpleJob" class="com.fanfan.sample001.MySimpleJob" registry-center-ref="regCenter"
                sharding-total-count="2" cron="0/2 * * * * ?" overwrite="true" />
 
</beans>

作业类型
elastic-job提供了三种类型的作业:Simple类型作业、Dataflow类型作业、Script类型作业。这里主要讲解前两者。Script类型作业意为脚本类型作业,支持shell,python,perl等所有类型脚本,使用不多,可以参见github文档。

SimpleJob需要实现SimpleJob接口,即实现简单,无需任何封装。它类似于quartz本地接口,例如示例代码中使用的作业。

Dataflow类型用于处理数据流,需实现DataflowJob接口。该接口提供2个方法可供覆盖,分别用于抓取(fetchData)和处理(processData)数据。
可通过DataflowJobConfiguration配置是否流式处理。
流式处理数据只有fetchData方法的返回值为null或集合长度为空时,作业才停止抓取,否则作业将一直运行下去; 非流式处理数据则只会在每次作业执行过程中执行一次fetchData方法和processData方法,随即完成本次作业。
实际开发中,Dataflow类型的job还是很有好用的。

比如拿余额宝计息来说:
 

package com.fanfan.sample001;
 
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.dataflow.DataflowJob;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * Created by fanfan on 2016/12/23.
 */
public class MyDataFlowJob implements DataflowJob<User> {
 
    /*
        status
        0:待处理
        1:已处理
     */
 
    @Override
    public List<User> fetchData(ShardingContext shardingContext) {
        List<User> users = null;
        /**
         * users = SELECT * FROM user WHERE status = 0 AND MOD(id, shardingTotalCount) = shardingItem Limit 0, 30
         */
        return users;
    }
 
    @Override
    public void processData(ShardingContext shardingContext, List<User> data) {
        for (User user: data) {
            System.out.println(String.format("用户 %s 开始计息", user.getUserId()));
            user.setStatus(1);
            /**
             * update user
             */
        }
    }
}
<job:dataflow id="myDataFlowJob" class="com.fanfan.sample001.MyDataFlowJob" registry-center-ref="regCenter"
              sharding-total-count="2" cron="0 0 02 * * ?" streaming-process="true" overwrite="true" />

其它功能
上述介绍的是最精简常用的功能。elastic-job的功能集还不止这些,比如像作业事件追踪、任务监听等,另外,elastic-job-lite-console作为一个独立的运维平台还提供了用来查询和操作任务的web页面。
这些增强的功能读者可以在github/elastic-job上自行学习,相信有了本篇博文的基础,再阅读那些文档就特别简单了。

原文:https://blog.csdn.net/fanfan_v5/article/details/61310045 

 

. . .

相关推荐

额外说明

Elasticsearch官方文档要点

normalizer : 标准化text,比如将大写转换成小写,这样倒排索引实际存储的是转换后的token,比如User user这两个doc实际是等价的,当搜索user时能匹配到两个doc,当对USer做统计时能统计到两个,但是_source里的fie

额外说明

前后端分离架构文件上传下载(含Vue+Spring完整代码)

一、前言 本文采用前后端分离式的架构,其中涉及到文件下载的需求,文件下载在任何系统中都是比较常见的。对于前后端分离架构的文件下载与往常的写法有些许不同(试过直接使用a标签,href填上下载地址,发现行不通),所以经过查找与尝试,以下文件下载前后端实现流程

额外说明

unity 接入百度人工智能Demo

Unity 版本 2020.1.0a12 demo 下载 demo下载 LoadAudio // ======================================================== // 描述:加载音乐 // 作者:qing

额外说明

设计模式——工厂方法模式

设计模式——工厂方法模式 //鼠标抽象类 public abstract class Mouse { public abstract void Print(); } //戴尔鼠标 publ

额外说明

【OpenCV】高手勿入! 半小时学会基本操作 8 ROI & 泛洪

【OpenCV】高手勿入! 半小时学会基本操作 8 概述 ROI 泛洪填充 概述 OpenCV 是一个跨平台的计算机视觉库, 支持多语言, 功能强大. 今天小白就带大家一起携手走进 OpenCV 的世界. (第 8 课) ROI ROI (Region

额外说明

疫情趋势下,远程控制软件成为刚需,ToDesk or 向日葵,哪一款最好用?

前言 自 2020 年疫情爆发以来,为了避免员工外出感染的风险,很多企业被迫改变经营模式,从传统的办公室上班模式逐渐变为远程在家办公。既然是远程办公,当然离不开远程控制软件,这一年多时间我算是什么远程软件都见识过了,最离谱的 2021 年了居然还有人在用

额外说明

阿里云创建二级域名,并在在nginx中配置二级域名访问

一、创建二级域名 1、在阿里云上(获取别的域名商)处点击域名 2、在域名列表中点击解析 3、新增解析 4、新增二级域名 5、解析生产后正常在浏览器访问地址 # xxx是你的域名 mp.xxx.cn 二、在nginx中配置你的二级域名 1、本人是cent

额外说明

T-SQL(SQL Sever) 简单语句实例

说明 此部分只注重语句的语法,使用场景和合理性不考虑在内。 此例子是主要是对一个货物表的价格进行操作。 创建表 //创建表 create table goods( gid int primary key, gname varchar(10),

额外说明

13、Redis与Mysql数据双写一致性

Redis与Mysql数据双写一致性 1、 复习+面试题 先动Mysql,再动Redis,两害相衡取其轻,避免Redis业务key突然消失,多线程请求集火打满mysql 动,写操作,先更新数据库,在删除缓存。回写的时候使用双检加锁机制锁住mysql,只让

ads via 小工具