redis.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package redispool
  2. import (
  3. "errors"
  4. "leafstalk/covenant/monitor"
  5. "strconv"
  6. "time"
  7. "github.com/gomodule/redigo/redis"
  8. )
  9. type RedisPool struct {
  10. pool *redis.Pool
  11. }
  12. func NewRedisPool(addr string, password string, db int) *RedisPool {
  13. pool := redis.Pool{
  14. MaxIdle: 10,
  15. IdleTimeout: 240 * time.Second,
  16. // Dial or DialContext must be set. When both are set, DialContext takes precedence over Dial.
  17. Dial: func() (redis.Conn, error) {
  18. c, err := redis.Dial("tcp", addr)
  19. if err != nil {
  20. return nil, err
  21. }
  22. if len(password) != 0 {
  23. if _, err := c.Do("AUTH", password); err != nil {
  24. c.Close()
  25. return nil, err
  26. }
  27. }
  28. if _, err := c.Do("SELECT", db); err != nil {
  29. c.Close()
  30. return nil, err
  31. }
  32. return c, nil
  33. },
  34. TestOnBorrow: func(c redis.Conn, t time.Time) error {
  35. if time.Since(t) < time.Minute {
  36. return nil
  37. }
  38. _, err := c.Do("PING")
  39. return err
  40. },
  41. }
  42. rp := new(RedisPool)
  43. rp.pool = &pool
  44. return rp
  45. }
  46. // CloseRedisPool 关闭reids池
  47. func (r *RedisPool) Close() {
  48. if r.pool != nil {
  49. r.pool.Close()
  50. }
  51. }
  52. func (r *RedisPool) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
  53. defer monitor.RedisDoTimeoutWarn("Do", map[string]interface{}{
  54. "commandName": commandName,
  55. "args": args,
  56. }, time.Now())
  57. conn := r.pool.Get()
  58. defer conn.Close()
  59. return conn.Do(commandName, args...)
  60. }
  61. func (r *RedisPool) DoMulti(f func(conn redis.Conn) error) error {
  62. defer monitor.RedisDoTimeoutWarn("DoMulti", "", time.Now())
  63. conn := r.pool.Get()
  64. defer conn.Close()
  65. return f(conn)
  66. }
  67. // 保存一个集合
  68. func (r *RedisPool) DoFlat(commandName string, key string, val interface{}) (reply interface{}, err error) {
  69. conn := r.pool.Get()
  70. defer conn.Close()
  71. //组织为串
  72. return conn.Do(commandName, redis.Args{key}.AddFlat(val)...)
  73. }
  74. func (r *RedisPool) IsNilError(err error) bool {
  75. return err == redis.ErrNil
  76. }
  77. func (r *RedisPool) DoHashSet(key string, val interface{}) (reply interface{}, err error) {
  78. conn := r.pool.Get()
  79. defer conn.Close()
  80. //以hash类型保存
  81. return conn.Do("hmset", redis.Args{key}.AddFlat(val)...)
  82. }
  83. func (r *RedisPool) DoHashGet(key string, strc interface{}) (interface{}, error) {
  84. conn := r.pool.Get()
  85. defer conn.Close()
  86. //获取缓存
  87. value, err := redis.Values(conn.Do("hgetall", key))
  88. if err != nil {
  89. if r.IsNilError(err) {
  90. return nil, nil
  91. }
  92. return nil, err
  93. }
  94. if len(value) == 0 {
  95. return nil, errors.New("value is nil")
  96. }
  97. //将values转成结构体 只能使用简单
  98. err = redis.ScanStruct(value, strc)
  99. if err != nil {
  100. return nil, err
  101. }
  102. return strc, nil
  103. }
  104. // 模糊匹配搜索
  105. func (r *RedisPool) ScanKeys(start int, pattern string, count int) (int, []string, error) {
  106. rep, err := r.Do("scan", start, "match", pattern, "count", count)
  107. if err != nil {
  108. return 0, nil, err
  109. }
  110. rep2 := rep.([]interface{})
  111. if len(rep2) != 2 {
  112. return 0, nil, errors.New("replay length is error")
  113. }
  114. nextSt := ""
  115. if strSt, ok := rep2[0].([]byte); !ok {
  116. return 0, nil, errors.New("replay type is error")
  117. } else {
  118. nextSt = string(strSt)
  119. }
  120. var lst []string
  121. if ks, ok := rep2[1].([]interface{}); !ok {
  122. return 0, nil, errors.New("replay type is error")
  123. } else {
  124. for _, v := range ks {
  125. if nv, ok := v.([]byte); ok {
  126. k := string(nv)
  127. lst = append(lst, k)
  128. }
  129. }
  130. }
  131. st, err := strconv.Atoi(nextSt)
  132. if err != nil {
  133. return 0, lst, nil
  134. }
  135. return st, lst, nil
  136. }
  137. func (r *RedisPool) ColScan(scanCmd string, key string, start int, pattern string, count int) (int, interface{}, error) {
  138. rep, err := redis.Values(r.Do(scanCmd, key, start, "match", pattern, "count", count))
  139. if err != nil {
  140. return 0, nil, err
  141. }
  142. next, err := redis.Int(rep[0], err)
  143. if err != nil {
  144. return 0, nil, err
  145. }
  146. // kvs, err := redis.StringMap(rep[1], err)
  147. // if err != nil {
  148. // return 0, nil, err
  149. // }
  150. // st, err := strconv.Atoi(next)
  151. // if err != nil {
  152. // return 0, kvs, nil
  153. // }
  154. return next, rep[1], err
  155. }
  156. func test() {
  157. //onlinestate.Do("SET", "foo", "bar")
  158. // currentTimeStart := time.Now()
  159. // onlinestate.DoMulti(func(conn redis.Conn) error {
  160. // for i := 0; i < 100000; i++ {
  161. // conn.Do("INCR", "TESTKEY")
  162. // }
  163. // return err
  164. // })
  165. // fmt.Println(time.Since(currentTimeStart))
  166. // currentTimeStart = time.Now()
  167. // onlinestate.DoMulti(func(conn redis.Conn) error {
  168. // for i := 0; i < 100000; i++ {
  169. // conn.Send("INCR", "TESTKEY")
  170. // }
  171. // conn.Flush()
  172. // conn.Receive()
  173. // return err
  174. // })
  175. // fmt.Println(time.Since(currentTimeStart))
  176. // currentTimeStart = time.Now()
  177. // onlinestate.DoMulti(func(conn redis.Conn) error {
  178. // for i := 0; i < 100000; i++ {
  179. // conn.Send("INCR", "TESTKEY")
  180. // conn.Flush()
  181. // }
  182. // conn.Receive()
  183. // return err
  184. // })
  185. // fmt.Println(time.Since(currentTimeStart))
  186. }