1 、语言自带函数方法 比如jdk的DelayQueue
这里就不做讨论了,无法做持久化
2、定时任务扫表。
效力低,增大数据库压力,这里也不讨论
3、rabbitmq 死信队列,不过要下插件,否者他是按顺序的,会阻塞。
4、 Redis sorted set
我们用的这种:
- 先把未支付订单存在redis的zset中
- 支付成功的,去redis利查,然后更改订单状态
- 30分钟未支付,通过判断zset中的key,可以判断订单是佛有超过30分钟,另外做处理
import (
"github.com/gomodule/redigo/redis"
"time"
)
// InsertOrder
// @description: 插入订单
// @return error
// @2022-11-09 09:44:20
const TimeInterval int64 = 1800
func (rs *RedisUtil) InsertOrder(OrderUuid string) error {
// 订单生成半个钟
currentNSecond := time.Now().Unix()
_, err := rs.client.Do("ZADD", "order", "INCR", currentNSecond+TimeInterval, OrderUuid)
if err != nil {
return err
}
return nil
}
// Unpaid
// @description: 查询半个钟未支付的, 查出来再删除
// @return error value 是 sco
// @2022-11-09 09:45:35
func (rs *RedisUtil) Unpaid() error {
var e error
var count interface{}
count, e = rs.client.Do("zcount", "order", 0, time.Now().Unix())
if e != nil {
return e
}
midCount := count.(int64)
orderMap, err := redis.StringMap(rs.client.Do("ZRANGE", "order", 0, midCount, "withscores"))
if err != nil {
return err
}
for key := range orderMap {
//删除redis 里面的数据
// todo 更改订单状态
_, _ = rs.client.Do("zrem", "order", key)
}
return nil
}
// PaymentCompleted
// @description: 支付完成,删除
// @return error
// @2022-11-09 09:46:05
func (rs *RedisUtil) PaymentCompleted(OrderUuid string) error {
//1、首先查出来有没有这个订单2、更改订单状态,3、删除redis数据
val, err := rs.client.Do("zrank", "order", OrderUuid)
if err != nil {
return err
}
if val != nil {
// todo 更改订单状态
_, err = rs.client.Do("zrem", "order", OrderUuid)
if err != nil {
return err
}
}
return nil
}
5、 Redis 过期回调
无Ack 会延迟
6、时间轮
会有时间粒度问题,如果对粒度要求不大,可以使用