package redisx import ( "context" "time" "github.com/redis/go-redis/v9" "github.com/zeromicro/go-zero/core/stores/cache" ) type MasterSlaveCluster struct { Client *redis.ClusterClient MasterHost string SlaveHost string HasSlave bool } func NewMasterSlaveCluster(cacheConf cache.CacheConf) *MasterSlaveCluster { cacheConf = filterCacheConf(cacheConf) if len(cacheConf) == 0 { return &MasterSlaveCluster{} } master := cacheConf[0] slave := cacheConf[0] hasSlave := len(cacheConf) > 1 if hasSlave { slave = cacheConf[1] } client := redis.NewClusterClient(&redis.ClusterOptions{ Addrs: []string{master.Host}, Username: master.User, Password: master.Pass, ReadOnly: hasSlave, ClusterSlots: func(ctx context.Context) ([]redis.ClusterSlot, error) { nodes := []redis.ClusterNode{{Addr: master.Host}} if hasSlave { nodes = append(nodes, redis.ClusterNode{Addr: slave.Host}) } return []redis.ClusterSlot{{ Start: 0, End: 16383, Nodes: nodes, }}, nil }, }) return &MasterSlaveCluster{ Client: client, MasterHost: master.Host, SlaveHost: slave.Host, HasSlave: hasSlave, } } func ConnectMasterSlaveCluster(cacheConf cache.CacheConf, timeout time.Duration) (*MasterSlaveCluster, error) { cluster := NewMasterSlaveCluster(cacheConf) if cluster == nil || cluster.Client == nil { return cluster, nil } ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() if err := cluster.Ping(ctx); err != nil { return cluster, err } return cluster, nil } func (m *MasterSlaveCluster) Ping(ctx context.Context) error { if m == nil || m.Client == nil { return nil } return m.Client.Ping(ctx).Err() } func filterCacheConf(cacheConf cache.CacheConf) cache.CacheConf { if len(cacheConf) == 0 { return cacheConf } filtered := make(cache.CacheConf, 0, len(cacheConf)) for _, node := range cacheConf { if node.Host == "" { continue } filtered = append(filtered, node) } return filtered }