中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

分布式Go緩存:HashMap的緩存數據訪問緩存穿透預防

發布時間:2024-11-09 01:03:47 來源:億速云 閱讀:79 作者:小樊 欄目:編程語言

在分布式系統中,緩存是一種提高性能的重要手段。然而,緩存穿透是一個常見的問題,它指的是查詢一個不存在的數據,導致緩存和數據庫都受到不必要的訪問。為了解決這個問題,我們可以采用以下幾種方法來預防緩存穿透:

1. 布隆過濾器(Bloom Filter)

布隆過濾器是一種空間效率極高的概率型數據結構,用于判斷一個元素是否在一個集合中。它可以用來過濾掉不存在的數據請求,從而避免對數據庫的無效訪問。

實現步驟:

  1. 初始化一個布隆過濾器。
  2. 對于每個請求的數據,先檢查布隆過濾器。
  3. 如果布隆過濾器返回不存在,直接返回空結果。
  4. 如果布隆過濾器返回可能存在,再查詢數據庫。
  5. 將查詢結果存入緩存。
package main

import (
	"fmt"
	"github.com/spaolacci/murmur3"
)

type BloomFilter struct {
	bitset []bool
	size   uint
}

func NewBloomFilter(size uint) *BloomFilter {
	return &BloomFilter{
		bitset: make([]bool, size),
		size:   size,
	}
}

func (bf *BloomFilter) Add(item []byte) {
	hashes := bf.hash(item)
	for _, hash := range hashes {
		bf.bitset[hash%bf.size] = true
	}
}

func (bf *BloomFilter) Test(item []byte) bool {
	hashes := bf.hash(item)
	for _, hash := range hashes {
		if !bf.bitset[hash%bf.size] {
			return false
		}
	}
	return true
}

func (bf *BloomFilter) hash(item []byte) []uint {
	hash := murmur3.Sum128(item)
	return []uint{uint(hash.Sum64() & 0xFFFFFFFFFFFFFF), uint(hash.Sum64() >> 64 & 0xFFFFFFFFFFFFFF)}
}

func main() {
	cache := NewBloomFilter(1000)
	cache.Add([]byte("key1"))
	cache.Add([]byte("key2"))

	if cache.Test([]byte("key1")) {
		fmt.Println("key1 exists in cache")
	} else {
		fmt.Println("key1 does not exist in cache")
	}

	if cache.Test([]byte("key3")) {
		fmt.Println("key3 exists in cache")
	} else {
		fmt.Println("key3 does not exist in cache")
	}
}

2. 緩存空對象

對于不存在的數據,可以將其緩存為一個空對象或一個特殊的標記,這樣可以避免對數據庫的無效訪問。

實現步驟:

  1. 對于每個請求的數據,先檢查緩存。
  2. 如果緩存中存在該數據,直接返回緩存結果。
  3. 如果緩存中不存在該數據,查詢數據庫并將結果存入緩存。
  4. 如果數據庫返回空結果,將空對象或特殊標記存入緩存。
package main

import (
	"fmt"
	"github.com/spaolacci/murmur3"
)

type Cache struct {
	data map[string][]byte
}

func NewCache() *Cache {
	return &Cache{
		data: make(map[string][]byte),
	}
}

func (c *Cache) Get(key string) []byte {
	if val, ok := c.data[key]; ok {
		return val
	}
	return nil
}

func (c *Cache) Set(key string, value []byte) {
	c.data[key] = value
}

func main() {
	cache := NewCache()
	cache.Set("key1", []byte("value1"))
	cache.Set("key2", []byte("value2"))

	if val := cache.Get("key1"); val != nil {
		fmt.Println("key1:", string(val))
	} else {
		fmt.Println("key1 does not exist in cache")
	}

	if val := cache.Get("key3"); val != nil {
		fmt.Println("key3:", string(val))
	} else {
		fmt.Println("key3 does not exist in cache")
	}
}

3. 請求限流

通過限制每個IP地址在一定時間內的請求次數,可以避免惡意攻擊導致的緩存穿透。

