github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/cache/memory.go (about) 1 package cache 2 3 import ( 4 "context" 5 "reflect" 6 "time" 7 8 "github.com/dgraph-io/ristretto" 9 "github.com/pkg/errors" 10 ) 11 12 type memoryCache struct { 13 client *ristretto.Cache 14 opts Options 15 } 16 17 // NewMemoryCache create a memory cache 18 func NewMemoryCache(opts ...Option) Cache { 19 o := NewOptions(opts...) 20 // see: https://dgraph.io/blog/post/introducing-ristretto-high-perf-go-cache/ 21 // https://www.start.io/blog/we-chose-ristretto-cache-for-go-heres-why/ 22 config := &ristretto.Config{ 23 NumCounters: 1e7, // number of keys to track frequency of (10M). 24 MaxCost: 1 << 30, // maximum cost of cache (1GB). 25 BufferItems: 64, // number of keys per Get buffer. 26 } 27 store, _ := ristretto.NewCache(config) 28 return &memoryCache{ 29 client: store, 30 opts: o, 31 } 32 } 33 34 // Set add cache 35 func (m *memoryCache) Set(ctx context.Context, key string, val any, expiration time.Duration) error { 36 buf, err := m.opts.codec.Marshal(val) 37 if err != nil { 38 return errors.Wrapf(err, "[cache.menery] marshal data err, value is %+v", val) 39 } 40 cacheKey, err := BuildCacheKey(m.opts.prefix, key) 41 if err != nil { 42 return err 43 } 44 m.client.SetWithTTL(cacheKey, buf, 0, expiration) 45 return nil 46 } 47 48 // Get data 49 func (m *memoryCache) Get(ctx context.Context, key string, val any) error { 50 cacheKey, err := BuildCacheKey(m.opts.prefix, key) 51 if err != nil { 52 return err 53 } 54 data, ok := m.client.Get(cacheKey) 55 if !ok { 56 return nil 57 } 58 if data == NotFoundPlaceholder { 59 return ErrPlaceholder 60 } 61 62 if err = m.opts.codec.Unmarshal(data.([]byte), val); err != nil { 63 return errors.Wrapf(err, "unmarshal data error, key=%s, cacheKey=%s type=%v, json is %+v ", 64 key, cacheKey, reflect.TypeOf(val), string(data.([]byte))) 65 } 66 return nil 67 } 68 69 // Del 删除 70 func (m *memoryCache) Del(ctx context.Context, keys ...string) error { 71 if len(keys) == 0 { 72 return nil 73 } 74 75 key := keys[0] 76 cacheKey, err := BuildCacheKey(m.opts.prefix, key) 77 if err != nil { 78 return err 79 } 80 m.client.Del(cacheKey) 81 return nil 82 } 83 84 // MultiSet 批量set 85 func (m *memoryCache) MultiSet(ctx context.Context, valMap map[string]any, expiration time.Duration) error { 86 panic("implement me") 87 } 88 89 // MultiGet 批量获取 90 func (m *memoryCache) MultiGet(ctx context.Context, keys []string, valueMap any, newObject func() any) error { 91 panic("implement me") 92 } 93 94 func (m *memoryCache) SetCacheWithNotFound(ctx context.Context, key string) error { 95 if m.client.Set(key, NotFoundPlaceholder, int64(DefaultNotFoundExpireTime)) { 96 return nil 97 } 98 return ErrSetMemoryWithNotFound 99 }