cache.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package cache
  2. import (
  3. "context"
  4. "fmt"
  5. "go-common/library/cache"
  6. "go-common/library/cache/memcache"
  7. "go-common/library/log"
  8. "go-common/library/net/metadata"
  9. "go-common/library/stat/prom"
  10. "time"
  11. )
  12. //DataLoader cache interface
  13. type DataLoader interface {
  14. Key() (key string)
  15. Value() (value interface{})
  16. // LoadValue return value need cache
  17. // if err, nothing will cache
  18. // if value == nil, and IsNullCached is true, empty will be cached
  19. LoadValue(c context.Context) (value interface{}, err error)
  20. Expire() time.Duration
  21. Desc() string
  22. }
  23. // Get
  24. // Delete
  25. // Add
  26. //MCWrapper wrapper for mc
  27. type MCWrapper struct {
  28. mc *memcache.Pool
  29. cache *cache.Cache
  30. // 是否缓存空值,防止缓存穿透
  31. IsNullCached bool
  32. }
  33. // null definition
  34. const (
  35. IsNull = 1
  36. NotNull = 0
  37. )
  38. type cacheValue struct {
  39. Null int8 `json:"n"` // not 0 means null
  40. Value interface{} `json:"v"`
  41. }
  42. //IsNull return true is it's null
  43. func (s *cacheValue) IsNull() bool {
  44. return s.Null != NotNull
  45. }
  46. //New new memcache wrapper
  47. func New(mc *memcache.Pool) *MCWrapper {
  48. return &MCWrapper{
  49. mc: mc,
  50. cache: cache.New(10, 1024),
  51. }
  52. }
  53. func (m *MCWrapper) addRaw(c context.Context, data DataLoader, cacheV *cacheValue) (err error) {
  54. if data == nil {
  55. return
  56. }
  57. conn := m.mc.Get(c)
  58. defer conn.Close()
  59. key := data.Key()
  60. item := &memcache.Item{Key: key, Object: cacheV, Expiration: int32(data.Expire() / time.Second), Flags: memcache.FlagJSON}
  61. if err = conn.Set(item); err != nil {
  62. actionDesc := "Add" + data.Desc()
  63. prom.BusinessErrCount.Incr("mc:" + actionDesc)
  64. log.Errorv(c, log.KV(actionDesc, fmt.Sprintf("%+v", err)), log.KV("key", key))
  65. return
  66. }
  67. log.Info("Add key ok, key=%s, null=%d", key, cacheV.Null)
  68. return
  69. }
  70. //Add add cache data
  71. func (m *MCWrapper) Add(c context.Context, data DataLoader) (err error) {
  72. var cacheV = &cacheValue{
  73. Value: data.Value(),
  74. }
  75. return m.addRaw(c, data, cacheV)
  76. }
  77. //Delete delete cache data
  78. func (m *MCWrapper) Delete(c context.Context, data DataLoader) (err error) {
  79. conn := m.mc.Get(c)
  80. defer conn.Close()
  81. key := data.Key()
  82. if err = conn.Delete(key); err != nil {
  83. if err == memcache.ErrNotFound {
  84. err = nil
  85. return
  86. }
  87. actionDesc := "Del" + data.Desc()
  88. prom.BusinessErrCount.Incr("mc:" + actionDesc)
  89. log.Errorv(c, log.KV(actionDesc, fmt.Sprintf("%+v", err)), log.KV("key", key))
  90. return
  91. }
  92. return
  93. }
  94. //Get get data
  95. func (m *MCWrapper) Get(c context.Context, data DataLoader) (err error) {
  96. _, err = m.getRaw(c, data)
  97. return
  98. }
  99. func (m *MCWrapper) getRaw(c context.Context, data DataLoader) (v *cacheValue, err error) {
  100. conn := m.mc.Get(c)
  101. defer conn.Close()
  102. key := data.Key()
  103. value, err := conn.Get(key)
  104. if err != nil {
  105. if err == memcache.ErrNotFound {
  106. err = nil
  107. return
  108. }
  109. actionDesc := "Cache" + data.Desc()
  110. prom.BusinessErrCount.Incr("mc:" + actionDesc)
  111. log.Errorv(c, log.KV(actionDesc, fmt.Sprintf("%+v", err)), log.KV("key", key))
  112. return
  113. }
  114. var cacheV = cacheValue{
  115. Value: data.Value(),
  116. }
  117. err = conn.Scan(value, &cacheV)
  118. if err != nil {
  119. actionDesc := "Cache" + data.Desc()
  120. prom.BusinessErrCount.Incr("mc:" + actionDesc)
  121. log.Errorv(c, log.KV(actionDesc, fmt.Sprintf("%+v", err)), log.KV("key", key))
  122. return
  123. }
  124. v = &cacheV
  125. return
  126. }
  127. //GetOrLoad get from cache, if not found, then call data.LoadValue to load
  128. func (m *MCWrapper) GetOrLoad(c context.Context, data DataLoader) (err error) {
  129. var v *cacheValue
  130. v, err = m.getRaw(c, data)
  131. if err != nil {
  132. return
  133. }
  134. if v != nil && !v.IsNull() {
  135. prom.CacheHit.Incr(data.Desc())
  136. return
  137. }
  138. // 没有找到对应的缓存,需求去拉取
  139. prom.CacheMiss.Incr(data.Desc())
  140. res, err := data.LoadValue(c)
  141. if err != nil {
  142. return
  143. }
  144. // 没有查到值,并且不缓存空值
  145. if res == nil && !m.IsNullCached {
  146. return
  147. }
  148. var cacheV = &cacheValue{
  149. Value: res,
  150. }
  151. if res == nil {
  152. cacheV.Null = IsNull
  153. }
  154. m.cache.Save(func() {
  155. m.addRaw(metadata.WithContext(c), data, cacheV)
  156. })
  157. return
  158. }