代码拉取完成,页面将自动刷新
package gredis
import (
"context"
"github.com/go-redis/redis"
"net"
"regexp"
"sync/atomic"
)
// Redis主从组
type CACHEGroup struct {
mCounter uint64
Master []*CACHEConn
sCounter uint64
Slave []*CACHEConn
Cluster *CACHEConn
}
// 创建主从连接
func newMasterSlaveConn(cacheGroup *CACHEGroup, groupConf *CACHEGroupConf) (err error) {
masterConf := groupConf.Master
slaveConf := groupConf.Slaves
cacheGroup.Master = make([]*CACHEConn, 0)
cacheGroup.Slave = make([]*CACHEConn, 0)
var cacheConn *CACHEConn
// master连接池
if masterConf != nil && masterConf.Instances != nil {
hostCountMap := cacheGroup.getHostCountMap(masterConf.Instances)
for i := 0; i < len(masterConf.Instances); i++ {
if cacheConn, err = newCACHEConnection(groupConf, masterConf, &masterConf.Instances[i], hostCountMap); err != nil {
return
}
cacheGroup.Master = append(cacheGroup.Master, cacheConn)
}
}
// slave连接池
if slaveConf != nil && slaveConf.Instances != nil {
hostCountMap := cacheGroup.getHostCountMap(slaveConf.Instances)
for i := 0; i < len(slaveConf.Instances); i++ {
if cacheConn, err = newCACHEConnection(groupConf, slaveConf, &slaveConf.Instances[i], hostCountMap); err != nil {
return
}
cacheGroup.Slave = append(cacheGroup.Slave, cacheConn)
}
}
return
}
// 创建集群连接
func newClusterConn(cacheGroup *CACHEGroup, groupConf *CACHEGroupConf) (err error) {
clusterConf := groupConf.Cluster
var cacheConn *CACHEConn
// redis-cluster连接池
if clusterConf != nil && clusterConf.Instances != nil {
if cacheConn, err = newCACHEConnection(groupConf, clusterConf, nil, nil); err != nil {
return
}
cacheGroup.Cluster = cacheConn
}
return
}
func newCACHEGroup(groupConf *CACHEGroupConf) (cacheGroup *CACHEGroup, err error) {
//redis实例名字必须设置
if len(groupConf.Name) <= 0 {
err = ERR_CACHE_NAME_NOT_FOUND
return
}
cacheGroup = &CACHEGroup{}
if err = newMasterSlaveConn(cacheGroup, groupConf); err != nil {
return
}
if err = newClusterConn(cacheGroup, groupConf); err != nil {
return
}
return
}
// 选择连接
func (cacheGroup *CACHEGroup) ChooseConn(ctx context.Context, accessType ACC_TYPE) (currentClient *redis.Client, err error) {
var currentConn *CACHEConn
// 从库
if accessType == SLAVE && len(cacheGroup.Slave) > 0 {
counter := atomic.AddUint64(&cacheGroup.sCounter, 1)
currentConn = cacheGroup.Slave[counter%uint64(len(cacheGroup.Slave))]
} else if len(cacheGroup.Master) != 0 {
counter := atomic.AddUint64(&cacheGroup.mCounter, 1)
currentConn = cacheGroup.Master[counter%uint64(len(cacheGroup.Master))]
}
if currentConn == nil {
err = ERR_CACHE_CONN_NOT_FOUND
return
}
// 包装请求上下文
currentClient, err = currentConn.NewWrapperClient(ctx)
return
}
func (cacheGroup *CACHEGroup) ChooseClusterConn(ctx context.Context) (currentClient *redis.ClusterClient, err error) {
var currentConn *CACHEConn
// cluster
currentConn = cacheGroup.Cluster
if currentConn == nil {
err = ERR_CACHE_CONN_NOT_FOUND
return
}
// 包装请求上下文
currentClient, err = currentConn.NewWrapperClusterClient(ctx)
return
}
// 多个从库指向1个redis实例 map管理
func (cacheGroup *CACHEGroup) getHostCountMap(instances []CACHEConnConf) (hostCountMap map[string]int) {
// host => host对应的ip被使用次数
hostCountMap = make(map[string]int, 0)
// host => ip 映射关系
hostIpMap := make(map[string]string, 0)
// ip => 出现次数映射关系
ipCountMap := make(map[string]int, 0)
for i := 0; i < len(instances); i++ {
ins := instances[i]
ipStr := "127.0.0.1"
// 匹配是否是直接配的IP地址
ipV4Matched, _ := regexp.MatchString("((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}", ins.Host)
if ipV4Matched {
ipStr = ins.Host
} else {
addrList, _ := net.LookupIP(ins.Host)
for _, addr := range addrList {
if addr.To4() != nil {
ipStr = addr.String()
break
}
}
}
hostIpMap[ins.Host] = ipStr
_, exists := ipCountMap[ipStr]
if !exists {
ipCountMap[ipStr] = 0
}
ipCountMap[ipStr] = ipCountMap[ipStr] + 1
}
for host, ip := range hostIpMap {
count := ipCountMap[ip]
hostCountMap[host] = count
}
return
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。