redis.go 4.6 KB

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