Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk melaksanakan strategi penghapusan cache di Golang?

Bagaimana untuk melaksanakan strategi penghapusan cache di Golang?

王林
王林asal
2023-06-20 11:16:57822semak imbas

Golang ialah bahasa pengaturcaraan yang telah menjadi sangat popular sejak beberapa tahun kebelakangan ini. Apabila menggunakan Golang untuk membangunkan aplikasi web, kami sering melibatkan penggunaan cache. Caching boleh meningkatkan prestasi aplikasi dan kelajuan tindak balas, tetapi jika kita tidak mengendalikan pengusiran cache dengan betul, ia akan menyebabkan cache menduduki terlalu banyak memori dan menjejaskan kestabilan sistem. Artikel ini akan memperkenalkan cara melaksanakan strategi penyingkiran cache di Golang.

Apakah penghapusan cache?

Ringkasnya, penghapusan cache bermakna apabila ruang cache tidak mencukupi, beberapa data cache perlu dihapuskan untuk memberi ruang kepada data cache baharu. Strategi penghapusan data cache selalunya berkaitan dengan keperluan sebenar aplikasi.

Penghapusan cache di Golang

Di Golang, kita boleh menggunakan pakej kontena dalam perpustakaan standard untuk melaksanakan strategi penyingkiran cache. Pakej ini menyediakan dua struktur data, List dan Heap, yang kedua-duanya boleh digunakan untuk melaksanakan pengusiran cache.

Senarai

Senarai ialah senarai berganda dalam pustaka standard Golang. Kami boleh menambah data cache pada Senarai mengikut peraturan tertentu dan mengemas kini penggunaan data dalam masa nyata. Apabila ruang cache tidak mencukupi, kami boleh memadamkan beberapa data cache yang tidak digunakan lagi dari hujung senarai terpaut mengikut strategi penyingkiran tertentu.

Berikut ialah contoh kod mudah untuk melaksanakan strategi penghapusan LRU (Paling Kurang Digunakan):

type Cache struct {
    maxBytes  int64                    // 允许使用的最大内存
    usedBytes int64                    // 当前已使用的内存
    lruList   *list.List               // 双向链表
    cache     map[string]*list.Element // map 作为缓存数据的索引
    onEvicted func(key string, value []byte)
}

type entry struct {
    key   string
    value []byte
}

// Add 新增一个缓存
func (c *Cache) Add(key string, value []byte) {
    if ele, ok := c.cache[key]; ok {
        c.lruList.MoveToFront(ele)
        kv := ele.Value.(*entry)
        c.usedBytes += int64(len(value) - len(kv.value))
        kv.value = value
        return
    }
    ele := c.lruList.PushFront(&entry{key, value})
    c.cache[key] = ele
    c.usedBytes += int64(len(key) + len(value))
    if c.maxBytes > 0 && c.usedBytes > c.maxBytes {
        c.RemoveOldest()
    }
}

// Get 获取一个缓存
func (c *Cache) Get(key string) ([]byte, bool) {
    if ele, ok := c.cache[key]; ok {
        c.lruList.MoveToFront(ele)
        kv := ele.Value.(*entry)
        return kv.value, true
    }
    return nil, false
}

// RemoveOldest 删除最久未使用的缓存
func (c *Cache) RemoveOldest() { 
    ele := c.lruList.Back()
    if ele != nil {
        c.lruList.Remove(ele)
        kv := ele.Value.(*entry)
        delete(c.cache, kv.key)
        c.usedBytes -= int64(len(kv.key) + len(kv.value))
        if c.onEvicted != nil {
            c.onEvicted(kv.key, kv.value)
        }
    }
}

Dalam kod di atas, kami menggunakan Senarai untuk menyimpan data cache dan peta cache sebagai Indeks ke cari cache dengan cepat dan mudah. Apabila ruang storan cache melebihi had, kami memadamkan cache yang tidak digunakan untuk masa yang paling lama bermula dari penghujung senarai (iaitu, dasar LRU) untuk memberi ruang. Pada masa yang sama, kami juga menyokong beberapa ciri lain, seperti menetapkan memori maksimum yang diperlukan untuk setiap cache dan menyokong beberapa operasi tertentu apabila data cache dipadamkan.

