package main

import (
"errors"
"flag"
"fmt"
log "github.com/cihub/seelog"
"github.com/garyburd/redigo/redis"
"github.com/robfig/cron"
"runtime"
"strings"
"sync"
"time"
)

var ch chan int = make(chan int)

//声明一些全局变量
var (
pool *redis.Pool
redisServer = flag.String("h", "10.100.68.50:6379", "")
// redisServer = flag.String("h", "pre-mds-sa.bhptzj.0001.sae1.cache.amazonaws.com:6379", "")
redisPassword = flag.String("p", "", "")
redisDbName = flag.String("db", "1", "")
)

/**
* [timerLog description]
* @param {[type]} logFileName string [description]
* @param {[type]} logLevel string [Warning Debug Error Info]
* @param {[type]} logContent string [description]
* @return {[type]} [description]
*/
func timerLog(logLevel string, logContent string) {
config := `
<seelog>
<outputs formatid="testSeeLog">
<filter levels="debug,error,info">
<file path="./error.log" />
</filter>
</outputs>
<formats>
<format id="testSeeLog" format="%Date/%Time [%LEV] %Msg%n"/>
</formats>
</seelog>
`
defer log.Flush()
logger, _ := log.LoggerFromConfigAsBytes([]byte(config))
log.ReplaceLogger(logger)
if logLevel == "error" {
log.Error(logContent)
} else if logLevel == "debug" {
log.Error(logContent)
} else {
log.Info(logContent)
}

}

/**
* 初始化一个pool
*/
func newPool(server, password string) *redis.Pool {
return &redis.Pool{
MaxIdle: 3,
MaxActive: 5,
IdleTimeout: 240 * time.Second,
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", server)
if err != nil {
fmt.Println("conn error:%s",err.Error())
timerLog("error", server+" conn error :"+err.Error())
return nil, err
}
if password != "" {
if _, err := c.Do("AUTH", password); err != nil {
c.Close()
fmt.Println("pass auth error :%s",err.Error())
timerLog("error", server+" pass auth error :"+err.Error())
return nil, err
}
}
if _, err := c.Do("SELECT", *redisDbName); err != nil {
fmt.Println("db exists error :%s",err.Error())
timerLog("error", server+" db exists error :"+err.Error())
c.Close()
return nil, err
}
return c, err
},
TestOnBorrow: func(c redis.Conn, t time.Time) error {
if time.Since(t) < time.Minute {
return nil
}
_, err := c.Do("PING")
return err
},
}
}

var ErrValueFormatError = errors.New("bucket: value format is error,may be topic,id")
var ErrValueTypeError = errors.New("bucket: value type is error,may be number")
var lock sync.Mutex

func timerProcess(key string) (string, error) {
lock.Lock()
pool = newPool(*redisServer, *redisPassword)
conn := pool.Get()
defer func() {
pool.Close()
conn.Close()
lock.Unlock()
}()
// conn.Do("select",*redisDbName)
t := time.Now().Unix()
rs, errGet := redis.Values(conn.Do("ZREVRANGEBYSCORE", key, t, 0))
if errGet != nil {
timerLog("error", key+":"+errGet.Error())
return key, errGet
}
for _, v := range rs {
value := string(v.([]byte))
topicAndId := strings.Split(value, ",")
var topic string
var queueId string
if len(topicAndId) == 2 {
topic = topicAndId[0]
queueId = topicAndId[1]
_, errSet := conn.Do("rpush", topic, queueId)
if errSet != nil {
timerLog("error", key+"-"+value+":"+errSet.Error())
} else {
_, errDel := conn.Do("zrem", key, value)
if errDel != nil {
timerLog("error", key+"-"+value+":"+errDel.Error())
}
}

} else {
timerLog("error", key+"-"+value+":"+ErrValueFormatError.Error())
}
}
ch <- 1
return "success", nil
}

var dbLock sync.Mutex

func main() {
flag.Parse()
// fmt.Println("begin")
runtime.GOMAXPROCS(runtime.NumCPU())
/**
Seconds | Yes | 0-59 | * / , -
Minutes | Yes | 0-59 | * / , -
Hours | Yes | 0-23 | * / , -
Day of month | Yes | 1-31 | * / , - ?
Month | Yes | 1-12 or JAN-DEC | * / , -
Day of week | Yes | 0-6 or SUN-SAT | * / , - ?
**/
c := cron.New()
spec := "*/1 * * * * *"
c.AddFunc(spec, func() {
dbLock.Lock()
pool = newPool(*redisServer, *redisPassword)
conn := pool.Get()
defer func() {
pool.Close()
conn.Close()
dbLock.Unlock()
}()
// conn.Do("SELECT",*redisDbName)
keys, errGet := redis.Values(conn.Do("keys", "DELAY_BUCKET_*"))
// fmt.Print(keys)
if errGet != nil {
timerLog("error", "get keys error:"+errGet.Error())
panic("get keys error:" + errGet.Error())
c.Stop()
}

for _, k := range keys {
key := string(k.([]byte))
// fmt.Println(key)
go timerProcess(key)
}

for i := 0; i < len(keys); i++ {
fmt.Println(i)
<-ch
}
})
c.Start()
select {}
}

