You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言如何实现按指定时间间隔定时向Redis存储数据

实现方案

你需要的是固定时间点触发的定时任务,Golang生态有两种常用的实现方式,都可以匹配你的需求:


方法1:使用第三方定时任务库cron

这是Go项目最常用的定时任务方案,原生支持cron表达式,可以直接匹配你要的4个整点执行规则,无需自己计算时间差。

  • 第一步安装依赖:
    go get github.com/robfig/cron/v3
  • 完整示例代码:
package main

import (
	"context"
	"github.com/go-redis/redis/v8"
	"github.com/robfig/cron/v3"
	"time"
)

var ctx = context.Background()
var rdb *redis.Client

// 初始化Redis连接,替换为你自己的配置
func init() {
	rdb = redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	})
}

// Redis写入逻辑,和你现有代码逻辑完全兼容
func writeRedis() {
	key := "your_custom_key"
	data := []byte("要写入的业务数据")
	// 过期时间设6小时刚好匹配下一次执行间隔
	err := rdb.Set(ctx, key, data, 6*time.Hour).Err()
	if err != nil {
		// 自行补充错误处理逻辑,比如打印日志、告警
		println("Redis写入失败:", err.Error())
	}
}

func main() {
	// 初始化支持秒级解析的cron实例
	c := cron.New(cron.WithSeconds())
	// cron表达式规则:秒 分 时 日 月 周,此处配置为每天0、6、12、18点整执行
	_, err := c.AddFunc("0 0 0,6,12,18 * * *", writeRedis)
	if err != nil {
		panic("定时任务注册失败:" + err.Error())
	}
	// 启动定时任务
	c.Start()
	// 阻塞主协程保持服务常驻,可替换为你自己的其他常驻逻辑
	select {}
}

方法2:原生Go实现,无需第三方依赖

如果你不想引入额外依赖,可以自己计算当前时间到下一个执行点的等待间隔,用time.After实现定时触发。

package main

import (
	"context"
	"github.com/go-redis/redis/v8"
	"time"
)

var ctx = context.Background()
var rdb *redis.Client

func init() {
	rdb = redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	})
}

func writeRedis() {
	key := "your_custom_key"
	data := []byte("要写入的业务数据")
	err := rdb.Set(ctx, key, data, 6*time.Hour).Err()
	if err != nil {
		println("Redis写入失败:", err.Error())
	}
}

// 计算距离下一个执行整点的等待时长
func getNextWaitDuration() time.Duration {
	now := time.Now()
	// 定义所有执行时间的小时数
	executeHours := []int{0, 6, 12, 18}
	for _, hour := range executeHours {
		executeTime := time.Date(now.Year(), now.Month(), now.Day(), hour, 0, 0, 0, now.Location())
		if executeTime.After(now) {
			return executeTime.Sub(now)
		}
	}
	// 若今日所有执行点已过,计算到次日0点的等待时长
	nextDay := now.AddDate(0, 0, 1)
	firstExecuteTime := time.Date(nextDay.Year(), nextDay.Month(), nextDay.Day(), 0, 0, 0, 0, now.Location())
	return firstExecuteTime.Sub(now)
}

func main() {
	// 若启动时不需要立即执行一次,可删掉这行代码
	writeRedis()
	// 循环等待触发
	for {
		waitDur := getNextWaitDuration()
		<-time.After(waitDur)
		writeRedis()
	}
}

注意事项

  • 两种方案都需要服务常驻运行,服务重启后会自动计算下一次执行时间,不会出现逻辑错乱
  • 如果是多实例部署,建议在写入逻辑前加Redis分布式锁(用SETNX实现),避免多个实例同时重复写入
  • 你原有设置的6小时过期时间和执行间隔完全匹配,下一次写入会覆盖旧值,就算旧值过期也会立刻有新值写入,逻辑是通顺的

内容的提问来源于stack exchange,提问作者Md. Sakhawath Hossain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 17:45:02