redisutil.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. /**
  2. redis_util Redis工具包<br/>
  3. 作者:hongbo<br/>
  4. 日期:2020-4-22<br/>
  5. */
  6. package redis_util
  7. import (
  8. "encoding/json"
  9. "errors"
  10. "log"
  11. "runtime"
  12. "strings"
  13. "time"
  14. redigo "github.com/garyburd/redigo/redis"
  15. )
  16. // RedisPool redis 多服务端连接池,1个应用同时连接多个redis服务
  17. var RedisPool map[string]*redigo.Pool
  18. // InitRedis 初始化redis 多端连接池 <br/>
  19. // @param addrs enterprise=192.168.3.14:1379,service=192.168.3.14:2379,other=192.168.3.14:3379
  20. func InitRedis(addrs string) {
  21. InitRedisBySize(addrs, 300, 30, 240)
  22. }
  23. //初始化redis连接池,支持多个redis库
  24. func InitRedisBySize(addrs string, maxSize, maxIdle, timeout int) {
  25. RedisPool = map[string]*redigo.Pool{}
  26. addr := strings.Split(addrs, ",")
  27. for _, v := range addr {
  28. saddr := strings.Split(v, "=")
  29. RedisPool[saddr[0]] = &redigo.Pool{MaxActive: maxSize, MaxIdle: maxIdle,
  30. IdleTimeout: time.Duration(timeout) * time.Second, Dial: func() (redigo.Conn, error) {
  31. return redigo.Dial("tcp", saddr[1])
  32. }}
  33. }
  34. }
  35. // PutKV 分流redis ,并存入字符串缓存
  36. // Output: bool 是否存储成功
  37. func PutKV(key string, obj interface{}) bool {
  38. return Put("other", key, obj, -1)
  39. }
  40. func PutCKV(code, key string, obj interface{}) bool {
  41. return Put(code, key, obj, -1)
  42. }
  43. func Put(code, key string, obj interface{}, timeout int) bool {
  44. b := false
  45. defer catch()
  46. conn := RedisPool[code].Get()
  47. defer conn.Close()
  48. var err error
  49. _obj, _err := json.Marshal(obj)
  50. if _err != nil {
  51. log.Println("redisutil-SET-序列化出错Error", _err)
  52. return b
  53. }
  54. if timeout < 1 {
  55. _, err = conn.Do("SET", key, _obj)
  56. } else {
  57. _, err = conn.Do("SET", key, _obj, "EX", timeout)
  58. }
  59. if nil != err {
  60. log.Println("redisutil-SETError-put", err)
  61. } else {
  62. b = true
  63. }
  64. return b
  65. }
  66. func BulkPut(code string, timeout int, obj ...interface{}) bool {
  67. b := false
  68. defer catch()
  69. conn := RedisPool[code].Get()
  70. defer conn.Close()
  71. var err error
  72. for _, _tmp := range obj {
  73. tmp, ok := _tmp.([]interface{})
  74. if ok && len(tmp) == 2 {
  75. key, kok := tmp[0].(string)
  76. if kok && key != "" {
  77. _obj, _err := json.Marshal(tmp[1])
  78. if _err != nil {
  79. log.Println("redisutil-SET-序列化出错Error", _err)
  80. return b
  81. }
  82. if timeout < 1 {
  83. _, err = conn.Do("SET", key, _obj)
  84. } else {
  85. _, err = conn.Do("SET", key, _obj, "EX", timeout)
  86. }
  87. }
  88. }
  89. }
  90. if nil != err {
  91. b = false
  92. log.Println("redisutil-SETError-put", err)
  93. } else {
  94. b = b && true
  95. }
  96. return b
  97. }
  98. //直接存字节流
  99. func PutBytes(code, key string, data *[]byte, timeout int) (err error) {
  100. defer catch()
  101. conn := RedisPool[code].Get()
  102. defer conn.Close()
  103. if timeout < 1 {
  104. _, err = conn.Do("SET", key, *data)
  105. } else {
  106. _, err = conn.Do("SET", key, *data, "EX", timeout)
  107. }
  108. if nil != err {
  109. log.Println("redisutil-SETError", err)
  110. }
  111. return
  112. }
  113. //设置超时时间,单位秒
  114. func SetExpire(code, key string, expire int) error {
  115. defer catch()
  116. conn := RedisPool[code].Get()
  117. defer conn.Close()
  118. _, err := conn.Do("expire", key, expire)
  119. return err
  120. }
  121. //判断一个key是否存在
  122. func Exists(code, key string) (bool, error) {
  123. defer catch()
  124. conn := RedisPool[code].Get()
  125. defer conn.Close()
  126. repl, err := conn.Do("exists", key)
  127. ret, _ := redigo.Int(repl, err)
  128. return ret == 1, err
  129. }
  130. //获取string
  131. func GetStr(code, key string) string {
  132. res := Get(code, key)
  133. str, _ := res.(string)
  134. return str
  135. }
  136. //获取int
  137. func GetInt(code, key string) int {
  138. result, _ := GetNewInt(code, key)
  139. return result
  140. }
  141. func GetNewInt(code, key string) (int, error) {
  142. var res interface{}
  143. err := GetNewInterface(code, key, &res)
  144. var result int
  145. if str, ok := res.(float64); ok {
  146. result = int(str)
  147. }
  148. return result, err
  149. }
  150. //取得字符串,支持变参,2个 (key,code),返回后自己断言
  151. func Get(code, key string) (result interface{}) {
  152. GetInterface(code, key, &result)
  153. return
  154. }
  155. func GetInterface(code, key string, result interface{}) {
  156. GetNewInterface(code, key, result)
  157. }
  158. func GetNewInterface(code, key string, result interface{}) error {
  159. defer catch()
  160. conn := RedisPool[code].Get()
  161. defer conn.Close()
  162. ret, err := conn.Do("GET", key)
  163. if nil != err {
  164. log.Println("redisutil-GetError", err)
  165. } else {
  166. var ok bool
  167. var res []byte
  168. if res, ok = ret.([]byte); ok {
  169. err = json.Unmarshal(res, result)
  170. if err != nil {
  171. log.Println("Get ERROR:", err.Error())
  172. }
  173. }
  174. }
  175. return err
  176. }
  177. //直接返回字节流
  178. func GetBytes(code, key string) (ret *[]byte, err error) {
  179. defer catch()
  180. conn := RedisPool[code].Get()
  181. defer conn.Close()
  182. var r interface{}
  183. r, err = conn.Do("GET", key)
  184. if err != nil {
  185. log.Println("redisutil-GetBytesError", err)
  186. } else {
  187. if tmp, ok := r.([]byte); ok {
  188. ret = &tmp
  189. } else {
  190. err = errors.New("redis返回数据格式不对")
  191. }
  192. }
  193. return
  194. }
  195. func GetNewBytes(code, key string) (ret *[]byte, err error) {
  196. defer catch()
  197. redisPool := RedisPool[code]
  198. if redisPool == nil {
  199. err = errors.New("redis code " + code + " is nil")
  200. log.Println("redisutil-GetNewBytesError", err)
  201. return
  202. }
  203. conn := redisPool.Get()
  204. defer conn.Close()
  205. var r interface{}
  206. r, err = conn.Do("GET", key)
  207. if err != nil {
  208. log.Println("redisutil-GetNewBytesError", err)
  209. } else if r != nil {
  210. if tmp, ok := r.([]byte); ok {
  211. ret = &tmp
  212. }
  213. }
  214. return
  215. }
  216. //删所有key
  217. func FlushDB(code string) bool {
  218. b := false
  219. defer catch()
  220. conn := RedisPool[code].Get()
  221. defer conn.Close()
  222. var err error
  223. _, err = conn.Do("FLUSHDB")
  224. if nil != err {
  225. log.Println("redisutil-FLUSHDBError", err)
  226. } else {
  227. b = true
  228. }
  229. return b
  230. }
  231. //支持删除多个key
  232. func Del(code string, key ...interface{}) bool {
  233. defer catch()
  234. b := false
  235. conn := RedisPool[code].Get()
  236. defer conn.Close()
  237. var err error
  238. _, err = conn.Do("DEL", key...)
  239. if nil != err {
  240. log.Println("redisutil-DELError", err)
  241. } else {
  242. b = true
  243. }
  244. return b
  245. }
  246. //
  247. //func GetCacheByMgo(key, coll, sql, show string, ftype, timeout int) map[string]interface{} {
  248. // obj := Get("", key)
  249. // if nil == obj {
  250. // switch ftype {
  251. // case 1:
  252. // m := mongodb.FindById(coll, sql, show)
  253. // if m != nil && len(*m) > 0 {
  254. // Put("", key, *m, timeout)
  255. // }
  256. // return *m
  257. // break
  258. // }
  259. // return nil
  260. // } else {
  261. // res, _ := obj.(map[string]interface{})
  262. // return res
  263. // }
  264. //
  265. //}
  266. //根据代码和前辍key删除多个
  267. func DelByCodePattern(code, key string) {
  268. defer catch()
  269. conn := RedisPool[code].Get()
  270. defer conn.Close()
  271. ret, err := conn.Do("KEYS", key)
  272. var result []interface{}
  273. if nil != err {
  274. log.Println("redisutil-GetError", err)
  275. } else {
  276. result = ret.([]interface{})
  277. for k := 0; k < len(result); k++ {
  278. conn.Do("DEL", string(result[k].([]uint8)))
  279. }
  280. }
  281. }
  282. /**
  283. func DelByPattern(key string) {
  284. defer func() {
  285. if r := recover(); r != nil {
  286. log.Println("[E]", r)
  287. for skip := 1; ; skip++ {
  288. _, file, line, ok := runtime.Caller(skip)
  289. if !ok {
  290. break
  291. }
  292. go log.Printf("%v,%v\n", file, line)
  293. }
  294. }
  295. }()
  296. i := 0
  297. for _, v := range RedisPool {
  298. conn := v.Get()
  299. defer conn.Close()
  300. ret, err := conn.Do("KEYS", key)
  301. var result []interface{}
  302. if nil != err {
  303. log.Println("redisutil-GetError", err)
  304. } else {
  305. result = ret.([]interface{})
  306. for k := 0; k < len(result); k++ {
  307. delByNum(i, string(result[k].([]uint8)))
  308. }
  309. }
  310. i++
  311. }
  312. }
  313. **/
  314. //自增计数器
  315. func Incr(code, key string) int64 {
  316. defer catch()
  317. conn := RedisPool[code].Get()
  318. defer conn.Close()
  319. ret, err := conn.Do("INCR", key)
  320. if nil != err {
  321. log.Println("redisutil-INCR-Error", err)
  322. } else {
  323. if res, ok := ret.(int64); ok {
  324. return res
  325. } else {
  326. return 0
  327. }
  328. }
  329. return 0
  330. }
  331. //自减
  332. func Decrby(code, key string, val int) int64 {
  333. defer catch()
  334. conn := RedisPool[code].Get()
  335. defer conn.Close()
  336. ret, err := conn.Do("DECRBY", key, val)
  337. if nil != err {
  338. log.Println("redisutil-DECR-Error", err)
  339. } else {
  340. if res, ok := ret.(int64); ok {
  341. return res
  342. } else {
  343. return 0
  344. }
  345. }
  346. return 0
  347. }
  348. //根据正则去取
  349. func GetKeysByPattern(code, key string) []interface{} {
  350. defer catch()
  351. conn := RedisPool[code].Get()
  352. defer conn.Close()
  353. ret, err := conn.Do("KEYS", key)
  354. if nil != err {
  355. log.Println("redisutil-GetKeysError", err)
  356. return nil
  357. } else {
  358. res, _ := ret.([]interface{})
  359. return res
  360. }
  361. }
  362. //批量取多个key
  363. func Mget(code string, key []string) []interface{} {
  364. defer catch()
  365. conn := RedisPool[code].Get()
  366. defer conn.Close()
  367. interfaceKeys := make([]interface{}, len(key))
  368. for n, k := range key {
  369. interfaceKeys[n] = k
  370. }
  371. ret, err := conn.Do("MGET", interfaceKeys...)
  372. if nil != err {
  373. log.Println("redisutil-MgetError", err)
  374. return nil
  375. } else {
  376. res, _ := ret.([]interface{})
  377. return res
  378. }
  379. }
  380. //取出并删除Key
  381. func Pop(code string, key string) (result interface{}) {
  382. defer catch()
  383. conn := RedisPool[code].Get()
  384. defer conn.Close()
  385. ret, err := conn.Do("GET", key)
  386. if nil != err {
  387. log.Println("redisutil-PopError", err)
  388. } else {
  389. var ok bool
  390. var res []byte
  391. if res, ok = ret.([]byte); ok {
  392. err = json.Unmarshal(res, &result)
  393. if err != nil {
  394. log.Println("Poperr", err)
  395. }
  396. }
  397. conn.Do("DEL", key)
  398. }
  399. return
  400. }
  401. //list操作
  402. func LPOP(code, list string) (result interface{}) {
  403. defer catch()
  404. conn := RedisPool[code].Get()
  405. defer conn.Close()
  406. ret, err := conn.Do("LPOP", list)
  407. if nil != err {
  408. log.Println("redisutil-LPopError", err)
  409. } else {
  410. if res, ok := ret.([]byte); ok {
  411. err = json.Unmarshal(res, &result)
  412. log.Println(err)
  413. }
  414. }
  415. return
  416. }
  417. func RPUSH(code, list string, val interface{}) bool {
  418. defer catch()
  419. conn := RedisPool[code].Get()
  420. defer conn.Close()
  421. _obj, _ := json.Marshal(val)
  422. _, err := conn.Do("RPUSH", list, _obj)
  423. if nil != err {
  424. log.Println("redisutil-RPUSHError", err)
  425. return false
  426. }
  427. return true
  428. }
  429. func LLEN(code, list string) int64 {
  430. defer catch()
  431. conn := RedisPool[code].Get()
  432. defer conn.Close()
  433. ret, err := conn.Do("LLEN", list)
  434. if nil != err {
  435. log.Println("redisutil-LLENError", err)
  436. return 0
  437. }
  438. if res, ok := ret.(int64); ok {
  439. return res
  440. } else {
  441. return 0
  442. }
  443. }
  444. func catch() {
  445. if r := recover(); r != nil {
  446. log.Println(r)
  447. for skip := 0; ; skip++ {
  448. _, file, line, ok := runtime.Caller(skip)
  449. if !ok {
  450. break
  451. }
  452. go log.Printf("%v,%v\n", file, line)
  453. }
  454. }
  455. }