github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/cache/local.go (about) 1 package cache 2 3 import ( 4 "math/rand" 5 "sync" 6 "time" 7 8 "github.com/vmihailenco/go-tinylfu" 9 ) 10 11 type LocalCache interface { 12 Set(key string, data []byte) 13 Get(key string) ([]byte, bool) 14 Del(key string) 15 } 16 17 type TinyLFU struct { 18 mu sync.Mutex 19 rand *rand.Rand 20 lfu *tinylfu.T 21 ttl time.Duration 22 offset time.Duration 23 } 24 25 var _ LocalCache = (*TinyLFU)(nil) 26 27 func NewTinyLFU(size int, ttl time.Duration) *TinyLFU { 28 const maxOffset = 10 * time.Second 29 30 offset := ttl / 10 31 if offset > maxOffset { 32 offset = maxOffset 33 } 34 35 return &TinyLFU{ 36 rand: rand.New(rand.NewSource(time.Now().UnixNano())), 37 lfu: tinylfu.New(size, 100000), 38 ttl: ttl, 39 offset: offset, 40 } 41 } 42 43 func (c *TinyLFU) UseRandomizedTTL(offset time.Duration) { 44 c.offset = offset 45 } 46 47 func (c *TinyLFU) Set(key string, b []byte) { 48 c.mu.Lock() 49 defer c.mu.Unlock() 50 51 ttl := c.ttl 52 if c.offset > 0 { 53 ttl += time.Duration(c.rand.Int63n(int64(c.offset))) 54 } 55 56 c.lfu.Set(&tinylfu.Item{ 57 Key: key, 58 Value: b, 59 ExpireAt: time.Now().Add(ttl), 60 }) 61 } 62 63 func (c *TinyLFU) Get(key string) ([]byte, bool) { 64 c.mu.Lock() 65 defer c.mu.Unlock() 66 67 val, ok := c.lfu.Get(key) 68 if !ok { 69 return nil, false 70 } 71 72 b := val.([]byte) 73 return b, true 74 } 75 76 func (c *TinyLFU) Del(key string) { 77 c.mu.Lock() 78 defer c.mu.Unlock() 79 80 c.lfu.Del(key) 81 }