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  }