作者 yangfu

redis trylock

@@ -2,9 +2,10 @@ package redis @@ -2,9 +2,10 @@ package redis
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 - "github.com/astaxie/beego"  
6 "github.com/gomodule/redigo/redis" 5 "github.com/gomodule/redigo/redis"
  6 + "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
7 "sync" 7 "sync"
  8 + "time"
8 ) 9 )
9 10
10 type Mutex struct { 11 type Mutex struct {
@@ -14,66 +15,91 @@ type Mutex struct { @@ -14,66 +15,91 @@ type Mutex struct {
14 lock bool 15 lock bool
15 closeOnce sync.Once 16 closeOnce sync.Once
16 } 17 }
  18 +
17 //NewMutex create new mutex 19 //NewMutex create new mutex
18 -func NewMutex(source string)*Mutex{ 20 +func NewMutex(source string) *Mutex {
19 return &Mutex{ 21 return &Mutex{
20 - resource:source,  
21 - lock:false,  
22 - timeOut:SECOND*5,//未执行完,已经超时 超时时间设大 22 + resource: source,
  23 + lock: false,
  24 + timeOut: SECOND * 5, //未执行完,已经超时 超时时间设大
23 } 25 }
24 } 26 }
25 -func (l *Mutex)Key()string{  
26 - return fmt.Sprintf("reidslock:%s",l.resource) 27 +func (l *Mutex) Key() string {
  28 + return fmt.Sprintf("reidslock:%s", l.resource)
27 } 29 }
28 -func(l *Mutex)Conn()redis.Conn{ 30 +func (l *Mutex) Conn() redis.Conn {
29 return l.conn 31 return l.conn
30 } 32 }
  33 +
31 //设置超时 34 //设置超时
32 -func (l *Mutex)TimeOut(t int64)*Mutex{ 35 +func (l *Mutex) TimeOut(t int64) *Mutex {
33 l.timeOut = t 36 l.timeOut = t
34 return l 37 return l
35 } 38 }
  39 +
36 //加锁 40 //加锁
37 //true:加锁成功 false:加锁失败 41 //true:加锁成功 false:加锁失败
38 -func (l *Mutex)Lock()( bool){  
39 - defer func(){  
40 - if !l.lock{  
41 - beego.Warn("on locked:",l.Key()) 42 +func (l *Mutex) Lock() bool {
  43 + defer func() {
  44 + if !l.lock {
  45 + log.Warn("on locked:", l.Key())
42 l.Close() 46 l.Close()
43 } 47 }
44 }() 48 }()
45 - if l.lock{ 49 + if l.lock {
46 return l.lock 50 return l.lock
47 } 51 }
48 - l.conn =redisPool.Get()  
49 - resourceKey :=l.Key()  
50 - if result, err := l.conn.Do("SET", resourceKey,l.resource,"NX","EX", l.timeOut); err != nil || result==nil{ 52 + l.conn = redisPool.Get()
  53 + resourceKey := l.Key()
  54 + if result, err := l.conn.Do("SET", resourceKey, l.resource, "NX", "EX", l.timeOut); err != nil || result == nil {
51 return l.lock 55 return l.lock
52 - }else{  
53 - ok :=result.(string)  
54 - if ok !="OK"{ 56 + } else {
  57 + ok := result.(string)
  58 + if ok != "OK" {
55 return l.lock 59 return l.lock
56 } 60 }
57 } 61 }
58 l.lock = true 62 l.lock = true
59 return l.lock 63 return l.lock
60 } 64 }
  65 +
  66 +//try get lock util time out
  67 +func (l *Mutex) TryLock(timeOut int) bool {
  68 + log.Info("try lock:", l.Key())
  69 + now := time.Now().Unix() + int64(timeOut)
  70 + count := 1
  71 + for {
  72 + if now < time.Now().Unix() {
  73 + log.Info(fmt.Sprintf("try lock timeout:%v retry %v; end...", l.Key(), count))
  74 + return false
  75 + }
  76 + result := l.Lock()
  77 + if result {
  78 + return true
  79 + }
  80 + log.Info(fmt.Sprintf("try lock fail:%v ... retry %v", l.Key(), count))
  81 + count++
  82 + time.Sleep(time.Second * 1)
  83 + }
  84 +}
  85 +
61 //解锁 86 //解锁
62 -func(l *Mutex)UnLock()error{ 87 +func (l *Mutex) UnLock() error {
63 defer l.Close() 88 defer l.Close()
64 - if !l.lock{ 89 + if !l.lock {
65 return nil 90 return nil
66 } 91 }
67 - if _,err :=l.conn.Do("DEL",l.Key());err!=nil{ 92 + if _, err := l.conn.Do("DEL", l.Key()); err != nil {
68 return err 93 return err
69 } 94 }
70 l.lock = false 95 l.lock = false
71 return nil 96 return nil
72 } 97 }
  98 +
73 //关闭 99 //关闭
74 -func(l *Mutex)Close(){  
75 - l.closeOnce.Do(func(){  
76 - if l.conn!=nil{ 100 +func (l *Mutex) Close() {
  101 + l.closeOnce.Do(func() {
  102 + if l.conn != nil {
77 l.conn.Close() 103 l.conn.Close()
78 } 104 }
79 }) 105 })
@@ -57,6 +57,17 @@ func Init(conf config.Redis) error { @@ -57,6 +57,17 @@ func Init(conf config.Redis) error {
57 return err 57 return err
58 } 58 }
59 59
  60 +func NewClient() redis.Conn {
  61 + c := redisPool.Get()
  62 + return c
  63 +}
  64 +
  65 +func NewPubsubClient() redis.PubSubConn {
  66 + c := redisPool.Get()
  67 + psc := redis.PubSubConn{c}
  68 + return psc
  69 +}
  70 +
60 func ping() (bool, error) { 71 func ping() (bool, error) {
61 c := redisPool.Get() 72 c := redisPool.Get()
62 defer c.Close() 73 defer c.Close()