golang实现延迟队列(delay queue)

golang实现延迟队列

1 延迟队列:邮件提醒、订单自动取消

延迟队列:处理需要在未来某个特定时间执行的任务。这些任务被添加到队列中,并且指定了一个执行时间,只有达到指定的时间点时才能从队列中取出并执行。
应用场景:

  • 邮件提醒
  • 订单自动取消(超过多少时间未支付,就取消订单)
  • 对超时任务的处理等

由于任务的执行是在未来的某个时间点,因此这些任务不会立即执行,而是存储在队列中,直到它的预定执行时间才会被执行。

2 实现

2.1 simple简单版:go自带的time包实现

思路:

  1. 定义Task结构体,包含
  • ExecuteTime time.Time
  • Job func()
  1. 定义DelayQueue
  • TaskQueue []Task
  • func AddTask
  • func RemoveTask
  • ExecuteTask

这种方案存在的问题:

Go程序重启时,存储在slice中的延迟处理任务将全部丢失

完整代码:

package mainimport ("fmt""time"
)/*
基于go实现延迟队列
*/
type Task struct {ExecuteTime time.TimeJob         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 enqueued.Tasks = d.Tasks[1:]
}func (d *DelayQueue) ExecuteTask() {for len(d.Tasks) > 0 {//dequeue a taskcurrentTask := d.Tasks[0]if time.Now().Before(currentTask.ExecuteTime) {//if the task execution time is not up, waittime.Sleep(currentTask.ExecuteTime.Sub(time.Now()))}//execute the taskcurrentTask.Job()//remove task who has been executedd.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的数据丢失,我们可以将任务持久化到redis中。

思路:

  1. 初始化redis连接
  2. 延迟队列采用redis的zset(有序集合)实现

前置准备:

# 安装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 mainimport ("fmt""github.com/go-redis/redis"log "github.com/ziyifast/log""time"
)/*
基于redis zset实现延迟队列
*/
var redisdb *redis.Client
var DelayQueueKey = "delay-queue"func initClient() (err error) {redisdb = redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "", // not set passwordDB:       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())//执行队列中的任务getAndExecuteTask()
}// executeTime为unix时间戳,作为zset中的score。允许redis按照task应该执行时间来进行排序
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并执行
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}//处理任务for _, task := range tasks {fmt.Println("Execute task: ", task)//执行完任务之后用 ZREM 移除该任务redisdb.ZRem(DelayQueueKey, task)}time.Sleep(time.Second * 1)}
}

效果:

redis一直从延迟队列中取数据,如果处理完一批则睡眠1s

  • 具体根据大家的业务调整,此处主要介绍思路

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2799550.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

[ Python+OpenCV+Mediapipe ] 实现对象识别

一、写在前面 本文所用例子为个人学习的小结,如有不足之处请各位多多海涵,欢迎小伙伴一起学习进步,如果想法可在评论区指出,我会尽快回复您,不胜感激! 所公布代码或截图均为运行成功后展示。 二、本文内容…

PEARL: 一个轻量的计算短文本相似度的表示模型

| 💻 [code] | 💾 [data] | 🤗 PEARL-small | 🤗 PEARL-base | 论文 如何计算短文本相似度是一个重要的任务,它发生在各种场景中: 字符串匹配(string matching)。我们计算两个字符…

AWS安全组是什么?有什么用?

最近看到小伙伴在问,AWS安全组是什么?有什么用?今天我们大家就来简单聊聊,仅供参考哦! AWS安全组是什么?有什么用? 【回答】:AWS安全组是一种虚拟防火墙,用于控制进出…

贝叶斯统计——入门级笔记

绪论 1.1 引言 全概率公式 贝叶斯公式 三种信息 总体信息 当把样本视为随机变量时,它有概率分布,称为总体分布. 如果我们已经知道总体的分布形式这就给了我们一种信息,称为总体信息 样本信息 从总体中抽取的样本所提供的信息 先…

【操作系统】

计算机操作系统 计算机是如何让用户得到好的体验什么是操作系统(OS)操作系统如何管理 计算机是如何让用户得到好的体验 计算机系统是由计算机硬件和软件组成的。用户使用计算机,比如在文本文件填写内容,通过邮箱发送邮件&#xf…

opencv图像放缩与插值-resize函数

