Go中實現Sieve快取

banq發表於2024-12-23

Sieve篩選快取是一種快取機制,旨在以高效且有選擇性的方式最佳化頻繁訪問內容的交付。該概念通常指在需要根據某些標準進行過濾或分割槽的系統中如何儲存和檢索資料,類似於篩選的選擇性過濾。

Sieve 篩選快取的主要特點:
1、選擇性快取:
僅儲存特定的、高價值的或經常訪問的資料。
通常用於由於大小或相關性限制而無法快取所有內容的場景。

2、高效過濾:
採用演算法“篩選Sieve ”資料並決定應該快取或驅逐什麼。
可以使用訪問頻率、新近度或自定義規則等指標來過濾內容。

3、自適應機制:
根據變化的模式或標準動態調整快取資料。
確保快取與當前工作負載保持相關。

4、低延遲:
專為快速訪問而設計,通常用於需要實時資料處理的系統中。

執行程式碼
篩選邏輯基於自定義規則,用於篩選應快取的內容。我們將使用sync.Map執行緒安全的快取儲存,並定義可自定義的過濾函式來確定快取資格。

package main

import (
 <font>"fmt"
 
"sync"
 
"time"
)

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

//SieveCache 表示篩選快取<i>
type SieveCache struct {
 store        sync.Map
 ttl          time.Duration
 sieveFilter  func(key string, value interface{}) bool
//自定義過濾邏輯<i>
 cleanupTicker *time.Ticker
 stopCleanup  chan struct{}
}

// NewSieveCache 建立 SieveCache 的新例項<i>
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<i>
 go cache.cleanupExpiredItems()
 return cache
}

// 如果透過了篩選過濾器,則 Set 將新專案新增到快取中<i>
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<i>
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<i>
func (c *SieveCache) Delete(key string) {
 c.store.Delete(key)
}

//cleanupExpiredItems 定期從快取中刪除過期專案<i>
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<i>
func (c *SieveCache) Stop() {
 close(c.stopCleanup)
 c.cleanupTicker.Stop()
}

func main() {
 
// 自定義篩選過濾器:僅快取長度 > 3 的字串<i>
 filter := func(key string, value interface{}) bool {
  str, ok := value.(string)
  return ok && len(str) > 3
 }

 
//  建立一個具有 10 秒 TTL 的篩選快取 cache<i>
 cache := NewSieveCache(10*time.Second, filter)
 defer cache.Stop()

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

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

 
// 等待 11 秒測試過期<i>
 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:快取經常使用的使用者定位規則、廣告創意或出價響應。
  • 資料庫查詢最佳化:選擇性查詢結果快取以減少資料庫負載。
  • 流媒體服務:根據使用者行為快取影片或音訊資料塊。

相關文章