我们需要一个“单点worker”系统,此系统来确保系统中定时任务在分布式环境中,任意时刻只有一个实例处于活跃;比如,生产环境中,有6台机器支撑一个应用,但是一个应用中有30个定时任务,这些任务有些必须被在“单线程”环境中运行(例如“数据统计”任务),避免并发的原因不是在java层面,可能是在操作db数据时,或者是在消息消费时,或者是信息推送时等。某个指标的“数据统计”任务,每天只需要执行一次,即使执行多次也是妄费,因为这种类型的定时任务,需要被“单点”。同时,如果一个任务在没有报告结果的情况下异常推出,我们仍然期望集群中其他实例能够主动“接管”它。在实现不良好的架构中,可能有些开发者使用手动触发特定脚本的方式执行,有些web项目可能是通过配置特定host的方式开启任务。对于某些定时任务,可能会采用quartz-cluster中的某些实现,但是他需要数据库的额外支持。
     此时,我们将使用zookeeper来实现此功能。本实例提供了如下功能展示:
    1) 提供了单点worker功能
    2) 提供了worker均衡能力(30个worker相对均匀的分配到6台机器上)
    3) 提供了worker失效接管能力。

但是仍有很多亟待解决的问题:
    1) 无法确保任务的接管是及时的,即一个任务执行者失效,将会在一定的过期时间后,才会被其他sid接管
    2) 在极少的情况下,仍然会有一个任务同时被2个sid执行。
    3) 在极少的情况下,会有极短的时间内,一个任务不会被任何sid接管,处于“孤立”状态
    尽管zk提供了watch机制,但是上述问题,不仅不能完全避免,还会额外增加代码的复杂度。最终我个人放弃了对在此类中使用watch的想法。。
    注意:zk中exist和create/delete等操作并非原子,可能在exist返回false的情况下,去create此节点,也有可能抛出NoExistsException;你应该能够想到“并发”环境造成此问题的时机(其他zk客户端也有类似的操作,并发)。
    注意:在zk中删除父节点,将会导致子节点一并删除;同理,如果创建一个节点,那么它的各级父节点必须已经存在,且节点的层级越深,对zk底层存储而言数据结构越冗杂。
 
    数据结构与设计思路:
    1) serverType为当前应用标识,我们期望每个应用都有各自的serverType,方便数据分类; jobType为任务类型或者任务名称;如下全节点表示某个serverType的jobType下有sid1,sid2,sid3共三个实例(例如tomcat实例,或者物理机器标识)参与了此任务。zk节点路径格式:
        /severType/jobType/register/sid1 
        ............................../sid2
        ............................../sid3
    2) 表示此jobType,被sid1运行。zk节点路径格式
        /severType/jobType/alive/sid1 挂载数据:null
    3) /serverType/jobType 挂载数据:cronExpression;将任务的“cron表达式”作为数据挂载
    4) {todu} 表示serverType下每个sid运行的任务个数,我们可以用来“均衡”任务,将新任务分配给任务较少的sid上。
        /serverType/sid1 挂载数据:任务个数.

如下是本人的代码样例,实际生产环境中代码与样例有区别,此处仅供参考,本实例基于zookeeper + quartz 2.1,如有错误之处,请不吝赐教:

1) TestMain.java :测试引导类

2) PrintNumberJob.java:一个简单的任务,打印一个随即数字。

3) PrintTimeJob.java:一个简单的任务,打印当前时间。

4) SingleWorkerManager.java:核心类,用于处理调用者提交的任务,并确保结果符合预期。此类有2个内部工作线程组成,分别处理zk数据同步和用户任务交付等工作。

zookeeper实战:SingleWorker代码样例