go延时队列的更多相关文章

  1. 10 DelayQueue 延时队列类——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 www.cnblogs.com/oloroso/ 本文由乌合 ...

  2. 9 DelayQueueEntry 延时队列节点类——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...

  3. 8 延时队列相关类——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...

  4. 简析LIVE555中的延时队列

    http://www.cnblogs.com/nightwatcher/archive/2011/04/10/2011158.html 最近在看LIVE555的源码,感觉其中的延时队列写的不错,于是就 ...

  5. Redis学习笔记之延时队列

    目录 一.业务场景 二.Redis延时队列 一.业务场景 所谓延时队列就是延时的消息队列,下面说一下一些业务场景比较好理解 1.1 实践场景 订单支付失败,每隔一段时间提醒用户 用户并发量的情况,可以 ...

  6. 了解一下Redis队列【缓兵之计-延时队列】

    https://www.cnblogs.com/wt645631686/p/8454021.html 我们平时习惯于使用 Rabbitmq 和 Kafka 作为消息队列中间件,来给应用程序之间增加 异 ...

  7. Redis简单延时队列

    Redis实现简单延队列, 利用zset有序的数据结构, score设置为延时的时间戳. 实现思路: 1.使用命令 [zrangebyscore keyName socreMin socreMax] ...

  8. RabbitMQ学习之延时队列

    原帖参考:http://www.cnblogs.com/telwanggs/p/7124687.html?utm_source=itdadao&utm_medium=referral http ...

  9. RabbitMQ进阶使用-延时队列的配置(Spring Boot)

    依赖 MAVEN配置pom.xml <dependency> <groupId>org.springframework.boot</groupId> <art ...

  10. java实现rabbitMQ延时队列详解以及spring-rabbit整合教程

    在实际的业务中我们会遇见生产者产生的消息,不立即消费,而是延时一段时间在消费.RabbitMQ本身没有直接支持延迟队列功能,但是我们可以根据其特性Per-Queue Message TTL和 Dead ...

随机推荐

  1. ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails ()

    centos7.5 删除表空间文件失败 问题: mysql> alter table country discard tablespace; ERROR 1451 (23000): Cannot ...

  2. Bytom Java版本离线签名

    比原项目仓库: Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom tx_s ...

  3. CSS【04】:CSS组合选择器

    组合选择器 群组(并集)选择器 作用:给所有选择器选中的标签设置属性,可以同时控制多个选择器 格式: 选择器1, 选择器2 { 属性: 值; } 注意点: 必须使用,来连接 选择器可以使用标签名称.i ...

  4. 【Visual Studio 扩展工具】如何在ComponentOne的DataTree中实现RightToLeft布局

    概述 C1FlexGrid提供了创建轮廓树的功能,其中可以显示缩进结构,每个节点行旁边都有折叠/展开图标. 然后,用户可以展开和折叠轮廓以查看所需的细节级别. 为此,C1FlexGrid允许您使用其T ...

  5. Java中的CAS实现原理

    一.什么是CAS? 在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令. 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将该内存位置的内容修改为新 ...

  6. Vue:(五)axios

    Axios是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中.axios主要是用于向后台发起请求的,还有在请求中做更多可控功能.官方不再维护vue-resource,推 ...

  7. 非递归遍历N-ary树Java实现

    2019-03-25 14:10:51 非递归遍历二叉树的Java版本实现之前已经进行了总结,这次做的是非递归遍历多叉树的Java版本实现. 在非递归遍历二叉树的问题中我个人比较推荐的是使用双whil ...

  8. BFS 路径记录

    有一迷宫 N*M,要求输出可通行的最短路径. 可以先倒着 BFS 一遍迷宫,这样 dis[] 数组储存的就是各点到迷宫终点的最短距离. 然后再从起点开始 BFS 一遍 dis[] ,只要满足 dis[ ...

  9. Android 回调函数的理解,实用简单(回调函数其实是为传递数据)

    作者: 夏至,欢饮转载,也请保留这段申明 http://blog.csdn.net/u011418943/article/details/60139910 一般我们在不同的应用传递数据,比较方便的是用 ...

  10. 『计算机视觉』mini深度学习框架实现

    一.项目简介 手动实现mini深度学习框架,主要精力不放在运算优化上,仅体会原理. 地址见:miniDeepFrame 相关博客 『TensorFlow』卷积层.池化层详解 『科学计算』全连接层.均方 ...