zoukankan      html  css  js  c++  java
  • 计时器 海量定时/延迟任务

    6.11 计时器 | Go 语言原本 https://golang.design/under-the-hood/zh-cn/part2runtime/ch06sched/timer/

    https://mp.weixin.qq.com/s/tkm9nYcyUxE2vUbplSO-pA

    Go-Zero如何应对海量定时/延迟任务
    原创 hxl@好未来 GoCN 2020-10-10
    一个系统中存在着大量的调度任务,同时调度任务存在时间的滞后性,而大量的调度任务如果每一个都使用自己的调度器来管理任务的生命周期的话,浪费 cpu 的资源而且很低效。

    本文来介绍 go-zero 中 延迟操作,它可能让开发者调度多个任务时,只需关注具体的业务执行函数和执行时间「立即或者延迟」。而 延迟操作,通常可以采用两个方案:

    Timer:定时器维护一个优先队列,到时间点执行,然后把需要执行的 task 存储在 map 中

    collection 中的 timingWheel ,维护一个存放任务组的数组,每一个槽都维护一个存储 task 的双向链表。开始执行时,计时器每隔指定时间执行一个槽里面的 tasks。

    方案 2 把维护 task 从 优先队列 O(nlog(n)) 降到 双向链表 O(1),而执行 task 也只要轮询一个时间点的 tasks O(N),不需要像优先队列,放入和删除元素 O(nlog(n))。

    我们先看看 go-zero 中自己对 timingWheel 的使用 :

    // 2021/3/29 22:17 Shawn
    package main

    import (
    "fmt"
    "time"
    )

    func NOW() time.Time {
    return time.Now()
    }
    func t() int {
    fmt.Println("in-", NOW())
    go func() {
    fmt.Println("1-NewTimer", NOW())
    i := 60
    s := time.Duration(i) * time.Second
    timer := time.NewTimer(s)
    <-timer.C
    fmt.Println("2-NewTimer", NOW())

    }()
    fmt.Println("leave", NOW())
    return 123
    }
    func main() {
    i := t()
    fmt.Println("i=", i, NOW())
    for {

    }
    }

    in- 2021-07-09 16:18:09.3988014 +0800 CST m=+0.003173901
    leave 2021-07-09 16:18:09.4144284 +0800 CST m=+0.018800901
    i= 123 2021-07-09 16:18:09.4144284 +0800 CST m=+0.018800901
    1-NewTimer 2021-07-09 16:18:09.4144284 +0800 CST m=+0.018800901
    2-NewTimer 2021-07-09 16:19:09.4144658 +0800 CST m=+60.018838301

    package main

    import (
    "fmt"
    "time"
    )

    func NOW() time.Time {
    return time.Now()
    }
    func t() int {
    fmt.Println("in-", NOW())
    go func() {
    fmt.Println("1-NewTimer", NOW())
    i := 60
    s := time.Duration(i) * time.Second
    timer := time.NewTimer(s)
    <-timer.C
    fmt.Println("2-NewTimer", NOW())

    }()
    fmt.Println("leave", NOW())
    return 123
    }
    func main() {
    i := t()
    fmt.Println("i=", i, NOW())
    //for {
    //
    //}
    }

    in- 2021-07-09 16:22:21.4064411 +0800 CST m=+0.003581001
    leave 2021-07-09 16:22:21.4209835 +0800 CST m=+0.018123401
    i= 123 2021-07-09 16:22:21.4209835 +0800 CST m=+0.018123401

    import (
    "fmt"
    "time"
    )

    func NOW() time.Time {
    return time.Now()
    }
    func t() int {
    i := 123
    fmt.Println("in-", NOW())
    go func() {
    fmt.Println("1-NewTimer", NOW())
    s := time.Duration(60) * time.Second
    timer := time.NewTimer(s)
    <-timer.C
    fmt.Println("2-NewTimer", NOW())
    }()
    fmt.Println("leave", NOW())
    defer func() {
    fmt.Println("defer", NOW())
    i = 456
    }()
    return i
    }
    func t1() (i int) {
    i = 123
    fmt.Println("in-", NOW())
    go func() {
    fmt.Println("1-NewTimer", NOW())
    s := time.Duration(60) * time.Second
    timer := time.NewTimer(s)
    <-timer.C
    fmt.Println("2-NewTimer", NOW())
    i = 789
    }()
    defer func() {
    fmt.Println("defer", NOW())
    i = 456
    }()
    fmt.Println("leave", NOW())
    return
    }
    func main() {
    i := t1()
    fmt.Println("i=", i, NOW())
    for {

    }
    }
  • 相关阅读:
    [SQL] 外卖系统数据库设计
    [PHP] 遗传算法求函数最大值一般实现
    PHP CURL根据详细地址获取腾讯地图经纬度
    PHP 递归读取无限级分类
    PHP 仿网易云的评论盖楼
    JavaScript清除空格、换行,把双引号转换成单引号
    百度地图小Demo---获取当前地址以及拖拽显示地址
    基于Modbus的C#串口调试开发
    二叉树的中序遍历
    二叉树的前序遍历
  • 原文地址:https://www.cnblogs.com/rsapaper/p/14884634.html
Copyright © 2011-2022 走看看