go redis分散ロックの実現

3918 ワード

githubをダウンロードします.com/garyburd/redigo、この分散ロックは上述したように実現される.ダウンロードgopkg.in/redsync.v 1これは分散ロックを実現するソースコードである(github.com/stvp/tempredisをダウンロードする必要がある場合).
ソースを見て
package redsync
 
import (
	"crypto/rand"
	"encoding/base64"
	"sync"
	"time"
 
	"github.com/garyburd/redigo/redis"
)
 
// A Mutex is a distributed mutual exclusion lock.
type Mutex struct {
	name   string
	expiry time.Duration
 
	tries int
	delay time.Duration
 
	factor float64
 
	quorum int
 
	value string
	until time.Time
 
	nodem sync.Mutex
 
	pools []Pool
}
 

name   string          //      
expiry time.Duration   //          ,      
tries int              //          
delay time.Duration    //               
factor float64
quorum int
value string           //         ,
until time.Time
nodem sync.Mutex
pools []Pool           //    
 
// New creates and returns a new Redsync instance from given Redis connection pools.
func New(pools []Pool) *Redsync {
	return &Redsync{
		pools: pools,
	}
}
 
// NewMutex returns a new distributed mutex with given name.
func (r *Redsync) NewMutex(name string, options ...Option) *Mutex {
	m := &Mutex{
		name:   name,
		expiry: 8 * time.Second,
		tries:  32,
		delay:  500 * time.Millisecond,
		factor: 0.01,
		quorum: len(r.pools)/2 + 1,
		pools:  r.pools,
	}
	for _, o := range options {
		o.Apply(m)
	}
	return m
}
 
// An Option configures a mutex.
type Option interface {
	Apply(*Mutex)
}
 
// OptionFunc is a function that configures a mutex.
type OptionFunc func(*Mutex)
 
// Apply calls f(mutex)
func (f OptionFunc) Apply(mutex *Mutex) {
	f(mutex)
}
 
// SetExpiry can be used to set the expiry of a mutex to the given value.
func SetExpiry(expiry time.Duration) Option {
	return OptionFunc(func(m *Mutex) {
		m.expiry = expiry
	})
}
 
// SetTries can be used to set the number of times lock acquire is attempted.
func SetTries(tries int) Option {
	return OptionFunc(func(m *Mutex) {
		m.tries = tries
	})
}
 
// SetRetryDelay can be used to set the amount of time to wait between retries.
func SetRetryDelay(delay time.Duration) Option {
	return OptionFunc(func(m *Mutex) {
		m.delay = delay
	})
}
 
// SetDriftFactor can be used to set the clock drift factor.
func SetDriftFactor(factor float64) Option {
	return OptionFunc(func(m *Mutex) {
		m.factor = factor
	})
}

//ここのSET*メソッドは、Mutexのパラメータをカスタマイズする方法です
//次はテストコード
package main
 
import (
	"gopkg.in/redsync.v1"
	"testing"
	"github.com/garyburd/redigo/redis"
	"time"
	"fmt"
)
 
//redis      
func DoRedisCmdByConn(conn *redis.Pool,commandName string, args ...interface{}) (interface{}, error) {
	redisConn := conn.Get()
	defer redisConn.Close()
	//   redis   
	return redisConn.Do(commandName, args...)
}
 
 
func TestRedis(t *testing.T) {
 
	//   
	//pool := newPool()
	//rs := redsync.New([]redsync.Pool{pool})
	//mutex1 := rs.NewMutex("test-redsync1")
	//
	//mutex1.Lock()
	//conn := pool.Get()
	//conn.Do("SET","name1","ywb1")
	//conn.Close()
	//mutex1.Unlock()
	curtime := time.Now().UnixNano()
	//      
	pool := newPool()
	mutexes := newTestMutexes([]redsync.Pool{pool}, "test-mutex", 2)
	orderCh := make(chan int)
	for i,v :=range mutexes {
		go func(i int,mutex *redsync.Mutex) {
			if err := mutex.Lock(); err != nil {
				t.Fatalf("Expected err == nil, got %q", err)
				return
			}
			fmt.Println(i,"add lock ....")
			conn := pool.Get()
            DoRedisCmdByConn(pool,"SET",fmt.Sprintf("name%v",i),fmt.Sprintf("name%v",i))
			str,_ := redis.String(DoRedisCmdByConn(pool,"GET",fmt.Sprintf("name%v",i))
			fmt.Println(str)
            DoRedisCmdByConn(pool,"DEL",fmt.Sprintf("name%v",i))
			conn.Close()
			mutex.Unlock()
			fmt.Println(i,"del lock ....")
			orderCh