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 }