goredis.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package redis
  2. import (
  3. "context"
  4. "hash/crc32"
  5. "log"
  6. "math"
  7. "regexp"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/go-redis/redis/v8"
  12. )
  13. type GoRedis struct {
  14. Addr string
  15. Password string
  16. Code string
  17. DB int
  18. DBS []int //数据库列表
  19. HashDb bool //是否是多个数据库
  20. PoolSize int
  21. MinIdleConns int
  22. IdleTimeout int
  23. Ctx context.Context
  24. C *redis.Client
  25. BakDb bool //是否有备用节点
  26. Bak *GoRedis //备用节点连接
  27. }
  28. //初始化单个"[other=]127.0.0.1:2203|127.0.0.1:2204=0-1=1-10=300" [代码]、地址[|备用地址,&集群地址]、库、最大池、空闲时间默认300秒
  29. func (r *GoRedis) Init(opt interface{}) {
  30. check := false
  31. code, addr, dbs, pool, idle := "", "", []int{0}, []int{2, 30}, 300
  32. if so, ok := opt.(string); ok {
  33. arr := strings.Split(so, "=")
  34. regAddr := regexp.MustCompile("[0-9.a-zA-Z/]+:[0-9]+.*")
  35. if len(arr) == 1 {
  36. if regAddr.MatchString(arr[0]) {
  37. check = true
  38. addr = arr[0]
  39. }
  40. } else if len(arr) > 1 {
  41. index := 0
  42. if regAddr.MatchString(arr[0]) {
  43. index = 1
  44. addr = arr[0]
  45. check = true
  46. } else if regAddr.MatchString(arr[1]) {
  47. check = true
  48. addr = arr[1]
  49. code = arr[0]
  50. }
  51. //解析库配置
  52. if len(arr) > 2-index { //dbs配置
  53. dbs1 := strings.Split(arr[2-index], "-")
  54. if len(dbs1) == 1 || len(dbs1) == 2 {
  55. check = true
  56. dbs[0], _ = strconv.Atoi(dbs1[0])
  57. if len(dbs1) == 2 {
  58. tmp, _ := strconv.Atoi(dbs1[1])
  59. dbs = append(dbs, tmp)
  60. }
  61. } else {
  62. check = false
  63. }
  64. //解析连接池配置
  65. if len(arr) > 3-index {
  66. pool1 := strings.Split(arr[3-index], "-")
  67. if len(pool1) == 1 || len(pool1) == 2 {
  68. check = true
  69. if len(pool1) == 1 {
  70. pool[1], _ = strconv.Atoi(pool1[0])
  71. pool[0] = int(math.Ceil(float64(pool[1]) * 0.2))
  72. } else {
  73. pool[0], _ = strconv.Atoi(pool1[0])
  74. pool[1], _ = strconv.Atoi(pool1[1])
  75. }
  76. } else {
  77. check = false
  78. }
  79. //解析最大空闲时间配置
  80. if len(arr) > 4-index {
  81. idle, _ = strconv.Atoi(arr[4-index])
  82. if idle == 0 {
  83. idle = 300
  84. }
  85. }
  86. }
  87. }
  88. }
  89. } else if _, ok := opt.(map[string]interface{}); ok {
  90. }
  91. if check {
  92. addrs := strings.Split(addr, "|")
  93. r.Addr = addrs[0]
  94. r.Code = code
  95. r.DB = dbs[0]
  96. //DBS []int
  97. r.PoolSize = pool[1]
  98. r.MinIdleConns = pool[0]
  99. r.IdleTimeout = idle
  100. r.Ctx = context.Background()
  101. r.C = redis.NewClient(&redis.Options{
  102. Addr: r.Addr,
  103. DB: r.DB,
  104. PoolSize: r.PoolSize,
  105. MinIdleConns: r.MinIdleConns,
  106. IdleTimeout: time.Duration(r.IdleTimeout) * time.Second,
  107. })
  108. if len(dbs) > 1 {
  109. r.HashDb = true
  110. r.DBS = []int{}
  111. for i := dbs[0]; i <= dbs[1]; i++ {
  112. r.DBS = append(r.DBS, i)
  113. }
  114. }
  115. if len(addrs) == 2 {
  116. r.BakDb = true
  117. //有备用节点,集群先不考虑
  118. r.Bak = &GoRedis{}
  119. r.Bak.Addr = addrs[1]
  120. r.Bak.Code = code
  121. r.Bak.DB = dbs[0]
  122. r.Bak.DBS = r.DBS
  123. r.Bak.HashDb = r.HashDb
  124. r.Bak.PoolSize = pool[1]
  125. r.Bak.MinIdleConns = pool[0]
  126. r.Bak.IdleTimeout = idle
  127. r.Bak.Ctx = context.Background()
  128. r.Bak.C = redis.NewClient(&redis.Options{
  129. Addr: r.Bak.Addr,
  130. DB: r.Bak.DB,
  131. PoolSize: r.Bak.PoolSize,
  132. MinIdleConns: r.Bak.MinIdleConns,
  133. IdleTimeout: time.Duration(r.Bak.IdleTimeout) * time.Second,
  134. })
  135. }
  136. }
  137. log.Println(check, code, addr, dbs, pool, idle, r.DBS)
  138. }
  139. func NewGoRedis(Addr, Password, Code string, DB, PoolSize, MinIdleConns, IdleTimeout int) *GoRedis {
  140. r := &GoRedis{}
  141. r.C = redis.NewClient(&redis.Options{
  142. Addr: Addr,
  143. Password: Password,
  144. DB: DB,
  145. PoolSize: PoolSize,
  146. MinIdleConns: MinIdleConns,
  147. IdleTimeout: time.Duration(IdleTimeout) * time.Second,
  148. })
  149. return r
  150. }
  151. func (r *GoRedis) Put(key string, val interface{}) {
  152. var stutsCmd *redis.StatusCmd
  153. if r.HashDb { //有多个库
  154. r.selectDB(key)
  155. stutsCmd = r.C.Set(r.Ctx, key, val, 0)
  156. } else {
  157. stutsCmd = r.C.Set(r.Ctx, key, val, 0)
  158. }
  159. str, err := stutsCmd.Result()
  160. log.Println(str, err)
  161. }
  162. //此处切换失败!!!,只能切换取到的连接,不会切换Client,待验证
  163. func (r *GoRedis) selectDB(key string) {
  164. db := r.DBS[hashCode(key)%len(r.DBS)] //取存哪个db,可以提取出来一个方法
  165. r.C.Conn(r.Ctx).Select(r.Ctx, db) //切换数据库
  166. }
  167. func hashCode(key string) int {
  168. v := int(crc32.ChecksumIEEE([]byte(key)))
  169. if v < 0 {
  170. v = -v
  171. }
  172. return v
  173. }