Heap

Heap ialah timbunan dalam pustaka standard Golang Ia menguruskan set data mengikut peraturan keutamaan tertentu (seperti masa akses data cache, saiz data. , dsb.) dan berdasarkan Peraturan secara automatik melaksanakan sisipan data, pemadaman dan pertanyaan. Begitu juga, apabila ruang cache tidak mencukupi, kami boleh menggunakan Heap untuk menghapuskan beberapa data secara automatik.

Berikut ialah contoh kod mudah untuk melaksanakan strategi penghapusan LFU (Kurang Kerap Digunakan):

type Item struct {
    Value  []byte
    Priority int // 优先级,即缓存访问次数
    Index  int    // 在 heap 中的索引
}

type PriorityQueue []*Item

// 实现 heap.Interface 接口的 Push 方法
func (pq *PriorityQueue) Push(x interface{}) {
    n := len(*pq)
    item := x.(*Item)
    item.Index = n
    *pq = append(*pq, item)
}

// 实现 heap.Interface 接口的 Pop 方法
func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    item.Index = -1 // 为了安全起见
    *pq = old[0 : n-1]
    return item
}

// 实现 heap.Interface 接口的 Len 方法
func (pq PriorityQueue) Len() int {
    return len(pq)
}

// 实现 heap.Interface 接口的 Less 方法
func (pq PriorityQueue) Less(i, j int) bool {
    return pq[i].Priority < pq[j].Priority
}

// 实现 heap.Interface 接口的 Swap 方法
func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].Index = i
    pq[j].Index = j
}

type Cache struct {
    maxBytes  int64
    usedBytes int64
    cache     map[string]*Item
    queue     PriorityQueue
    onEvicted func(key string, value []byte)
}

// Add 新增一个缓存
func (c *Cache) Add(key string, value []byte) {
    if item, ok := c.cache[key]; ok {
        item.Priority++
        item.Value = value
        heap.Fix(&c.queue, item.Index)
    } else {
        item = &Item{Value: value, Priority: 1}
        c.cache[key] = item
        heap.Push(&c.queue, item)
    }
    c.usedBytes += int64(len(key) + len(value))
    if c.maxBytes > 0 && c.usedBytes > c.maxBytes {
        c.RemoveOldest()
    }
}

// Get 获取一个缓存
func (c *Cache) Get(key string) ([]byte, bool) {
    if item, ok := c.cache[key]; ok {
        item.Priority++
        heap.Fix(&c.queue, item.Index)
        return item.Value, true
    }
    return nil, false
}

// RemoveOldest 删除访问次数最少的缓存
func (c *Cache) RemoveOldest() {
    item := heap.Pop(&c.queue).(*Item)
    delete(c.cache, item.Value)
    c.usedBytes -= int64(len(item.Value) + item.Priority)
    if c.onEvicted != nil {
        c.onEvicted(item.Value, item.Value)
    }
}

Dalam kod di atas, kami menggunakan Heap untuk menyimpan data cache dan menggunakan peta cache sebagai indeks. Berbeza daripada Senarai, dalam timbunan, kami secara automatik mengurus keutamaan data dan operasi cache seperti penyisipan dan pemadaman. Apabila ruang storan cache melebihi had, timbunan akan memadamkan beberapa data cache secara automatik yang kurang kerap diakses.

Ringkasan

Apabila menulis aplikasi web dalam Golang, penggunaan cache selalunya tidak dapat dielakkan. Tetapi untuk mengelakkan data yang dicache daripada mengambil terlalu banyak memori, kita mesti mengendalikan pengusiran cache dengan betul. Dengan menggunakan struktur data List dan Heap dalam pustaka standard Golang, kami boleh melaksanakan strategi penyingkiran cache yang biasa digunakan dengan mudah dan memastikan operasi aplikasi yang stabil.

Atas ialah kandungan terperinci Bagaimana untuk melaksanakan strategi penghapusan cache di Golang?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn