redis.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Package redis 工具包
  2. package redis
  3. import (
  4. "context"
  5. "sync"
  6. "time"
  7. "github.com/redis/go-redis/v9"
  8. "github.com/runningwater/gohub/pkg/logger"
  9. )
  10. // RedisClient Redis 服务
  11. type RedisClient struct {
  12. Client *redis.Client
  13. Context context.Context
  14. }
  15. // Ping 测试 Redis 连接
  16. // 通过 Ping 方法测试 Redis 连接是否正常
  17. func (rds *RedisClient) Ping() error {
  18. _, err := rds.Client.Ping(rds.Context).Result()
  19. return err
  20. }
  21. // Set 设置 Redis 键值对, 并设置过期时间
  22. func (rds *RedisClient) Set(key string, value any, expiraction time.Duration) bool {
  23. if err := rds.Client.Set(rds.Context, key, value, expiraction).Err(); err != nil {
  24. logger.ErrorString("Redis", "Set", err.Error())
  25. return false
  26. }
  27. return true
  28. }
  29. // Get 获取 Redis 键值对
  30. func (rds *RedisClient) Get(key string) string {
  31. val, err := rds.Client.Get(rds.Context, key).Result()
  32. if err != nil {
  33. logger.ErrorString("Redis", "Get", err.Error())
  34. return ""
  35. }
  36. return val
  37. }
  38. // Has 检查 Redis 中是否存在某个键
  39. func (rds *RedisClient) Has(key string) bool {
  40. _, err := rds.Client.Get(rds.Context, key).Result()
  41. if err != nil {
  42. if err == redis.Nil {
  43. logger.ErrorString("Redis", "Has", err.Error())
  44. }
  45. return false
  46. }
  47. return true
  48. }
  49. // Del 删除 Redis 中的键, 支持多个 key 传参
  50. func (rds *RedisClient) Del(keys ...string) bool {
  51. if err := rds.Client.Del(rds.Context, keys...).Err(); err != nil {
  52. logger.ErrorString("Redis", "Del", err.Error())
  53. return false
  54. }
  55. return true
  56. }
  57. // FlushDb 清空 Redis 数据库
  58. func (rds *RedisClient) FlushDb() bool {
  59. if err := rds.Client.FlushDB(rds.Context).Err(); err != nil {
  60. logger.ErrorString("Redis", "FlushDb", err.Error())
  61. return false
  62. }
  63. return true
  64. }
  65. // Increment 当参数只有 1 个时,增加 Redis 中的键值对增加 1
  66. // 当参数有 2 个时,第一个参数为 Key,第二个参数为增加的值 int64 类型
  67. func (rds *RedisClient) Increment(args ...any) bool {
  68. switch len(args) {
  69. case 1:
  70. key := args[0].(string)
  71. if err := rds.Client.Incr(rds.Context, key).Err(); err != nil {
  72. logger.ErrorString("Redis", "Increment", err.Error())
  73. return false
  74. }
  75. case 2:
  76. key := args[0].(string)
  77. value := args[1].(int64)
  78. if err := rds.Client.IncrBy(rds.Context, key, value).Err(); err != nil {
  79. logger.ErrorString("Redis", "Increment", err.Error())
  80. return false
  81. }
  82. default:
  83. logger.ErrorString("Redis", "Increment", "参数错误, 只能传入 1 或 2 个参数")
  84. return false
  85. }
  86. return true
  87. }
  88. // Decrement 当参数只有 1 个时,减少 Redis 中的键值对减少 1
  89. // 当参数有 2 个时,第一个参数为 Key,第二个参数为减少的值 int64 类型
  90. func (rds *RedisClient) Decrement(args ...any) bool {
  91. switch len(args) {
  92. case 1:
  93. key := args[0].(string)
  94. if err := rds.Client.Decr(rds.Context, key).Err(); err != nil {
  95. logger.ErrorString("Redis", "Decrement", err.Error())
  96. return false
  97. }
  98. case 2:
  99. key := args[0].(string)
  100. value := args[1].(int64)
  101. if err := rds.Client.DecrBy(rds.Context, key, value).Err(); err != nil {
  102. logger.ErrorString("Redis", "Decrement", err.Error())
  103. return false
  104. }
  105. default:
  106. logger.ErrorString("Redis", "Decrement", "参数错误, 只能传入 1 或 2 个参数")
  107. return false
  108. }
  109. return true
  110. }
  111. // func (rds *RedisClient) Reconnect(ctx context.Context) {
  112. // for {
  113. // err := rds.Ping()
  114. // if err == nil {
  115. // logger.InfoString("Redis", "Ping", "Redis 连接正常")
  116. // return
  117. // }
  118. // logger.ErrorString("Redis", "Ping", "Redis 连接异常,正在重连...")
  119. // // 重新连接 Redis
  120. // rds.Client = redis.NewClient(&redis.Options{
  121. // Addr: rds.Client.Options().Addr,
  122. // Password: rds.Client.Options().Password,
  123. // DB: rds.Client.Options().DB,
  124. // })
  125. // select {
  126. // case <-ctx.Done():
  127. // logger.InfoString("Redis", "Reconnect", "Redis 重连已取消")
  128. // return
  129. // case <-time.After(5 * time.Second):
  130. // }
  131. // }
  132. // }
  133. // once 确保全局的 Redis 对象只实例一次
  134. var once sync.Once
  135. // Redis 全局 Redis, 使用 db 1
  136. var Redis *RedisClient
  137. // ConnectRedis 连接 redis 数据库,设置全局 Redis 对象
  138. func ConnectRedis(address, username, password string, db int) {
  139. once.Do(func() {
  140. Redis = NewClient(address, username, password, db)
  141. })
  142. }
  143. func NewClient(address, username, password string, db int) *RedisClient {
  144. rds := &RedisClient{}
  145. rds.Context = context.Background()
  146. // 使用 redis 库里的 NewClient 初始化连接
  147. rds.Client = redis.NewClient(&redis.Options{
  148. Addr: address,
  149. Password: password,
  150. DB: db,
  151. })
  152. err := rds.Ping()
  153. logger.LogIf(err)
  154. // ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  155. // defer cancel()
  156. // rds.Reconnect(ctx)
  157. return rds
  158. }