• 计时器 海量定时/延迟任务


    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 {

    }
    }
  • 相关阅读:
    剑指offer-二叉树的深度
    剑指offer-二叉树中和为某一值的路径
    剑指offer-数组中只出现一次的数字
    剑指offer-反转单词顺序列
    剑指offer-数字在排序数组中出现的次数
    剑指offer-第一个只出现一次的字符
    剑指offer-连续子数组的最大和
    剑指offer-数组中的逆序对
    CSS3滚动条美化,CSS3滚动条皮肤
    mouseover事件与mouseenter事件的区别
  • 原文地址:https://www.cnblogs.com/rsapaper/p/14884634.html
Copyright © 2020-2023  润新知