github.com/godaddy-x/freego@v1.0.156/cache/redis_cache.go (about)

     1  package cache
     2  
     3  import (
     4  	"github.com/garyburd/redigo/redis"
     5  	DIC "github.com/godaddy-x/freego/common"
     6  	"github.com/godaddy-x/freego/utils"
     7  	"github.com/godaddy-x/freego/zlog"
     8  	"time"
     9  )
    10  
    11  var (
    12  	redisSessions = make(map[string]*RedisManager, 0)
    13  )
    14  
    15  type RedisConfig struct {
    16  	DsName      string
    17  	Host        string
    18  	Port        int
    19  	Password    string
    20  	MaxIdle     int
    21  	MaxActive   int
    22  	IdleTimeout int
    23  	Network     string
    24  }
    25  
    26  type RedisManager struct {
    27  	CacheManager
    28  	DsName string
    29  	Pool   *redis.Pool
    30  }
    31  
    32  func (self *RedisManager) InitConfig(input ...RedisConfig) (*RedisManager, error) {
    33  	for _, v := range input {
    34  		dsName := DIC.MASTER
    35  		if len(v.DsName) > 0 {
    36  			dsName = v.DsName
    37  		}
    38  		if _, b := redisSessions[dsName]; b {
    39  			return nil, utils.Error("init redis pool failed: [", v.DsName, "] exist")
    40  		}
    41  		pool := &redis.Pool{MaxIdle: v.MaxIdle, MaxActive: v.MaxActive, IdleTimeout: time.Duration(v.IdleTimeout) * time.Second, Dial: func() (redis.Conn, error) {
    42  			c, err := redis.Dial(v.Network, utils.AddStr(v.Host, ":", utils.AnyToStr(v.Port)))
    43  			if err != nil {
    44  				return nil, err
    45  			}
    46  			if len(v.Password) > 0 {
    47  				if _, err := c.Do("AUTH", v.Password); err != nil {
    48  					if err := c.Close(); err != nil {
    49  						zlog.Error("redis close failed", 0, zlog.AddError(err))
    50  					}
    51  					return nil, err
    52  				}
    53  			}
    54  			return c, err
    55  		}}
    56  		redisSessions[dsName] = &RedisManager{Pool: pool, DsName: dsName}
    57  		zlog.Printf("redis service【%s】has been started successful", dsName)
    58  	}
    59  	if len(redisSessions) == 0 {
    60  		return nil, utils.Error("init redis pool failed: sessions is nil")
    61  	}
    62  	return self, nil
    63  }
    64  
    65  func (self *RedisManager) Client(ds ...string) (*RedisManager, error) {
    66  	dsName := DIC.MASTER
    67  	if len(ds) > 0 && len(ds[0]) > 0 {
    68  		dsName = ds[0]
    69  	}
    70  	manager := redisSessions[dsName]
    71  	if manager == nil {
    72  		return nil, utils.Error("redis session [", ds, "] not found...")
    73  	}
    74  	return manager, nil
    75  }
    76  
    77  func NewRedis(ds ...string) (*RedisManager, error) {
    78  	return new(RedisManager).Client(ds...)
    79  }
    80  
    81  /********************************** redis缓存接口实现 **********************************/
    82  
    83  func (self *RedisManager) Get(key string, input interface{}) (interface{}, bool, error) {
    84  	client := self.Pool.Get()
    85  	defer self.Close(client)
    86  	value, err := redis.Bytes(client.Do("GET", key))
    87  	if err != nil && err != redis.ErrNil {
    88  		return nil, false, err
    89  	}
    90  	if value == nil || len(value) == 0 {
    91  		return nil, false, nil
    92  	}
    93  	if input == nil {
    94  		return value, true, nil
    95  	}
    96  	return value, true, utils.JsonUnmarshal(value, input)
    97  }
    98  
    99  func (self *RedisManager) GetInt64(key string) (int64, error) {
   100  	client := self.Pool.Get()
   101  	defer self.Close(client)
   102  	value, err := redis.Bytes(client.Do("GET", key))
   103  	if err != nil && err != redis.ErrNil {
   104  		return 0, err
   105  	}
   106  	if value == nil || len(value) == 0 {
   107  		return 0, nil
   108  	}
   109  	if ret, err := utils.StrToInt64(utils.Bytes2Str(value)); err != nil {
   110  		return 0, err
   111  	} else {
   112  		return ret, nil
   113  	}
   114  }
   115  
   116  func (self *RedisManager) GetFloat64(key string) (float64, error) {
   117  	client := self.Pool.Get()
   118  	defer self.Close(client)
   119  	value, err := redis.Bytes(client.Do("GET", key))
   120  	if err != nil && err != redis.ErrNil {
   121  		return 0, err
   122  	}
   123  	if value == nil || len(value) == 0 {
   124  		return 0, nil
   125  	}
   126  	if ret, err := utils.StrToFloat(utils.Bytes2Str(value)); err != nil {
   127  		return 0, err
   128  	} else {
   129  		return ret, nil
   130  	}
   131  }
   132  
   133  func (self *RedisManager) GetString(key string) (string, error) {
   134  	client := self.Pool.Get()
   135  	defer self.Close(client)
   136  	value, err := redis.Bytes(client.Do("GET", key))
   137  	if err != nil && err != redis.ErrNil {
   138  		return "", err
   139  	}
   140  	if value == nil || len(value) == 0 {
   141  		return "", nil
   142  	}
   143  	return utils.Bytes2Str(value), nil
   144  }
   145  
   146  func (self *RedisManager) GetBytes(key string) ([]byte, error) {
   147  	client := self.Pool.Get()
   148  	defer self.Close(client)
   149  	value, err := redis.Bytes(client.Do("GET", key))
   150  	if err != nil && err != redis.ErrNil {
   151  		return nil, err
   152  	}
   153  	if value == nil || len(value) == 0 {
   154  		return nil, nil
   155  	}
   156  	return value, nil
   157  }
   158  
   159  func (self *RedisManager) GetBool(key string) (bool, error) {
   160  	client := self.Pool.Get()
   161  	defer self.Close(client)
   162  	value, err := redis.Bytes(client.Do("GET", key))
   163  	if err != nil && err != redis.ErrNil {
   164  		return false, err
   165  	}
   166  	if value == nil || len(value) == 0 {
   167  		return false, nil
   168  	}
   169  	return utils.StrToBool(utils.Bytes2Str(value))
   170  }
   171  
   172  func (self *RedisManager) Put(key string, input interface{}, expire ...int) error {
   173  	if len(key) == 0 || input == nil {
   174  		return nil
   175  	}
   176  	var value []byte
   177  	if v, b := input.([]byte); b {
   178  		value = v
   179  	} else {
   180  		value = utils.Str2Bytes(utils.AnyToStr(input))
   181  	}
   182  	client := self.Pool.Get()
   183  	defer self.Close(client)
   184  	if len(expire) > 0 && expire[0] > 0 {
   185  		if _, err := client.Do("SET", key, value, "EX", expire[0]); err != nil {
   186  			return err
   187  		}
   188  	} else {
   189  		if _, err := client.Do("SET", key, value); err != nil {
   190  			return err
   191  		}
   192  	}
   193  	return nil
   194  }
   195  
   196  func (self *RedisManager) PutBatch(objs ...*PutObj) error {
   197  	if objs == nil || len(objs) == 0 {
   198  		return nil
   199  	}
   200  	client := self.Pool.Get()
   201  	defer self.Close(client)
   202  	if err := client.Send("MULTI"); err != nil {
   203  		return err
   204  	}
   205  	for _, v := range objs {
   206  		if v.Expire > 0 {
   207  			if err := client.Send("SET", v.Key, v.Value, "EX", v.Expire); err != nil {
   208  				return err
   209  			}
   210  		} else {
   211  			if err := client.Send("SET", v.Key, v.Value); err != nil {
   212  				return err
   213  			}
   214  		}
   215  	}
   216  	if _, err := client.Do("EXEC"); err != nil {
   217  		return err
   218  	}
   219  	return nil
   220  }
   221  
   222  func (self *RedisManager) Del(key ...string) error {
   223  	client := self.Pool.Get()
   224  	defer self.Close(client)
   225  	if err := client.Send("MULTI"); err != nil {
   226  		return err
   227  	}
   228  	for _, v := range key {
   229  		if err := client.Send("DEL", v); err != nil {
   230  			return err
   231  		}
   232  	}
   233  	if _, err := client.Do("EXEC"); err != nil {
   234  		return err
   235  	}
   236  	return nil
   237  }
   238  
   239  func (self *RedisManager) Brpop(key string, expire int64, result interface{}) error {
   240  	ret, err := self.BrpopString(key, expire)
   241  	if err != nil || len(ret) == 0 {
   242  		return err
   243  	}
   244  	if err := utils.JsonUnmarshal(utils.Str2Bytes(ret), &result); err != nil {
   245  		return err
   246  	}
   247  	return nil
   248  }
   249  
   250  func (self *RedisManager) BrpopString(key string, expire int64) (string, error) {
   251  	if len(key) == 0 || expire <= 0 {
   252  		return "", nil
   253  	}
   254  	client := self.Pool.Get()
   255  	defer self.Close(client)
   256  	ret, err := redis.ByteSlices(client.Do("BRPOP", key, expire))
   257  	if err != nil {
   258  		return "", err
   259  	} else if len(ret) != 2 {
   260  		return "", utils.Error("data len error")
   261  	}
   262  	return utils.Bytes2Str(ret[1]), nil
   263  }
   264  
   265  func (self *RedisManager) BrpopInt64(key string, expire int64) (int64, error) {
   266  	ret, err := self.BrpopString(key, expire)
   267  	if err != nil || len(ret) == 0 {
   268  		return 0, err
   269  	}
   270  	return utils.StrToInt64(ret)
   271  }
   272  
   273  func (self *RedisManager) BrpopFloat64(key string, expire int64) (float64, error) {
   274  	ret, err := self.BrpopString(key, expire)
   275  	if err != nil || len(ret) == 0 {
   276  		return 0, err
   277  	}
   278  	return utils.StrToFloat(ret)
   279  }
   280  
   281  func (self *RedisManager) BrpopBool(key string, expire int64) (bool, error) {
   282  	ret, err := self.BrpopString(key, expire)
   283  	if err != nil || len(ret) == 0 {
   284  		return false, err
   285  	}
   286  	return utils.StrToBool(ret)
   287  }
   288  
   289  func (self *RedisManager) Rpush(key string, val interface{}) error {
   290  	if val == nil || len(key) == 0 {
   291  		return nil
   292  	}
   293  	client := self.Pool.Get()
   294  	defer self.Close(client)
   295  	_, err := client.Do("RPUSH", key, utils.AnyToStr(val))
   296  	if err != nil {
   297  		return err
   298  	}
   299  	return nil
   300  }
   301  
   302  func (self *RedisManager) Publish(key string, val interface{}, try ...int) (bool, error) {
   303  	if val == nil || len(key) == 0 {
   304  		return false, nil
   305  	}
   306  	client := self.Pool.Get()
   307  	defer self.Close(client)
   308  	trySend := 5
   309  	if try != nil && try[0] > 0 {
   310  		trySend = try[0]
   311  	}
   312  	for i := 0; i < trySend; i++ {
   313  		reply, err := client.Do("PUBLISH", key, utils.AnyToStr(val))
   314  		if err != nil {
   315  			return false, err
   316  		}
   317  		if r, b := reply.(int64); b && r > 0 {
   318  			return true, nil
   319  		}
   320  		time.Sleep(time.Duration(100*i) * time.Millisecond)
   321  	}
   322  	return false, nil
   323  }
   324  
   325  func (self *RedisManager) Subscribe(key string, expSecond int, call func(msg string) (bool, error)) error {
   326  	if call == nil || len(key) == 0 {
   327  		return nil
   328  	}
   329  	if expSecond <= 0 {
   330  		expSecond = 5
   331  	}
   332  	client := self.Pool.Get()
   333  	defer self.Close(client)
   334  	c := redis.PubSubConn{Conn: client}
   335  	if err := c.Subscribe(key); err != nil {
   336  		return err
   337  	}
   338  	for {
   339  		switch v := c.ReceiveWithTimeout(time.Duration(expSecond) * time.Second).(type) {
   340  		case redis.Message:
   341  			if v.Channel == key {
   342  				r, err := call(utils.Bytes2Str(v.Data))
   343  				if err == nil && r {
   344  					return nil
   345  				}
   346  			}
   347  		case error:
   348  			return v
   349  		}
   350  	}
   351  }
   352  
   353  func (self *RedisManager) LuaScript(cmd string, key []string, val ...interface{}) (interface{}, error) {
   354  	if len(cmd) == 0 || key == nil || len(key) == 0 {
   355  		return nil, nil
   356  	}
   357  	args := make([]interface{}, 0, len(key)+len(val))
   358  	for _, v := range key {
   359  		args = append(args, v)
   360  	}
   361  	if val != nil && len(val) > 0 {
   362  		for _, v := range val {
   363  			args = append(args, utils.AddStr(v))
   364  		}
   365  	}
   366  	client := self.Pool.Get()
   367  	defer self.Close(client)
   368  	return redis.NewScript(len(key), cmd).Do(client, args...)
   369  }
   370  
   371  func (self *RedisManager) Keys(pattern ...string) ([]string, error) {
   372  	if pattern == nil || len(pattern) == 0 || pattern[0] == "*" {
   373  		return nil, nil
   374  	}
   375  	client := self.Pool.Get()
   376  	defer self.Close(client)
   377  	keys, err := redis.Strings(client.Do("KEYS", pattern[0]))
   378  	if err != nil {
   379  		return nil, err
   380  	}
   381  	return keys, nil
   382  }
   383  
   384  func (self *RedisManager) Size(pattern ...string) (int, error) {
   385  	keys, err := self.Keys(pattern...)
   386  	if err != nil {
   387  		return 0, err
   388  	}
   389  	return len(keys), nil
   390  }
   391  
   392  func (self *RedisManager) Values(pattern ...string) ([]interface{}, error) {
   393  	return nil, utils.Error("No implementation method [Values] was found")
   394  }
   395  
   396  func (self *RedisManager) Exists(key string) (bool, error) {
   397  	client := self.Pool.Get()
   398  	defer self.Close(client)
   399  	ret, err := client.Do("EXISTS", key)
   400  	if err != nil {
   401  		return false, err
   402  	}
   403  	b, err := redis.Int(ret, err)
   404  	return b == 1, err
   405  }
   406  
   407  func (self *RedisManager) Flush() error {
   408  	return utils.Error("No implementation method [Flush] was found")
   409  }
   410  
   411  func (self *RedisManager) Close(conn redis.Conn) {
   412  	if err := conn.Close(); err != nil {
   413  		zlog.Error("redis conn close failed", 0, zlog.AddError(err))
   414  	}
   415  }