在OpenCV中,resize函数用于对图像进行尺寸调整(放大或缩小),这个过程中通常需要用到插值方法来计算新尺寸下图像像素的值。插值方法对于放缩的质量有着直接影响。 void resize(InputArray src, OutputArray dst, Size dsize, dou…

全流程点云机器学习(二)使用PaddlePaddle进行PointNet的机器学习训练和评估

前言 这不是高支模项目需要嘛,他们用传统算法切那个横杆竖杆流程复杂耗时很长,所以想能不能用机器学习完成这些工作,所以我就来整这个工作了。 基于上文的数据集切分 ,现在来对切分好的数据来进行正式的训练。 本系列文章所用的…

解决app中以webview的方式嵌入h5网页,h5网页加载不出来

问题描述:我的h5网页在web端和手机浏览器都能正常渲染展示,但是嵌入到客户的webview中,渲染加载不出来,仔细检查代码之后并没有任何代码错误和后台报错。抓耳挠腮查找两天之后发现,原因为整个h5网页的最外层高度设置成…

WordPress如何将后台右上角管理员头像去除并调整注销位置及启用注销确认功能?

WordPress后台默认情况下右上角可以看到管理员昵称和头像,将鼠标移动到该昵称上还会出现一个下拉菜单,点击下拉菜单中的“注销”无需我们再次确认就会自动退出。 现在我想将WordPress后台右上角的管理员头像和管理员昵称子菜单去除,并将“注销…

HDFS中常用的Shell命令 全面且详细

HDFS中常用的Shell命令目录 一、ls命令 二、mkdir 命令 三、put命令 四、get命令 五、mv命令 六、rm命令 七、cp命令 八、cat命令 前言 安装好hadoop环境之后,可以执行hdfs相关的shell命令对hdfs文件系统进行操作,比如文件的创建、删除、修改文…

【时事篇-05-02】20240221 2525元存17只货币基金的具体数目测算( itertools)

背景需求: 前文提到存10个货币基金,每个投150元,1500元,每天有1分钱利息,10个基金就有0.1元,比1500元投1只货币基金0.06元,的收益高一点。 【时事篇-05】20240112 150元存46只货币基金-CSDN博…

C++之new和delete表达式

目录 一、new表达式工作步骤 二、delete表达式工作步骤 三、operator new和operator delete函数的重载版本 ​编辑​编辑 四、要求一个类只能创建栈对象 五、要求一个类只能创建堆对象 一、new表达式工作步骤 使用new表达式时发生的三个步骤: 1. 调用名为opera…

第2.5章:StarRocks表设计--Colocation Join

目录 一、StarRocks数据划分 1.1 分区 1.2 分桶 二、Colocation Join实现原理 2.1 Colocate Join概述 2.2 Colocate Join实现原理 三、应用案例 注:本篇文章阐述的是StarRocks-3.2版本的Colocation Join 官网文章地址: Colocate Join | StarRoc…

政安晨:【示例演绎机器学习】(一)—— 剖析神经网络:学习核心的Keras API

打开这篇文章,相信您已经了解了TensorFlow的一些基础知识,可以用它从头开始实现一个简单模型。 如果您对这些概念还不是太清晰,可以浏览一下我这个栏目中的相关文章: 政安晨的机器学习笔记http://t.csdnimg.cn/DHcyL 尤其是其中…

npm run dev和npm run serve两个命令的区别

npm run dev和npm run serve两个命令的区别 前端开发过程中运行Vue项目的时候,有时候使用npm run serve命令可以启动项目,有时候却会报错;有时候使用npm run dev命令可以启动项目,有时候却也会报错。是什么原因造成这种情况呢&am…

HTML5-CSS3

一、HTML5的新特性 HTML5 的新增特性主要是针对于以前的不足,增加了一些新的标签、新的表单和新的表单属性等。 这些新特性都有兼容性问题,基本是 **IE9 以上版本的浏览器**才支持,如果不考虑兼容性问题,可以大量使用这些新特性…

Github代码仓库SSH配置流程

作者: Herman Ye Auromix 测试环境: Ubuntu20.04 更新日期: 2024/02/21 注1: Auromix 是一个机器人爱好者开源组织。 注2: 由于笔者水平有限,以下内容可能存在事实性错误。 相关背景 在为Github代码仓库配…

【LeetCode】升级打怪之路 Day 01:二分法

今日题目: 704. 二分查找35. 搜索插入位置34. 在排序数组中查找元素的第一个和最后一个位置 目录 今日总结Problem 1: 二分法LeetCode 704. 二分查找 【easy】LeetCode 35. 搜索插入位置 ⭐⭐⭐⭐⭐LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置 【medi…

探索Linux系统中HTTP隧道技术的原理与实践

在Linux的世界里,HTTP隧道技术就像是一个神秘的魔法师,它能让你的网络请求穿越重重障碍,安全地到达目的地。今天,我们就来一起探索这个魔法师的奥秘,看看它是如何在Linux系统中施展魔法的。 首先,我们要明…

pcd文件介绍

pcd文件介绍 一、PCD文件格式二、为什么要使用新的文件格式?三、PCD 版本四、文件格式头五、数据存储类型六、优于其他文件格式七、结果展示八、相关链接 一、PCD文件格式 本文档描述PCD(点云数据)文件格式,以及它在点云库(PCL)中的使用方式。 二、为什…