go-redis中创建一个redis的cluster对象
redisCluster := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: c.RedisCluster.Host,
Password: c.RedisCluster.Password,
PoolSize: c.RedisCluster.PoolSize,
MinIdleConns: c.RedisCluster.MinIdle,
IdleTimeout: time.Second * 3,
MaxRetries: 3,
})
使用ClusterOptions结构体接收参数
实例化中使用init函数初始化一些参数
func (opt *ClusterOptions) init() {
if opt.MaxRedirects == -1 {
opt.MaxRedirects = 0
} else if opt.MaxRedirects == 0 {
opt.MaxRedirects = 3
}
if opt.RouteByLatency || opt.RouteRandomly {
opt.ReadOnly = true
}
if opt.PoolSize == 0 {
opt.PoolSize = 5 * runtime.GOMAXPROCS(0)
}
......
}
对于redis中的各种操作,get,set等,cluster是怎么处理的呢?
// Get Redis `GET key` command. It returns redis.Nil error when key does not exist.
func (c cmdable) Get(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "get", key)
_ = c(ctx, cmd)
return cmd
}
cmdable是一个函数
type cmdable func(ctx context.Context, cmd Cmder) error
在cluster实例化的时候,对cmdable这个函数,赋值了
c.cmdable = c.Process
所以函数cluster的Process函数实现了cmdable
func (c *ClusterClient) Process(ctx context.Context, cmd Cmder) error {
return c.hooks.process(ctx, cmd, c.process)
}
对于hooks的process,接收了真正处理cmd的process函数,也在自己的procee中里面增加了hook的处理
func (hs hooks) process(
ctx context.Context, cmd Cmder, fn func(context.Context, Cmder) error,
) error {
if len(hs.hooks) == 0 {
err := fn(ctx, cmd)
cmd.SetErr(err)
return err
}
var hookIndex int
var retErr error
for ; hookIndex < len(hs.hooks) && retErr == nil; hookIndex++ {
ctx, retErr = hs.hooks[hookIndex].BeforeProcess(ctx, cmd)
if retErr != nil {
cmd.SetErr(retErr)
}
}
if retErr == nil {
retErr = fn(ctx, cmd)
cmd.SetErr(retErr)
}
for hookIndex--; hookIndex >= 0; hookIndex-- {
if err := hs.hooks[hookIndex].AfterProcess(ctx, cmd); err != nil {
retErr = err
cmd.SetErr(retErr)
}
}
return retErr
}
通过函数AddHook增加多个hook切片,循环的调用每个hook的处理方法
func (hs *hooks) AddHook(hook Hook) {
hs.hooks = append(hs.hooks, hook)
}
例如增加一个hook:
clusterHook := &hook{
beforeProcess: func(ctx context.Context, cmd redis.Cmder) (context.Context, error) {
Expect(cmd.String()).To(Equal("ping: "))
stack = append(stack, "cluster.BeforeProcess")
return ctx, nil
},
afterProcess: func(ctx context.Context, cmd redis.Cmder) error {
Expect(cmd.String()).To(Equal("ping: PONG"))
stack = append(stack, "cluster.AfterProcess")
return nil
},
}
client.AddHook(clusterHook)