亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

golang實(shí)現(xiàn)延遲隊(duì)列(delay queue)的兩種實(shí)現(xiàn)

 更新時間:2025年05月25日 14:28:45   作者:NPE~  
本文主要介紹了golang實(shí)現(xiàn)延遲隊(duì)列(delay queue)的兩種實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1 延遲隊(duì)列:郵件提醒、訂單自動取消

延遲隊(duì)列:處理需要在未來某個特定時間執(zhí)行的任務(wù)。這些任務(wù)被添加到隊(duì)列中,并且指定了一個執(zhí)行時間,只有達(dá)到指定的時間點(diǎn)時才能從隊(duì)列中取出并執(zhí)行。
應(yīng)用場景:

  • 郵件提醒
  • 訂單自動取消(超過多少時間未支付,就取消訂單)
  • 對超時任務(wù)的處理等

由于任務(wù)的執(zhí)行是在未來的某個時間點(diǎn),因此這些任務(wù)不會立即執(zhí)行,而是存儲在隊(duì)列中,直到它的預(yù)定執(zhí)行時間才會被執(zhí)行。

2 實(shí)現(xiàn)

2.1 simple簡單版:go自帶的time包實(shí)現(xiàn)

思路:

定義Task結(jié)構(gòu)體,包含

  • ExecuteTime time.Time
  • Job func()

定義DelayQueue

  • TaskQueue []Task
  • func AddTask
  • func RemoveTask
  • ExecuteTask

這種方案存在的問題:

Go程序重啟時,存儲在slice中的延遲處理任務(wù)將全部丟失

完整代碼:

package main

import (
	"fmt"
	"time"
)

/*
基于go實(shí)現(xiàn)延遲隊(duì)列
*/
type Task struct {
	ExecuteTime time.Time
	Job         func()
}

type DelayQueue struct {
	Tasks []*Task
}

func (d *DelayQueue) AddTask(t *Task) {
	d.Tasks = append(d.Tasks, t)
}

func (d *DelayQueue) RemoveTask() {
	//FIFO: remove the first task to enqueue
	d.Tasks = d.Tasks[1:]
}

func (d *DelayQueue) ExecuteTask() {
	for len(d.Tasks) > 0 {
		//dequeue a task
		currentTask := d.Tasks[0]
		if time.Now().Before(currentTask.ExecuteTime) {
			//if the task execution time is not up, wait
			time.Sleep(currentTask.ExecuteTime.Sub(time.Now()))
		}
		//execute the task
		currentTask.Job()
		//remove task who has been executed
		d.RemoveTask()
	}

}

func main() {
	fmt.Println("start delayQueue")
	delayQueue := &DelayQueue{}
	firstTask := &Task{
		ExecuteTime: time.Now().Add(time.Second * 1),
		Job: func() {
			fmt.Println("executed task 1 after delay")
		},
	}
	delayQueue.AddTask(firstTask)
	secondTask := &Task{
		ExecuteTime: time.Now().Add(time.Second * 7),
		Job: func() {
			fmt.Println("executed task 2 after delay")
		},
	}
	delayQueue.AddTask(secondTask)
	delayQueue.ExecuteTask()
	fmt.Println("all tasks have been done!!!")
}

效果:

在這里插入圖片描述

2.2 complex持久版:go+redis

為了防止Go重啟后存儲到delayQueue的數(shù)據(jù)丟失,我們可以將任務(wù)持久化到redis中。

思路:

初始化redis連接

延遲隊(duì)列采用redis的zset(有序集合)實(shí)現(xiàn)

前置準(zhǔn)備:

# 安裝docker
yum install -y yum-utils
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
yum install docker
systemctl start docker

# docker搭建redis
mkdir -p /Users/ziyi2/docker-home/redis
docker run -d --name redis -v /Users/ziyi2/docker-home/redis:/data -p 6379:6379 redis

完整代碼:

package main

import (
	"fmt"
	"github.com/go-redis/redis"
	log "github.com/ziyifast/log"
	"time"
)

/*
基于redis zset實(shí)現(xiàn)延遲隊(duì)列
*/
var redisdb *redis.Client
var DelayQueueKey = "delay-queue"

func initClient() (err error) {
	redisdb = redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "", // not set password
		DB:       0,  //use default db
	})
	_, err = redisdb.Ping().Result()
	if err != nil {
		log.Errorf("%v", err)
		return err
	}
	return nil
}

func main() {
	err := initClient()
	if err != nil {
		log.Errorf("init redis client err: %v", err)
		return
	}
	addTaskToQueue("task1", time.Now().Add(time.Second*3).Unix())
	addTaskToQueue("task2", time.Now().Add(time.Second*8).Unix())
	//執(zhí)行隊(duì)列中的任務(wù)
	getAndExecuteTask()
}

