github.com/charlienet/go-mixed@v0.3.7/cache/redis.go (about) 1 package cache 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "time" 8 9 "github.com/charlienet/go-mixed/bytesconv" 10 "github.com/charlienet/go-mixed/json" 11 "github.com/charlienet/go-mixed/rand" 12 "github.com/go-redis/redis/v8" 13 ) 14 15 const redisEmptyObject = "redis object not exist" 16 17 type RedisConfig struct { 18 Prefix string // key perfix 19 Addrs []string 20 21 // Database to be selected after connecting to the server. 22 // Only single-node and failover clients. 23 DB int 24 25 Username string 26 Password string 27 MaxRetries int 28 MinRetryBackoff time.Duration 29 MaxRetryBackoff time.Duration 30 31 DialTimeout time.Duration 32 ReadTimeout time.Duration 33 WriteTimeout time.Duration 34 } 35 36 type redisClient struct { 37 client redis.UniversalClient 38 emptyStamp string // 空对象标识,每个实例隔离 39 prefix string // 缓存键前缀 40 } 41 42 func NewRedis(c RedisConfig) *redisClient { 43 client := redis.NewUniversalClient(&redis.UniversalOptions{ 44 Addrs: c.Addrs, 45 DB: c.DB, 46 Username: c.Username, 47 Password: c.Password, 48 }) 49 50 return &redisClient{ 51 emptyStamp: fmt.Sprintf("redis-empty-%d-%s", time.Now().Unix(), rand.Hex.Generate(6)), 52 prefix: c.Prefix, 53 client: client, 54 } 55 } 56 57 func (c *redisClient) Get(key string, out any) error { 58 val, err := c.client.Get(context.Background(), c.getKey(key)).Result() 59 if errors.Is(err, redis.Nil) { 60 return ErrNotFound 61 } 62 63 if err != nil { 64 return err 65 } 66 67 // redis 保存键为空值时返回键不存在错误 68 if val == redisEmptyObject { 69 return ErrNotFound 70 } 71 72 return json.Unmarshal(bytesconv.StringToBytes(val), out) 73 } 74 75 func (c *redisClient) Set(key string, value any, expiration time.Duration) error { 76 j, _ := json.Marshal(value) 77 return c.client.Set(context.Background(), c.getKey(key), j, expiration).Err() 78 } 79 80 func (c *redisClient) Exist(key string) (bool, error) { 81 val, err := c.client.Exists(context.Background(), c.getKey(key)).Result() 82 return val > 0, err 83 } 84 85 func (c *redisClient) Delete(key ...string) error { 86 keys := make([]string, 0, len(key)) 87 for _, k := range key { 88 keys = append(keys, c.getKey(k)) 89 } 90 91 _ , err := c.client.Del(context.Background(), keys...).Result() 92 if err != nil { 93 return err 94 } 95 96 return nil 97 } 98 99 func (c *redisClient) Ping() error { 100 _, err := c.client.Ping(context.Background()).Result() 101 return err 102 } 103 104 func (c *redisClient) getKey(key string) string { 105 if c.prefix != "" { 106 return c.prefix + ":" + key 107 } 108 109 return key 110 }