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),通过缓存预加载(预热)、合理调整缓存有效期的时间 (避免同时失效)、增加存储容量、调整缓存粒度、更新缓存等手段来提高命中率。对于时效性很高(或缓存空间有限),内容跨度很大(或访问很随机),并且访问量不高的应用来说缓存命中率可能长期很低。