redis client自适应读写命令选择主库 OR 读库

This commit is contained in:
2024-10-08 16:31:59 +08:00
parent eec9374d48
commit 6f502a5bdd
3 changed files with 109 additions and 27 deletions

View File

@ -28,14 +28,14 @@ var (
func init() {
Client = &OwnClient{
lock: &sync.RWMutex{},
instanceTable: make(map[string]*redisClient.Client),
instanceTable: make(map[string]*define.ClientInfo),
whiteCommandTable: make(map[string]bool),
}
}
type OwnClient struct {
lock *sync.RWMutex
instanceTable map[string]*redisClient.Client
instanceTable map[string]*define.ClientInfo
whiteCommandTable map[string]bool
logger *zap.Logger
extraLogFieldList []string
@ -66,7 +66,7 @@ func (o *OwnClient) Exec(ctx context.Context, instanceFlag string, command strin
ctx = context.Background()
}
var (
instance *redisClient.Client
instance *define.ClientInfo
)
cmdParamList := []any{
@ -117,7 +117,21 @@ func (o *OwnClient) Exec(ctx context.Context, instanceFlag string, command strin
if nil == ctx {
ctx = context.Background()
}
cmdRes := instance.Do(ctx, cmdParamList...)
if instance.ReadOnly && o.isWriteCommand(command) {
// 只读实例, 尝试执行写命令
res.Err = errors.New(instanceFlag + " : instance is read only")
return res
}
if instance.ReadOnly && o.isWriteCommand(command) && instance.MasterClient() == nil {
// 写命令, 没有主库连接
res.Err = errors.New(instanceFlag + " : instance master client is nil")
return res
}
redisRealClient := instance.MasterClient()
if !o.isWriteCommand(command) {
redisRealClient = instance.SlaveClient()
}
cmdRes := redisRealClient.Do(ctx, cmdParamList...)
if res.Err = cmdRes.Err(); nil != res.Err {
return res
}
@ -138,13 +152,13 @@ func (o *OwnClient) SetCommandWhiteList(commandList []string) {
}
}
func (o *OwnClient) GetRealClient(instanceFlag string) *redisClient.Client {
func (o *OwnClient) GetRealClient(instanceFlag string) *define.ClientInfo {
o.lock.RLock()
defer o.lock.RUnlock()
return o.instanceTable[instanceFlag]
}
func (o *OwnClient) GetRealClientWithError(instanceFlag string) (*redisClient.Client, error) {
func (o *OwnClient) GetRealClientWithError(instanceFlag string) (*define.ClientInfo, error) {
o.lock.RLock()
defer o.lock.RUnlock()
instance, exist := o.instanceTable[instanceFlag]
@ -154,8 +168,57 @@ func (o *OwnClient) GetRealClientWithError(instanceFlag string) (*redisClient.Cl
return instance, nil
}
func (o *OwnClient) AddClient(instanceFlag string, instanceConfig *define.Options) error {
instance := redisClient.NewClient(&redisClient.Options{
func (o *OwnClient) AddClient(instanceFlag string, instanceConfig *define.Config) error {
if nil == instanceConfig.Master && !instanceConfig.ReadOnly {
// 不是只读, 则要求 主库配置 和 从库配置都要存在
return errors.New(instanceFlag + " : master config is nil")
}
clientInfo := &define.ClientInfo{
ReadOnly: instanceConfig.ReadOnly,
Master: nil,
Slave: nil,
}
if nil != instanceConfig.Master {
clientInfo.Master = o.newClient(instanceConfig.Master)
}
if nil != instanceConfig.Slave {
clientInfo.Master = o.newClient(instanceConfig.Slave)
}
o.lock.Lock()
defer o.lock.Unlock()
o.instanceTable[instanceFlag] = clientInfo
return nil
}
func (o *OwnClient) RemoveClient(instanceFlag string) {
o.lock.Lock()
defer o.lock.Unlock()
delete(o.instanceTable, instanceFlag)
}
func (o *OwnClient) SetLogger(loggerInstance *zap.Logger, extraLogFieldList []string) {
o.logger = loggerInstance
o.extraLogFieldList = extraLogFieldList
}
// isWriteCommand 判断是否写命令
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:22 2024/10/8
func (o *OwnClient) isWriteCommand(command string) bool {
return wrapperOperate.ArrayType([]string{}).Has(strings.ToUpper(command)) >= 0
}
// newClient 获取客户端连接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:12 2024/10/8
func (o *OwnClient) newClient(instanceConfig *define.Options) *redisClient.Client {
return redisClient.NewClient(&redisClient.Options{
DB: instanceConfig.DB,
Addr: instanceConfig.Addr,
ClientName: instanceConfig.ClientName,
@ -187,19 +250,4 @@ func (o *OwnClient) AddClient(instanceFlag string, instanceConfig *define.Option
// DisableIndentity: instanceConfig.DisableIdentity,
// IdentitySuffix: instanceConfig.IdentitySuffix,
})
o.lock.Lock()
defer o.lock.Unlock()
o.instanceTable[instanceFlag] = instance
return nil
}
func (o *OwnClient) RemoveClient(instanceFlag string) {
o.lock.Lock()
defer o.lock.Unlock()
delete(o.instanceTable, instanceFlag)
}
func (o *OwnClient) SetLogger(loggerInstance *zap.Logger, extraLogFieldList []string) {
o.logger = loggerInstance
o.extraLogFieldList = extraLogFieldList
}