// executeTime為unix時間戳,作為zset中的score。允許redis按照task應(yīng)該執(zhí)行時間來進(jìn)行排序
func addTaskToQueue(task string, executeTime int64) {
	err := redisdb.ZAdd(DelayQueueKey, redis.Z{
		Score:  float64(executeTime),
		Member: task,
	}).Err()
	if err != nil {
		panic(err)
	}
}

// 從redis中取一個task并執(zhí)行
func getAndExecuteTask() {
	for {
		tasks, err := redisdb.ZRangeByScore(DelayQueueKey, redis.ZRangeBy{
			Min:    "-inf",
			Max:    fmt.Sprintf("%d", time.Now().Unix()),
			Offset: 0,
			Count:  1,
		}).Result()
		if err != nil {
			time.Sleep(time.Second * 1)
			continue
		}
		//處理任務(wù)
		for _, task := range tasks {
			fmt.Println("Execute task: ", task)
			//執(zhí)行完任務(wù)之后用 ZREM 移除該任務(wù)
			redisdb.ZRem(DelayQueueKey, task)
		}
		time.Sleep(time.Second * 1)
	}
}

效果:

redis一直從延遲隊(duì)列中取數(shù)據(jù),如果處理完一批則睡眠1s

  • 具體根據(jù)大家的業(yè)務(wù)調(diào)整,此處主要介紹思路

在這里插入圖片描述

到此這篇關(guān)于golang實(shí)現(xiàn)延遲隊(duì)列(delay queue)的示例代碼的文章就介紹到這了,更多相關(guān)golang 延遲隊(duì)列(delay queue)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Golang并發(fā)控制之errgroup使用詳解

    Golang并發(fā)控制之errgroup使用詳解

    errgroup?是?Go?官方庫?x?中提供的一個非常實(shí)用的工具,用于并發(fā)執(zhí)行多個?goroutine,并且方便的處理錯誤,下面就跟隨小編一起來了解下的它的具體使用吧
    2024-11-11
  • Golang實(shí)現(xiàn)密碼加密的示例詳解

    Golang實(shí)現(xiàn)密碼加密的示例詳解

    數(shù)據(jù)庫在存儲密碼時,不能明文存儲,需要加密后存儲,而Golang中的加密算法有很多種,下面小編就來通過簡單的示例和大家簡單聊聊吧
    2023-07-07
  • golang使用sort接口實(shí)現(xiàn)排序示例

    golang使用sort接口實(shí)現(xiàn)排序示例

    這篇文章主要介紹了golang使用sort接口實(shí)現(xiàn)排序的方法,簡單分析了sort接口的功能并實(shí)例演示了基于sort接口的排序?qū)崿F(xiàn)方法,需要的朋友可以參考下
    2016-07-07
  • Go語言中的速率限流策略全面詳解

    Go語言中的速率限流策略全面詳解

    這篇文章主要為大家介紹了Go語言中的速率限流策略全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • golang下的viper包的簡單使用方式

    golang下的viper包的簡單使用方式

    這篇文章主要介紹了golang下的viper包的簡單使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • go mutex互斥鎖使用Lock和Unlock方法占有釋放資源

    go mutex互斥鎖使用Lock和Unlock方法占有釋放資源

    Go號稱是為了高并發(fā)而生的,在高并發(fā)場景下,勢必會涉及到對公共資源的競爭,當(dāng)對應(yīng)場景發(fā)生時,我們經(jīng)常會使用 mutex 的 Lock() 和 Unlock() 方法來占有或釋放資源,雖然調(diào)用簡單,但 mutex 的內(nèi)部卻涉及挺多的,本文來好好研究一下
    2023-09-09
  • 淺析Go語言中的Range關(guān)鍵字

    淺析Go語言中的Range關(guān)鍵字

    Range是go語言中很獨(dú)特的一個關(guān)鍵詞,也相當(dāng)好用。下面就跟著小編來再聊聊這個Range關(guān)鍵字,有需要的朋友們可以參考借鑒。
    2016-09-09
  • go MethodByName()不能獲取私有方法的解決

    go MethodByName()不能獲取私有方法的解決

    本文主要介紹了go MethodByName()不能獲取私有方法的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • Go語言中內(nèi)存管理逃逸分析詳解

    Go語言中內(nèi)存管理逃逸分析詳解

    所謂的逃逸分析(Escape?analysis)是指由編譯器決定內(nèi)存分配的位置嗎不需要程序員指定。本文就來和大家簡單分析一下Go語言中內(nèi)存管理逃逸吧
    2023-03-03
  • Sublime Text3安裝Go語言相關(guān)插件gosublime時搜不到gosublime的解決方法

    Sublime Text3安裝Go語言相關(guān)插件gosublime時搜不到gosublime的解決方法

    本文主要介紹了Sublime Text3安裝Go語言相關(guān)插件gosublime時搜不到gosublime的解決方法,具有一定的參考價值,感興趣的可以了解一下
    2022-01-01

最新評論