美文网首页
golang实现定时任务调度

golang实现定时任务调度

作者: yushu_bd | 来源:发表于2019-01-14 17:34 被阅读0次

在定时任务中,有这样一个场景,定时给某些用户发送消息,或者定时给某些数据进行对账,而这些场景有一个要求是,下次处理是上次处理的定时间隔(比如下次的1分钟)等,这样就会出现,每秒处理的数据和用户是不一样的。比如13:13:13 对数据A处理失败了(处理失败常见,非常规意义的失败),那下一分钟接着处理A(13:14:13),13:13:14 对数据B处理失败了那下一分钟接着处理B(13:14:14)。这样就会发现,每分钟的60秒都在处理一批批数据。类似于时间轮一样的轮循。

image.png

当然,也可以使用消息队列的延时队列,但这种情况会造成,一个消息的堆积,而且无法处理这种清空,比如A,B的任务相差一分钟,那在A的2分钟后是发送A的第2次,而B是第1次,这两次是同时发送的,消息队列比较难处理这种情况,同时对于消息的标记也比较麻烦。

方案:可以使用go里的定时器,每秒触发一次任务,对任务进行轮循处理,简单的demo如下:(这里忽略了任务的进入,具体可以使用kafka结合到达的时间点来标记队列的轮片)

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)

type Task struct {
    msg string   //任务的内容, 具体可以是一个复杂的结构体对象
    pri int   // 任务的优先级,在对同一个bucket的数据,可以按照优先级来处理
    idx int   //  bucket 的标识
    status bool // 任务标识,标识任务是否执行成功,是否需要删除
}

func (t *Task) runTask() {  //简单的执行任务
    fmt.Println("run message", t.msg)
    t.status = true
}

var taskList = map[int][]Task{}

func sendTask(idx int) {
    msg := fmt.Sprintf("task message %d", idx)
    pri := idx / 60
    idx = idx % 60

    task := Task{
        msg,
        pri,
        idx,
            false,
    }
    taskList[idx] = append(taskList[idx], task)
}

/**
 * 假设 i是任务的id号,表示有一个150个任务要进如队列审核
 */
func initTask() {
    for i := 0; i < 150; i++ {
        sendTask(i)
    }
}

var ticker = time.NewTicker(1 * time.Second)
var cc = 0 //轮片指针

func main() {
    c := make(chan os.Signal)
    status:=true
    signal.Notify(c,
        syscall.SIGKILL,
        syscall.SIGHUP,
        syscall.SIGINT,
        syscall.SIGQUIT,
        os.Interrupt,
        os.Kill,
    )
    initTask()
    go func() {
        for {
            select {
            case <-ticker.C:
                for _, t := range taskList[cc] {
                    if t.status == false {
                        t.runTask()
                    }
                }
                cc += 1
                cc = cc%60  //循环轮询
            case <-c: //监听 信号
                ticker.Stop()
                fmt.Println("kill task")
                status = false
                break

            }
        }
    }()
    for {// 常驻
        time.Sleep(1*time.Second)
        if status == false {
            break
        }
    }
}

如有不对的地方,请指正

相关文章

  • golang实现定时任务调度

    在定时任务中,有这样一个场景,定时给某些用户发送消息,或者定时给某些数据进行对账,而这些场景有一个要求是,下次处理...

  • Golang实现简单爬虫框架(5)——项目重构与数据存储

    前言 在上一篇文章《Golang实现简单爬虫框架(4)——队列实现并发任务调度》中,我们使用用队列实现了任务调度,...

  • 深入理解scheduledthreadpoolexecutor

    scheduledthreadpool是JDK自带的一个定时调度任务的实现,通过它可以实现定时的循环调度,最近在看...

  • Java定时任务调度工具详解

    本篇内容:什么是定时任务调度?Java定时任务调度工具详解之 Timer篇Java定时任务调度工具详解之 Quar...

  • 分布式任务调度-xxl-job

    前言 为什么要使用分布式任务调度框架? 使用原因和解决问题是为了解决: 实现定时调度任务 将定时任务分布式部署 提...

  • 学习Linux2

    linux 学习2 定时任务管理 crond 任务调度 crontab 进行 定时任务的设置 概述任务调度:是指系...

  • Spring Boot定时任务应用实践

    Spring Boot中实现定时任务功能,可以通过Spring自带的定时任务调度,也可以通过集成经典开源组件Qua...

  • 定时任务调度之Timer

    定时任务调度之Timer 前言 定时任务调度,有两个比较重要的概念,一个是定时,一个是调度,所谓的定时调度,指的是...

  • 尚硅谷大数据技术之Oozie

    4.4 案例四:Oozie定时任务/循环任务目标:Coordinator周期性调度任务分步实现:1) 配置Lin...

  • quartz框架(一)-入门使用

    什么是quartz? quartz是一个开源的任务调度框架,它可以帮助我们实现任务的定时调度,任务的持久化,支持故...

网友评论

      本文标题:golang实现定时任务调度

      本文链接:https://www.haomeiwen.com/subject/sbaorqtx.html