實現步驟:

  1. 使用一個計數器記錄每個IP地址的請求次數。
  2. 對于每個請求,檢查計數器是否超過限制。
  3. 如果超過限制,返回錯誤信息。
  4. 如果沒有超過限制,更新計數器并繼續處理請求。
package main

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

type RateLimiter struct {
	mu        sync.Mutex
	requests  map[string]int
	interval  time.Duration
	maxRequests int
}

func NewRateLimiter(interval time.Duration, maxRequests int) *RateLimiter {
	return &RateLimiter{
		requests:  make(map[string]int),
		interval:  interval,
		maxRequests: maxRequests,
	}
}

func (rl *RateLimiter) Allow(ip string) bool {
	rl.mu.Lock()
	defer rl.mu.Unlock()

	now := time.Now()
	if entries, ok := rl.requests[ip]; ok {
		if now.Sub(entries.lastRequest) > rl.interval {
			entries.count = 1
			entries.lastRequest = now
			return true
		} else {
			if entries.count < rl.maxRequests {
				entries.count++
				return true
			}
		}
	} else {
		if len(rl.requests) < rl.maxRequests {
			rl.requests[ip] = &RequestEntry{
				count:    1,
				lastRequest: now,
			}
			return true
		}
	}
	return false
}

type RequestEntry struct {
	count     int
	lastRequest time.Time
}

func main() {
	limiter := NewRateLimiter(1*time.Second, 5)

	for i := 0; i < 10; i++ {
		ip := fmt.Sprintf("127.0.0.1:%d", i%1000)
		if limiter.Allow(ip) {
			fmt.Printf("Request from %s allowed\n", ip)
		} else {
			fmt.Printf("Request from %s denied\n", ip)
		}
		time.Sleep(200 * time.Millisecond)
	}
}

4. 數據預熱

對于一些不常用的數據,可以在系統啟動時預先加載到緩存中,從而避免實時查詢數據庫。

實現步驟:

  1. 在系統啟動時,根據預定義的數據列表,查詢數據庫并將結果存入緩存。
  2. 對于每個請求的數據,先檢查緩存。
  3. 如果緩存中存在該數據,直接返回緩存結果。
  4. 如果緩存中不存在該數據,查詢數據庫并將結果存入緩存。
package main

import (
	"fmt"
	"github.com/spaolacci/murmur3"
)

type Cache struct {
	data map[string][]byte
}

func NewCache() *Cache {
	return &Cache{
		data: make(map[string][]byte),
	}
}

func (c *Cache) Get(key string) []byte {
	if val, ok := c.data[key]; ok {
		return val
	}
	return nil
}

func (c *Cache) Set(key string, value []byte) {
	c.data[key] = value
}

func preloadData() {
	cache := NewCache()
	// 預加載數據
	cache.Set("key1", []byte("value1"))
	cache.Set("key2", []byte("value2"))
	cache.Set("key3", []byte("value3"))
}

func main() {
	preloadData()

	cache := NewCache()
	for i := 0; i < 10; i++ {
		key := fmt.Sprintf("key%d", i%3)
		if val := cache.Get(key); val != nil {
			fmt.Printf("key%d: %s\n", i%3, string(val))
		} else {
			fmt.Printf("key%d does not exist in cache\n", i%3)
		}
		time.Sleep(200 * time.Millisecond)
	}
}

通過以上幾種方法,我們可以有效地預防緩存穿透問題,提高分布式系統的性能和穩定性。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

go
AI

灵丘县| 镇平县| 正阳县| 乌什县| 库车县| 二连浩特市| 含山县| 西乌珠穆沁旗| 天全县| 佛学| 体育| 芒康县| 陇南市| 泗水县| 静乐县| 东源县| 元江| 灵寿县| 包头市| 金坛市| 唐河县| 泸西县| 剑川县| 施秉县| 娱乐| 板桥市| 莫力| 麦盖提县| 河北省| 尖扎县| 永兴县| 咸丰县| 土默特右旗| 塔河县| 木里| 谢通门县| 澄迈县| 昌邑市| 固镇县| 周至县| 武汉市|