zookeeper实战:SingleWorker代码样例的更多相关文章

  1. 2020JAVA最新应对各种OOM代码样例及解决办法

    引言 作者:黄青石 链接:https://www.cnblogs.com/huangqingshi/p/13336648.html?utm_source=tuicool&utm_medium= ...

  2. 33个超级有用必须要收藏的PHP代码样例

    作为一个正常的程序员,会好几种语言是十分正常的,相信大部分程序员也都会编写几句PHP程序,如果是WEB程序员,PHP一定是必备的,即使你没用开发过大型软件项目,也一定多少了解它的语法. 在PHP的流行 ...

  3. java servlet 代码样例 (demo)

    今天又搞了下jsp +servlet 的代码样例,感觉虽然搭了好多次,可是每次还是不记得那些参数,都要去网上搜索,索性自己把这次的简单demo给记录下来,供下次使用的时候直接复制吧. 这个web逻辑 ...

  4. 30个php操作redis经常用法代码样例

    这篇文章主要介绍了30个php操作redis经常用法代码样例,本文事实上不止30个方法,能够操作string类型.list类型和set类型的数据,须要的朋友能够參考下 redis的操作非常多的,曾经看 ...

  5. 14.ZooKeeper Java API 使用样例

    转自:http://www.aboutyun.com/thread-7332-1-1.html package com.taobao.taokeeper.research.sample; import ...

  6. JAVA各种OOM代码样例及解决方法

    周末了,觉得我还有很多作业没有写,针对目前大家对OOM的类型不太熟悉,那么我们来总结一下各种OOM出现的情况以及解决方法. 我们把各种OOM的情况列出来,然后逐一进行代码编写复现和提供解决方法. 1. ...

  7. PHP代码样例

    1 <?php 2 3 /** 4 * 时间:2015-8-6 5 * 作者:River 6 * 超级有用.必须收藏的PHP代码样例 7 */ 8 class Helper { 9 10 /** ...

  8. Java操作HDFS代码样例

    代码在GitHub上. 包括如下几种样例代码: 新建文件夹 删除文件/文件夹 重命名文件/文件夹 查看指定路径下的所有文件 新建文件 读文件 写文件 下载文件至本地 上传本地文件 https://gi ...

  9. Python代码样例列表

    扫描左上角二维码,关注公众账号 数字货币量化投资,回复“1279”,获取以下600个Python经典例子源码 ├─algorithm│       Python用户推荐系统曼哈顿算法实现.py│    ...

随机推荐

  1. Javascript-- jQuery动画篇(2)

    动画效果 前面的 hide/show,slide in/out 其实也具有动画效果,本篇介绍使用 animate()实现自定义动画效果. 基本语法如下: $(selector).animate({pa ...

  2. vue.js 源代码学习笔记 ----- instance render

    /* @flow */ import { warn, nextTick, toNumber, _toString, looseEqual, emptyObject, handleError, loos ...

  3. 在servlet中的中文乱码,相对路径和绝对路径

    默认情况下在servlet中的中文是显示不出来的,解决问题就是加resp.setContentType("text/html;charset=gbk"); 而且这句加的话必须写在P ...

  4. ffmpeg命令汇总

    1. 查看ffmpeg信息: ldd `which ffmpeg` ffmpeg -filters ffmpeg -h filter=drawtext man ffmpeg ffmpeg --help ...

  5. Android 编程 高德地图 (实现显示地图以及定位功能)

    本文参考文章: http://www.apkbus.com/blog-904057-63610.html 本人实现的 定位代码:(具体配置省略,可见参考文章) package com.example. ...

  6. Git详解之八 Git与其他系统

    以下内容转载自:http://www.open-open.com/lib/view/open1328070454218.html Git 与其他系统 世界不是完美的.大多数时候,将所有接触到的项目全部 ...

  7. hiredis处理zscan和hscan的reply

    zscan的返回值可以看做是一个二维数组,第一维包含两个元素:string类型的游标cursor和集合元素数组:第二维即集合元素数组,这个数组交替存放着集合元素和score,元素和score也都是st ...

  8. >=< 在set和dict中的不同

    两个dict比较的算法是,长度>键>值,由于dict无序,所以比较的时候会自动将键对齐比较,我们不用担心这个. >>> d1 = dict(x=1, y=2) >& ...

  9. 封装 一下 php sql 的存储语句

    function get_insert_sql($obj){ $str1 =""; $str2 =""; foreach($obj as $key => ...

  10. NSLayoutConstraint 布局,配合简单的动画效果

    demo地址 :链接: http://pan.baidu.com/s/1c00ipDQ 密码: mi4c 1 @interface ViewController () @property (nonat ...