mirror of
https://github.com/xxjwxc/public.git
synced 2025-09-26 20:01:19 +08:00
388 lines
8.4 KiB
Go
388 lines
8.4 KiB
Go
package myredis
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"github.com/gomodule/redigo/redis"
|
||
"github.com/xxjwxc/public/dev"
|
||
"github.com/xxjwxc/public/mylog"
|
||
"github.com/xxjwxc/public/tools"
|
||
)
|
||
|
||
type base struct {
|
||
*MyRedis
|
||
}
|
||
|
||
func (mc *base) getCtx() context.Context {
|
||
return context.Background()
|
||
}
|
||
|
||
func (mc *base) getKey(key interface{}) string {
|
||
tmp := ""
|
||
if len(mc.conf.groupName) > 0 {
|
||
tmp = fmt.Sprintf("%v:", mc.conf.groupName)
|
||
}
|
||
switch t := key.(type) {
|
||
case []byte:
|
||
return fmt.Sprintf("%v%v", tmp, string(t))
|
||
case string:
|
||
return fmt.Sprintf("%v%v", tmp, t)
|
||
default:
|
||
return fmt.Sprintf("%v%v", tmp, tools.JSONDecode(key))
|
||
}
|
||
}
|
||
|
||
func (mc *base) encodeValue(value interface{}) interface{} {
|
||
switch t := value.(type) {
|
||
case int32, byte, string, bool, int, uint, int8, int16, int64, uint16, uint32, uint64, float32, float64: // 基础类型
|
||
return t
|
||
default:
|
||
return tools.JSONDecode(value)
|
||
// data, _ := serializing.Encode(value)
|
||
// return data
|
||
}
|
||
}
|
||
|
||
func (mc *base) decodeValue(in, out interface{}) (err error) {
|
||
if in == nil {
|
||
return fmt.Errorf("not fond")
|
||
}
|
||
|
||
var reply string
|
||
switch t := in.(type) {
|
||
case []byte:
|
||
reply = string(t)
|
||
default:
|
||
return fmt.Errorf("decodeValue err in type not find:%v", t)
|
||
}
|
||
|
||
switch o := out.(type) {
|
||
case *string: // string类型
|
||
*o = reply
|
||
return nil
|
||
case *int32:
|
||
i64, err := strconv.ParseInt(reply, 10, 0)
|
||
*o = int32(i64)
|
||
return err
|
||
case *bool:
|
||
b, err := strconv.ParseBool(string(reply))
|
||
*o = b
|
||
return err
|
||
case *int:
|
||
i64, err := strconv.ParseInt(reply, 10, 0)
|
||
*o = int(i64)
|
||
return err
|
||
case *int8:
|
||
i64, err := strconv.ParseInt(reply, 10, 0)
|
||
*o = int8(i64)
|
||
return err
|
||
case *int16:
|
||
i64, err := strconv.ParseInt(reply, 10, 0)
|
||
*o = int16(i64)
|
||
return err
|
||
case *int64:
|
||
i64, err := strconv.ParseInt(string(reply), 10, 64)
|
||
*o = int64(i64)
|
||
return err
|
||
case *uint:
|
||
i64, err := strconv.ParseUint(reply, 10, 0)
|
||
*o = uint(i64)
|
||
return err
|
||
case *uint8:
|
||
i64, err := strconv.ParseUint(reply, 10, 0)
|
||
*o = uint8(i64)
|
||
return err
|
||
case *uint16:
|
||
i64, err := strconv.ParseUint(reply, 10, 0)
|
||
*o = uint16(i64)
|
||
return err
|
||
case *uint32:
|
||
i64, err := strconv.ParseInt(string(reply), 10, 0)
|
||
*o = uint32(i64)
|
||
return err
|
||
case *uint64:
|
||
i64, err := strconv.ParseUint(reply, 10, 64)
|
||
*o = uint64(i64)
|
||
return err
|
||
case *float32:
|
||
f64, err := strconv.ParseFloat(string(reply), 32)
|
||
*o = float32(f64)
|
||
return err
|
||
case *float64: // 基础类型
|
||
f64, err := strconv.ParseFloat(string(reply), 64)
|
||
*o = float64(f64)
|
||
return err
|
||
default:
|
||
tools.JSONEncode(reply, out) // 复杂类型
|
||
return nil
|
||
//return serializing.Decode(t, out)
|
||
|
||
}
|
||
|
||
// return fmt.Errorf("decodeValue err not match:%v %v", in, out)
|
||
}
|
||
|
||
func (mc *base) ping(con redis.Conn) bool {
|
||
if con == nil {
|
||
return false
|
||
}
|
||
|
||
_, err := con.Do("PING")
|
||
if err != nil {
|
||
mylog.Errorf("ping redis error: %s", err)
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
// Dial 获取一个链接
|
||
func (mc *base) build() (con redis.Conn, err error) {
|
||
err = fmt.Errorf("not fond ")
|
||
index := mc.conf.addrIdex
|
||
len := len(mc.conf.addrs)
|
||
b := false
|
||
for i := 0; i < len; i++ {
|
||
index = (mc.conf.addrIdex + i) % len
|
||
con, err = redis.Dial("tcp", mc.conf.addrs[index], // redis.DialClientName(mc.conf.clientName),
|
||
redis.DialConnectTimeout(mc.conf.timeout), redis.DialDatabase(mc.conf.db),
|
||
redis.DialPassword(mc.conf.pwd), redis.DialReadTimeout(mc.conf.readTimeout), redis.DialWriteTimeout(mc.conf.writeTimeout),
|
||
)
|
||
if err != nil {
|
||
mylog.Error(err)
|
||
}
|
||
if mc.ping(con) {
|
||
b = true
|
||
}
|
||
}
|
||
if b {
|
||
mc.conf.addrIdex = (index + 1) % len
|
||
}
|
||
return
|
||
}
|
||
|
||
// Dial 获取一个链接
|
||
func (mc *base) Dial() (redis.Conn, error) {
|
||
mc.mtx.Lock()
|
||
defer mc.mtx.Unlock()
|
||
return mc.build() // 创建连接
|
||
}
|
||
|
||
func (mc *base) DO(con redis.Conn, commandName string, args ...interface{}) (reply interface{}, err error) {
|
||
if dev.IsDev() && mc.conf.isLog {
|
||
cmd := commandName
|
||
for _, v := range args {
|
||
cmd += fmt.Sprintf(" %v", v)
|
||
if len(cmd) > 100 {
|
||
cmd = cmd[:100]
|
||
break
|
||
}
|
||
}
|
||
mylog.Infof("redis req :%v \n", cmd)
|
||
}
|
||
|
||
if con != nil {
|
||
reply, err = con.Do(commandName, args...)
|
||
// show log
|
||
if dev.IsDev() && mc.conf.isLog {
|
||
tmp := ""
|
||
switch reply := reply.(type) {
|
||
case []byte:
|
||
tmp = string(reply)
|
||
case string:
|
||
tmp = reply
|
||
case int64:
|
||
tmp = fmt.Sprintf("%v", reply)
|
||
}
|
||
if len(tmp) > 100 {
|
||
tmp = tmp[:100]
|
||
}
|
||
mylog.Infof("redis resp:%v,%v \n", tmp, err)
|
||
|
||
}
|
||
return
|
||
}
|
||
return nil, fmt.Errorf("con is nil")
|
||
}
|
||
|
||
func (mc *base) fixKeyGroupName(key string) string {
|
||
tmp := ""
|
||
if len(mc.conf.groupName) > 0 {
|
||
tmp = fmt.Sprintf("%v:", mc.conf.groupName)
|
||
}
|
||
return strings.TrimPrefix(key, tmp)
|
||
}
|
||
|
||
// type redisConOlny struct {
|
||
// base
|
||
// con redis.Conn
|
||
// }
|
||
|
||
// // Destory 析构
|
||
// func (mc *redisConOlny) Destory() {
|
||
// mc.mtx.Lock()
|
||
// defer mc.mtx.Unlock()
|
||
|
||
// if mc.con != nil {
|
||
// err := mc.con.Close()
|
||
// if err != nil {
|
||
// mylog.Error(err)
|
||
// }
|
||
// mc.con = nil
|
||
// }
|
||
// }
|
||
|
||
// // GetRedisClient ...
|
||
// func (mc *redisConOlny) GetRedisClient() redis.Conn {
|
||
// if mc.con == nil {
|
||
// con, _ := mc.Dial()
|
||
// mc.con = con
|
||
// }
|
||
// return mc.con
|
||
// }
|
||
|
||
// // Ping 判断是否能ping通
|
||
// func (mc *redisConOlny) Ping() bool {
|
||
// return mc.ping(mc.GetRedisClient())
|
||
// }
|
||
|
||
// // 判断是否能ping通
|
||
// // Add 添加一个缓存 lifeSpan:缓存时间,0表示永不超时
|
||
// func (mc *redisConOlny) Add(key interface{}, value interface{}, lifeSpan time.Duration) error {
|
||
// var args []interface{}
|
||
// args = append(args, mc.getKey(key), mc.encodeValue(value))
|
||
// if lifeSpan > 0 {
|
||
// if usePrecise(lifeSpan) {
|
||
// args = append(args, "px", formatMs(lifeSpan))
|
||
// } else {
|
||
// args = append(args, "ex", formatSec(lifeSpan))
|
||
// }
|
||
// } else if lifeSpan == keepTTL {
|
||
// args = append(args, "keepttl")
|
||
// }
|
||
|
||
// _, err := mc.DO(mc.GetRedisClient(), "SET", args...)
|
||
// if err != nil {
|
||
// mylog.Error(err)
|
||
// }
|
||
// return err
|
||
// }
|
||
|
||
// // Value 查找一个cache
|
||
// func (mc *redisConOlny) Value(key interface{}, value interface{}) (err error) {
|
||
// repy, err := mc.DO(mc.GetRedisClient(), "GET", mc.getKey(key))
|
||
// if err != nil {
|
||
// mylog.Error(err)
|
||
// return err
|
||
// }
|
||
// return mc.decodeValue(repy, value)
|
||
// }
|
||
|
||
// // IsExist 判断key是否存在
|
||
// func (mc *redisConOlny) IsExist(key interface{}) bool {
|
||
// repy, err := mc.DO(mc.GetRedisClient(), "EXISTS", mc.getKey(key))
|
||
// if err != nil {
|
||
// mylog.Error(err)
|
||
// return false
|
||
// }
|
||
// exist, err := redis.Bool(repy, err) // 转化bool格式
|
||
// if err != nil {
|
||
// mylog.Error(err)
|
||
// return false
|
||
// }
|
||
|
||
// return exist
|
||
// }
|
||
|
||
// // Delete 删除一个cache
|
||
// func (mc *redisConOlny) Delete(key interface{}) error {
|
||
// _, err := mc.DO(mc.GetRedisClient(), "del", mc.getKey(key))
|
||
// if err != nil {
|
||
// mylog.Error(err)
|
||
// return err
|
||
// }
|
||
// return err
|
||
// }
|
||
|
||
// // Clear 清空表內容
|
||
// func (mc *redisConOlny) Clear() error {
|
||
// out, err := mc.GetKeyS("*")
|
||
// if err != nil {
|
||
// return err
|
||
// }
|
||
|
||
// for _, v := range out {
|
||
// err = mc.Delete(v)
|
||
// if err != nil {
|
||
// return err
|
||
// }
|
||
// }
|
||
|
||
// return err
|
||
// }
|
||
|
||
// // GetKeyS 查询所有key
|
||
// func (mc *redisConOlny) GetKeyS(key interface{}) ([]string, error) {
|
||
// var keys []string
|
||
// repy, err := mc.DO(mc.GetRedisClient(), "keys", mc.getKey(key))
|
||
// if err != nil {
|
||
// mylog.Error(err)
|
||
// return keys, err
|
||
// }
|
||
|
||
// switch t := repy.(type) {
|
||
// case []interface{}:
|
||
// for _, v := range t {
|
||
// out, err := redis.String(v, nil)
|
||
// if err != nil {
|
||
// mylog.Error(err)
|
||
// }
|
||
// keys = append(keys, mc.fixKeyGroupName(out))
|
||
// }
|
||
// default:
|
||
// return keys, fmt.Errorf("decodeValue err in type not find:%v", t)
|
||
// }
|
||
|
||
// return keys, err
|
||
// }
|
||
|
||
// func (mc *redisConOlny) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
|
||
// con := mc.GetRedisClient()
|
||
// mc.mtx.Lock()
|
||
// defer mc.mtx.Unlock()
|
||
// return mc.DO(con, commandName, args...)
|
||
// }
|
||
|
||
// // Close 关闭一个连接
|
||
// func (mc *redisConOlny) Close() (err error) {
|
||
// mc.mtx.Lock()
|
||
// defer mc.mtx.Unlock()
|
||
// if mc.con != nil {
|
||
// err = mc.con.Close()
|
||
// mc.con = nil
|
||
// }
|
||
|
||
// return
|
||
// }
|
||
|
||
func usePrecise(dur time.Duration) bool {
|
||
return dur < time.Second || dur%time.Second != 0
|
||
}
|
||
|
||
func formatMs(dur time.Duration) int64 {
|
||
if dur > 0 && dur < time.Millisecond {
|
||
return 1
|
||
}
|
||
return int64(dur / time.Millisecond)
|
||
}
|
||
|
||
func formatSec(dur time.Duration) int64 {
|
||
if dur > 0 && dur < time.Second {
|
||
return 1
|
||
}
|
||
return int64(dur / time.Second)
|
||
}
|