memcache.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package exp
  2. import (
  3. "context"
  4. expModel "go-common/app/service/live/xuser/model/exp"
  5. gmc "go-common/library/cache/memcache"
  6. "go-common/library/log"
  7. "go-common/library/stat/prom"
  8. "go-common/library/sync/errgroup"
  9. "math/rand"
  10. "strconv"
  11. "time"
  12. )
  13. // redis cache
  14. const (
  15. _prefixExp = "json_e_" // 用户经验cache key,json协议
  16. _emptyExpire = 20 * 24 * 3600
  17. _errorMcLogPrefix = "xuser.exp.dao.memcache"
  18. _promGetSuccess = "xuser_exp_mc:获取用户经验cache成功"
  19. _promDelSuccess = "xuser_exp_mc:成功删除用户经验cache"
  20. _promDelErr = "xuser_exp_mc:删除用户经验cache失败"
  21. _promGetErr = "xuser_exp_mc:批量获取用户经验key失败"
  22. _promScanErr = "xuser_exp_mc:解析用户经验key失败"
  23. // _recExpire = 5 * 24 * 3600
  24. )
  25. var (
  26. errorsCount = prom.BusinessErrCount
  27. infosCount = prom.BusinessInfoCount
  28. cacheHitCount = prom.CacheHit
  29. cacheMissCount = prom.CacheMiss
  30. )
  31. // PromError prometheus error count.
  32. func PromError(name string) {
  33. errorsCount.Incr(name)
  34. }
  35. // PromInfo prometheus info count.
  36. func PromInfo(name string) {
  37. infosCount.Incr(name)
  38. }
  39. // PromCacheHit prometheus cache hit count.
  40. func PromCacheHit(name string) {
  41. cacheHitCount.Incr(name)
  42. }
  43. // PromCacheMiss prometheus cache hit count.
  44. func PromCacheMiss(name string) {
  45. cacheMissCount.Incr(name)
  46. }
  47. func expKey(mid int64) string {
  48. return _prefixExp + strconv.FormatInt(mid, 10)
  49. }
  50. // SetExpListCache 批量设置用户经验cache
  51. func (d *Dao) SetExpListCache(c context.Context, expList map[int64]*expModel.LevelInfo) (err error) {
  52. return d.setExpListCache(c, expList)
  53. }
  54. // DelExpFromMemCache 删除获取用户经验cache,不支持批量
  55. func (d *Dao) DelExpFromMemCache(c context.Context, mid int64) (err error) {
  56. return d.delExpFromMemCache(c, expKey(mid))
  57. }
  58. // GetExpFromMemCache 对外接口
  59. func (d *Dao) GetExpFromMemCache(ctx context.Context, mids []int64) (expList map[int64]*expModel.LevelInfo, missedUids []int64, err error) {
  60. return d.getExpFromMemCache(ctx, mids)
  61. }
  62. // getExpFromMemCache 批量获取用户经验cache
  63. func (d *Dao) getExpFromMemCache(ctx context.Context, mids []int64) (expList map[int64]*expModel.LevelInfo, arrayMissedUids []int64, err error) {
  64. var expKeys []string
  65. expList = make(map[int64]*expModel.LevelInfo)
  66. mapMissedUids := make(map[int64]bool)
  67. arrayMissedUids = make([]int64, 0)
  68. for _, uid := range mids {
  69. expKeys = append(expKeys, expKey(uid))
  70. mapMissedUids[uid] = true
  71. }
  72. group := errgroup.Group{}
  73. group.Go(func() error {
  74. conn := d.memcache.Get(context.TODO())
  75. defer conn.Close()
  76. resp, err := conn.GetMulti(expKeys)
  77. if err != nil {
  78. PromError(_promGetErr)
  79. log.Error(_errorMcLogPrefix+"|conn.Gets(%v) error(%v)", expKeys, err)
  80. return nil
  81. }
  82. // miss uids
  83. for _, item := range resp {
  84. element := &expModel.LevelInfo{}
  85. if err = conn.Scan(item, &element); err != nil {
  86. PromError(_promScanErr)
  87. log.Error(_errorMcLogPrefix+"|item.Scan(%s) error(%v)", item.Value, err)
  88. return err
  89. }
  90. expList[element.UID] = element
  91. mapMissedUids[element.UID] = false
  92. }
  93. return nil
  94. })
  95. group.Wait()
  96. for k, v := range mapMissedUids {
  97. if v {
  98. arrayMissedUids = append(arrayMissedUids, k)
  99. }
  100. }
  101. PromInfo(_promGetSuccess)
  102. return
  103. }
  104. func (d *Dao) delExpFromMemCache(ctx context.Context, key string) (err error) {
  105. conn := d.memcache.Get(ctx)
  106. if err = conn.Delete(key); err != nil {
  107. if err == gmc.ErrNotFound {
  108. err = nil
  109. } else {
  110. log.Error(_errorMcLogPrefix+"|Delete(%s) error(%v)", key, err)
  111. PromError(_promDelErr)
  112. }
  113. }
  114. PromInfo(_promDelSuccess)
  115. conn.Close()
  116. return
  117. }
  118. func (d *Dao) setExpListCache(ctx context.Context, expList map[int64]*expModel.LevelInfo) (err error) {
  119. expire := d.getExpire()
  120. rand.Seed(time.Now().UnixNano())
  121. expire = expire + rand.Int31n(3600)
  122. conn := d.memcache.Get(context.TODO())
  123. defer conn.Close()
  124. for _, v := range expList {
  125. item := &gmc.Item{Key: expKey(v.UID),
  126. Object: &expModel.LevelInfo{UID: v.UID, UserLevel: v.UserLevel, AnchorLevel: v.AnchorLevel, CTime: v.CTime, MTime: v.MTime},
  127. Expiration: expire, Flags: gmc.FlagJSON}
  128. err := conn.Set(item)
  129. if err != nil {
  130. PromError("mc:设置上报")
  131. log.Error(_errorMcLogPrefix+"|conn.Set(%v) error(%v)", expKey(v.UID), err)
  132. continue
  133. }
  134. }
  135. return
  136. }