Go中实现Sieve缓存

Sieve筛选缓存是一种缓存机制,旨在以高效且有选择性的方式优化频繁访问内容的交付。该概念通常指在需要根据某些标准进行过滤或分区的系统中如何存储和检索数据,类似于筛选的选择性过滤。

Sieve 筛选缓存的主要特点:
1、选择性缓存:
仅存储特定的、高价值的或经常访问的数据。
通常用于由于大小或相关性限制而无法缓存所有内容的场景。

2、高效过滤:
采用算法“筛选Sieve ”数据并决定应该缓存或驱逐什么。
可以使用访问频率、新近度或自定义规则等指标来过滤内容。

3、自适应机制:
根据变化的模式或标准动态调整缓存数据。
确保缓存与当前工作负载保持相关。

4、低延迟:
专为快速访问而设计,通常用于需要实时数据处理的系统中。

执行代码
筛选逻辑基于自定义规则,用于筛选应缓存的内容。我们将使用sync.Map线程安全的缓存存储,并定义可自定义的过滤函数来确定缓存资格。

package main

import (
 "fmt"
 
"sync"
 
"time"
)

// CacheItem represents an individual item in the cache
type CacheItem struct {
 Value      interface{}
 Expiration int64
// Unix timestamp for expiration
}

//SieveCache 表示筛选缓存
type SieveCache struct {
 store        sync.Map
 ttl          time.Duration
 sieveFilter  func(key string, value interface{}) bool
//自定义过滤逻辑
 cleanupTicker *time.Ticker
 stopCleanup  chan struct{}
}

// NewSieveCache 创建 SieveCache 的新实例
func NewSieveCache(ttl time.Duration, sieveFilter func(key string, value interface{}) bool) *SieveCache {
 cache := &SieveCache{
  ttl:         ttl,
  sieveFilter: sieveFilter,
  stopCleanup: make(chan struct{}),
 }
 cache.cleanupTicker = time.NewTicker(ttl / 2)
// Cleanup runs at half the TTL interval
 go cache.cleanupExpiredItems()
 return cache
}

// 如果通过了筛选过滤器,则 Set 将新项目添加到缓存中
func (c *SieveCache) Set(key string, value interface{}) {
 if c.sieveFilter(key, value) {
  c.store.Store(key, CacheItem{
   Value:      value,
   Expiration: time.Now().Add(c.ttl).Unix(),
  })
 }
}

// Get retrieves an item from the cache if it exists and is not expired
func (c *SieveCache) Get(key string) (interface{}, bool) {
 item, exists := c.store.Load(key)
 if !exists {
  return nil, false
 }

 cacheItem := item.(CacheItem)
 if time.Now().Unix() > cacheItem.Expiration {
  c.store.Delete(key)
  return nil, false
 }
 return cacheItem.Value, true
}

// Delete removes an item from the cache
func (c *SieveCache) Delete(key string) {
 c.store.Delete(key)
}

//cleanupExpiredItems 定期从缓存中删除过期项目
func (c *SieveCache) cleanupExpiredItems() {
 for {
  select {
  case <-c.cleanupTicker.C:
   c.store.Range(func(key, value interface{}) bool {
    cacheItem := value.(CacheItem)
    if time.Now().Unix() > cacheItem.Expiration {
     c.store.Delete(key)
    }
    return true
   })
  case <-c.stopCleanup:
   return
  }
 }
}

// Stop stops the cleanup goroutine
func (c *SieveCache) Stop() {
 close(c.stopCleanup)
 c.cleanupTicker.Stop()
}

func main() {
 
// 自定义筛选过滤器:仅缓存长度 > 3 的字符串
 filter := func(key string, value interface{}) bool {
  str, ok := value.(string)
  return ok && len(str) > 3
 }

 
//  创建一个具有 10 秒 TTL 的筛选缓存 cache
 cache := NewSieveCache(10*time.Second, filter)
 defer cache.Stop()

 
// Add items to the cache
 cache.Set(
"key1", "short")         // Won't be cached (length <= 3)
 cache.Set(
"key2", "longerString") // Will be cached

 
// Retrieve items from the cache
 if value, ok := cache.Get(
"key2"); ok {
  fmt.Println(
"Found key2:", value)
 } else {
  fmt.Println(
"key2 not found")
 }

 
// 等待 11 秒测试过期
 time.Sleep(11 * time.Second)
 if _, ok := cache.Get(
"key2"); !ok {
  fmt.Println(
"key2 expired")
 }
}

解释:
过滤功能:
函数sieveFilter决定是否应缓存某个项目。它可根据您的用例进行自定义。

2. TTL:
缓存项具有生存期 ( ttl)。过期项会在定期清理时自动删除。

3.清理:
后台 goroutine 会定期扫描并删除过期的项目。

4.并发:
确保sync.Map线程安全的读写操作。

5.优雅停止:
Stop方法清理资源并停止清理 goroutine。

与LRU缓存的比较
LRU缓存

  • 针对最近使用的项目可能再次被访问的场景进行了优化。
  • 驱逐最近最少使用的项目以便为新项目腾出空间。

Sieve筛选缓存:

  • 根据自定义逻辑(筛选过滤器)对缓存前的数据进行过滤进行了优化。
  • 根据生存时间 (TTL) 到期策略逐出项目。

Sieve 筛选缓存应用:

  • 内容分发网络 (CDN):缓存热门或地理相关的网络资源。
  • AdTech:缓存经常使用的用户定位规则、广告创意或出价响应。
  • 数据库查询优化:选择性查询结果缓存以减少数据库负载。
  • 流媒体服务:根据用户行为缓存视频或音频数据块。