base_redis.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright (c) [2022] [巴拉迪维 BaratSemet]
  2. // [ohUrlShortener] is licensed under Mulan PSL v2.
  3. // You can use this software according to the terms and conditions of the Mulan PSL v2.
  4. // You may obtain a copy of Mulan PSL v2 at:
  5. // http://license.coscl.org.cn/MulanPSL2
  6. // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
  7. // See the Mulan PSL v2 for more details.
  8. package storage
  9. import (
  10. "context"
  11. "log"
  12. "time"
  13. "ohurlshortener/utils"
  14. "github.com/go-redis/redis/v8"
  15. )
  16. var (
  17. redisService = &RedisService{}
  18. ctx = context.Background()
  19. )
  20. // RedisService Redis 服务
  21. type RedisService struct {
  22. redisClient *redis.Client
  23. redisClusterClient *redis.ClusterClient
  24. clusterMode bool
  25. }
  26. // InitRedisService 初始化 Redis 服务
  27. func InitRedisService() (*RedisService, error) {
  28. redisClusterClient := redis.NewClusterClient(&redis.ClusterOptions{
  29. Addrs: utils.RedisClusterConfig.Hosts,
  30. Username: utils.RedisClusterConfig.User,
  31. Password: utils.RedisClusterConfig.Password,
  32. PoolSize: utils.RedisClusterConfig.PoolSize,
  33. })
  34. _, err := redisClusterClient.Ping(ctx).Result()
  35. if err != nil {
  36. log.Println(err)
  37. log.Println("Failed to connect to Redis cluster. Will try to connect to single node.")
  38. // If there's any error while connecting to Redis cluster,
  39. // then try to connect to single Redis node.
  40. redisClient := redis.NewClient(&redis.Options{
  41. Addr: utils.RedisConfig.Host,
  42. DB: utils.RedisConfig.Database,
  43. Username: utils.RedisConfig.User,
  44. Password: utils.RedisConfig.Password,
  45. PoolSize: utils.RedisConfig.PoolSize,
  46. })
  47. _, err := redisClient.Ping(ctx).Result()
  48. if err != nil {
  49. return nil, err
  50. }
  51. redisService.redisClient = redisClient
  52. } else {
  53. redisService.clusterMode = true
  54. redisService.redisClusterClient = redisClusterClient
  55. }
  56. return redisService, nil
  57. }
  58. // RedisSet 设置 Redis 键值对
  59. func RedisSet(key string, value interface{}, ttl time.Duration) error {
  60. if redisService.clusterMode {
  61. return redisService.redisClusterClient.Set(ctx, key, value, ttl).Err()
  62. }
  63. return redisService.redisClient.Set(ctx, key, value, ttl).Err()
  64. }
  65. // RedisSet30m 设置 Redis 键值对,过期时间为 30 分钟
  66. func RedisSet30m(key string, value interface{}) error {
  67. return RedisSet(key, value, 30*time.Minute)
  68. }
  69. // RedisSet4Ever 设置 Redis 键值对,永不过期
  70. func RedisSet4Ever(key string, value interface{}) error {
  71. return RedisSet(key, value, redis.KeepTTL)
  72. }
  73. // RedisScan4Keys 获取 Redis 中所有以 prefix 开头的键
  74. func RedisScan4Keys(prefix string) ([]string, error) {
  75. var keys []string
  76. var sc *redis.ScanIterator
  77. if redisService.clusterMode {
  78. err := redisService.redisClusterClient.ForEachMaster(ctx, func(ctx context.Context, client *redis.Client) error {
  79. sc = client.Scan(ctx, 0, prefix, 0).Iterator()
  80. for sc.Next(ctx) {
  81. keys = append(keys, sc.Val())
  82. }
  83. return sc.Err()
  84. })
  85. if err != nil {
  86. return keys, err
  87. }
  88. } else {
  89. sc = redisService.redisClient.Scan(ctx, 0, prefix, 0).Iterator()
  90. }
  91. for sc.Next(ctx) {
  92. keys = append(keys, sc.Val())
  93. }
  94. return keys, sc.Err()
  95. }
  96. // RedisGetString 获取 Redis 中的字符串
  97. func RedisGetString(key string) (string, error) {
  98. var result string
  99. var err error
  100. if redisService.clusterMode {
  101. result, err = redisService.redisClusterClient.Get(ctx, key).Result()
  102. } else {
  103. result, err = redisService.redisClient.Get(ctx, key).Result()
  104. }
  105. if err == redis.Nil {
  106. return result, nil
  107. }
  108. return result, err
  109. }
  110. // RedisFlushDB 清空 Redis 中的所有键值对
  111. func RedisFlushDB() error {
  112. if redisService.clusterMode {
  113. return redisService.redisClusterClient.ForEachMaster(ctx, func(ctx context.Context, client *redis.Client) error {
  114. return client.FlushDB(ctx).Err()
  115. })
  116. }
  117. return redisService.redisClient.FlushDB(ctx).Err()
  118. }
  119. // RedisDelete 删除 Redis 中的键值对
  120. func RedisDelete(key ...string) error {
  121. if len(key) > 0 {
  122. if redisService.clusterMode {
  123. // Apparently you can NOT delete multiple keys in a single request,since keys are distributed across multiple nodes.
  124. var err error
  125. for _, k := range key {
  126. err = redisService.redisClusterClient.Del(ctx, k).Err()
  127. }
  128. return err
  129. } else {
  130. return redisService.redisClient.Del(ctx, key...).Err()
  131. }
  132. }
  133. return nil
  134. }