go-redsyn實現redis分佈式鎖
go-redsyn實現了一個Mutex鎖而且用到了redis連接池,代碼也很簡潔明瞭 https://github.com/go-redsync/redsync
// A Mutex is a distributed mutual exclusion lock.
type Mutex struct {
name string
expiry time.Duration
tries int
delayFunc DelayFunc
factor float64
quorum int
genValueFunc func() (string, error)
value string
until time.Time
pools []redis.Pool
}
測試配置一個互斥鎖:
// 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,
delayFunc: func(tries int) time.Duration {
return time.Duration(rand.Intn(maxRetryDelayMilliSec-minRetryDelayMilliSec)+minRetryDelayMilliSec) * time.Millisecond
},
genValueFunc: genValue,
factor: 0.01,
quorum: len(r.pools)/2 + 1,
pools: r.pools,
}
for _, o := range options {
o.Apply(m)
}
return m
}
package main
import (
"time"
"github.com/go-redsync/redsync/v4"
"github.com/go-redsync/redsync/v4/redis/redigo"
redigolib "github.com/gomodule/redigo/redis"
"github.com/stvp/tempredis"
)
func main() {
server, err := tempredis.Start(tempredis.Config{})
if err != nil {
panic(err)
}
defer server.Term()
pool := redigo.NewPool(&redigolib.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redigolib.Conn, error) {
return redigolib.Dial("unix", server.Socket())
},
TestOnBorrow: func(c redigolib.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
},
})
rs := redsync.New(pool)
//一般會根據實際業務增加配置鎖的過期時間(默認爲8秒)
mutex := rs.NewMutex("test-redsync")
if err = mutex.Lock(); err != nil {
panic(err)
}
if _, err = mutex.Unlock(); err != nil {
panic(err)
}
}
如何提高緩存命中率(redis)
在高併發的互聯網系統中緩存的命中率是至關重要的指標。
緩存未命中:無法直接通過緩存獲取到想要的數據,需要再次查詢數據庫或者執行其它的操作。原因可能是由於緩存中根本不存在,或者緩存已經過期。
redis提供了INFO這個命令,能夠隨時監控服務器的狀態 127.0.0.1> info
在輸出的信息裏面有這幾項說明緩存的狀態:
keyspace_hits:14414110
keyspace_misses:3228654
used_memory:433264648
expired_keys:1333536
evicted_keys:1547380
通過計算hits和miss可以得到緩存的命中率:14414110 / (14414110 +3228654) = 81% ,一個緩存失效機制和過期時間設計良好的系統命中率可以做到95%以上。
從架構師的角度需要應用盡可能的通過緩存直接獲取數據並避免緩存失效。需要在業務需求,緩存粒度,緩存策略,技術選型等各個方面去通盤考慮並做權衡。
儘可能的聚焦在高頻訪問且時效性要求不高的熱點業務上(如字典數據、session、token),通過緩存預加載(預熱)、合理調整緩存有效期的時間 (避免同時失效)、增加存儲容量、調整緩存粒度、更新緩存等手段來提高命中率。對於時效性很高(或緩存空間有限),內容跨度很大(或訪問很隨機),並且訪問量不高的應用來說緩存命中率可能長期很低。