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
相关产品推荐
相关产品推荐

