背景
在业务开发过程中,你可能会碰到有任务形式的场景。比如Client请求Proxy GateWay(同时后端有若干机器), 要求执行某个(执行时间不定)的任务。如何去保证任务被执行一次。或者你的第一反应是,根据请求参数Hash取模似的统一请求只打到特定机器,但是如上场景明显不能做到,因为Proxy不受你控制。下面提供两种可行,简单的方式。a. MySQL行锁(FOR UPDATE)
b. Redis分布式锁
c. 当然你也可以使用MQ这种重量级应用
d. …..(方法很多,选择合适的)思考
如果并发不打,使用DB锁,也是特别方便,但是碰到有一定并发的场景,流量自然直接穿透到后端,对DB造成一定压力。所以这里详细介绍下使用Redis锁的一种实现方式,当然值得注意的是,如果你的任务时间不定长,你需要去reset过期时间,防止任务还在,但是锁释放了。
下面,提供一个简版的Redis锁,原因是厂里目前只有一主多从并且根据Key哈希取模形式的Slave,所以无法使用redlock-rb算法来实现更加可靠的锁。当然了,如果业务能够容忍,下面这种实现,也是没什么问题。实现(Show me your code)
// NOTICE
//
// Mi redis集群基于Key分片,故在Key确定情况下可认为集群为一主多从模式
// 此Redis锁有一个前提:即 Redis单点的、保证永不宕机(https://github.com/antirez/redis-doc/blob/master/topics/distlock.md)
package utils
import (
"errors"
"fmt"
"sync"
"time"
xredis "path/to/redis"
)
var (
//ErrLockerExisted 重复加锁
ErrLockerExisted = errors.New("Locker Existed")