redis.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package dao
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "strconv"
  7. "go-common/app/job/main/dm/model"
  8. "go-common/library/cache/redis"
  9. "go-common/library/log"
  10. )
  11. const (
  12. _keyIdxContent = "c_%d_%d" // dm content hash(c_type_oid, dmid, xml)
  13. _keyTrimQueue = "tq_n_%d_%d" // trim queue if dm_count > dm_maxlimit
  14. divide = int64(34359738368) // 2^35
  15. )
  16. // keyIdxContent return key of different dm.
  17. func keyIdxContent(typ int32, oid int64) string {
  18. return fmt.Sprintf(_keyIdxContent, typ, oid)
  19. }
  20. // keyIdxQueue return trim queue key.
  21. func keyTrimQueue(tp int32, oid int64) string {
  22. return fmt.Sprintf(_keyTrimQueue, tp, oid)
  23. }
  24. // ExpireTrimQueue set expire time of index.
  25. func (d *Dao) ExpireTrimQueue(c context.Context, tp int32, oid int64) (ok bool, err error) {
  26. key := keyTrimQueue(tp, oid)
  27. conn := d.redis.Get(c)
  28. if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.redisExpire)); err != nil {
  29. log.Error("conn.Do(EXPIRE %s) error(%v)", key, err)
  30. }
  31. conn.Close()
  32. return
  33. }
  34. func score(attr int32, id int64) (score float64) {
  35. v := id / divide // 2^63 / 2^35 = 2^28-1 整数部分最大值:268435455
  36. k := id % divide // 精度8位,最后5位可忽略
  37. r := int64(attr)&1<<28 | v // NOTE v should less than 2^28
  38. score, _ = strconv.ParseFloat(fmt.Sprintf("%d.%d", r, k), 64)
  39. return
  40. }
  41. // AddTrimQueueCache add dm index into trim queue.
  42. func (d *Dao) AddTrimQueueCache(c context.Context, tp int32, oid int64, trims []*model.Trim) (count int64, err error) {
  43. var (
  44. key = keyTrimQueue(tp, oid)
  45. conn = d.redis.Get(c)
  46. )
  47. defer conn.Close()
  48. for _, trim := range trims {
  49. if err = conn.Send("ZADD", key, score(trim.Attr, trim.ID), trim.ID); err != nil {
  50. log.Error("conn.Send(ZADD %s %v) error(%v)", key, trim, err)
  51. return
  52. }
  53. }
  54. if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
  55. log.Error("conn.Send(EXPIRE %s) error(%v)", key, err)
  56. return
  57. }
  58. if err = conn.Send("ZCARD", key); err != nil {
  59. log.Error("conn.Send(ZCARD %s) error(%v)", key, err)
  60. return
  61. }
  62. if err = conn.Flush(); err != nil {
  63. log.Error("conn.Flush() error(%v)", err)
  64. return
  65. }
  66. for i := 0; i < len(trims)+1; i++ {
  67. if _, err = conn.Receive(); err != nil {
  68. log.Error("conn.Receive() error(%v)", err)
  69. return
  70. }
  71. }
  72. if count, err = redis.Int64(conn.Receive()); err != nil {
  73. log.Error("conn.Receive() error(%v)", err)
  74. }
  75. return
  76. }
  77. // FlushTrimCache flush trim queue cache.
  78. func (d *Dao) FlushTrimCache(c context.Context, tp int32, oid int64, trims []*model.Trim) (err error) {
  79. var (
  80. key = keyTrimQueue(tp, oid)
  81. conn = d.redis.Get(c)
  82. )
  83. defer conn.Close()
  84. for _, trim := range trims {
  85. if err = conn.Send("ZADD", key, score(trim.Attr, trim.ID), trim.ID); err != nil {
  86. log.Error("conn.Send(ZADD %s %v) error(%v)", key, trim, err)
  87. return
  88. }
  89. }
  90. if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
  91. log.Error("conn.Send(EXPIRE %s) error(%v)", key, err)
  92. return
  93. }
  94. if err = conn.Flush(); err != nil {
  95. log.Error("conn.Flush(%s) error(%v)", key, err)
  96. return
  97. }
  98. for i := 0; i < len(trims)+1; i++ {
  99. if _, err = conn.Receive(); err != nil {
  100. log.Error("conn.Receive() error(%v)", err)
  101. return
  102. }
  103. }
  104. return
  105. }
  106. // ZRemTrimCache ZREM trim from trim queue.
  107. func (d *Dao) ZRemTrimCache(c context.Context, tp int32, oid int64, dmID int64) (err error) {
  108. var (
  109. key = keyTrimQueue(tp, oid)
  110. conn = d.redis.Get(c)
  111. )
  112. if _, err = conn.Do("ZREM", key, dmID); err != nil {
  113. log.Error("conn.Do(ZREM %s %v) error(%v)", key, dmID, err)
  114. }
  115. conn.Close()
  116. return
  117. }
  118. // TrimCache trim trim queue and return trimed dmid from trim queue.
  119. func (d *Dao) TrimCache(c context.Context, tp int32, oid, count int64) (dmids []int64, err error) {
  120. var (
  121. key = keyTrimQueue(tp, oid)
  122. conn = d.redis.Get(c)
  123. replys [][]byte
  124. dmID int64
  125. )
  126. defer conn.Close()
  127. if replys, err = redis.ByteSlices(conn.Do("ZRANGE", key, 0, count-1)); err != nil {
  128. log.Error("conn.Do(ZRANGE %s) error(%v)", key, err)
  129. return
  130. }
  131. for _, reply := range replys {
  132. if err = json.Unmarshal(reply, &dmID); err != nil {
  133. log.Error("json.Unmarshal(%s) error(v)", string(reply), err)
  134. return
  135. }
  136. dmids = append(dmids, dmID)
  137. }
  138. if len(dmids) > 0 {
  139. if _, err = conn.Do("ZREMRANGEBYRANK", key, 0, len(dmids)-1); err != nil {
  140. log.Error("conn.Do(ZREMRANGEBYRANK %s) error(%v)", key, err)
  141. }
  142. }
  143. return
  144. }
  145. // DelIdxContentCaches del index content cache.
  146. func (d *Dao) DelIdxContentCaches(c context.Context, typ int32, oid int64, dmids ...int64) (err error) {
  147. key := keyIdxContent(typ, oid)
  148. conn := d.redis.Get(c)
  149. args := []interface{}{key}
  150. for _, dmid := range dmids {
  151. args = append(args, dmid)
  152. }
  153. if _, err = conn.Do("HDEL", args...); err != nil {
  154. log.Error("conn.Do(HDEL %s) error(%v)", key, err)
  155. }
  156. conn.Close()
  157. return
  158. }