Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk menangani masalah pengusiran cache serentak dalam bahasa Go?

Bagaimana untuk menangani masalah pengusiran cache serentak dalam bahasa Go?

WBOY
WBOYasal
2023-10-08 17:30:39882semak imbas

Bagaimana untuk menangani masalah pengusiran cache serentak dalam bahasa Go?

Bagaimana untuk menangani masalah pengusiran cache serentak dalam bahasa Go?

Pengenalan

Masalah pengusiran cache serentak adalah cabaran biasa dalam proses pembangunan. Dalam bahasa Go, disebabkan sokongan yang wujud untuk concurrency, kami boleh menggunakan beberapa strategi untuk menangani isu pengusiran cache serentak. Artikel ini akan memperkenalkan beberapa strategi yang biasa digunakan dan memberikan contoh kod khusus.

1. Strategi penghapusan cache LRU

LRU (Paling Kurang Digunakan) ialah strategi penghapusan cache biasa. Apabila cache penuh, data baharu akan menggantikan data yang paling kurang digunakan baru-baru ini.

Dalam bahasa Go, anda boleh menggunakan pakej kontena/senarai untuk melaksanakan strategi penyingkiran cache LRU. Pertama, kami menentukan struktur yang mengandungi saiz cache dan baris gilir.

type LRUCache struct {
    size  int
    cache map[string]*list.Element
    list  *list.List
}

Seterusnya, kami melaksanakan kaedah Dapatkan untuk mendapatkan data dalam cache dan mengemas kini susunan penggunaan.

func (c *LRUCache) Get(key string) interface{} {
    if element, ok := c.cache[key]; ok {
        c.list.MoveToFront(element)
        return element.Value
    }
    return nil
}

Kemudian, kami melaksanakan kaedah Put untuk memasukkan data ke dalam cache, dan mengusir data tertua yang tidak digunakan apabila cache penuh.

func (c *LRUCache) Put(key string, value interface{}) {
    if element, ok := c.cache[key]; ok {
        c.list.MoveToFront(element)
        element.Value = value
    } else {
        if c.list.Len() == c.size {
            // 缓存已满,删除最久未使用的数据
            evictedElement := c.list.Back()
            delete(c.cache, evictedElement.Value.(string))
            c.list.Remove(evictedElement)
        }
        // 新增数据到缓存
        element := c.list.PushFront(value)
        c.cache[key] = element
    }
}

2. Strategi penghapusan cache LFU

LFU (Kurang Kerap Digunakan, paling jarang digunakan) ialah satu lagi strategi penghapusan cache biasa. Apabila cache penuh, data yang paling kurang digunakan akan diganti.

Dalam bahasa Go, jadual cincang dan senarai terpaut dua kali boleh digunakan untuk melaksanakan strategi penyingkiran cache LFU. Mula-mula, kami mentakrifkan struktur yang mengandungi saiz cache, jadual cincang dan senarai terpaut dua kali.

type LFUCache struct {
    size         int
    cache        map[string]*lfuNode
    frequencyDLL *dll
    minFrequency int // 记录当前缓存中最小的使用次数
}

Seterusnya, kami mentakrifkan struktur nod untuk menyimpan data cache dan bilangan penggunaan yang sepadan.

type lfuNode struct {
    key        string
    value      interface{}
    frequency  int
    prev, next *lfuNode
}

Kemudian, kami mentakrifkan struktur senarai terpaut dua kali untuk menyimpan nod dan menyediakan kaedah operasi yang sepadan.

type dll struct {
    head, tail *lfuNode
}

func (d *dll) insertAfter(node, newNode *lfuNode) {
    newNode.prev = node
    newNode.next = node.next
    node.next.prev = newNode
    node.next = newNode
}

func (d *dll) remove(node *lfuNode) {
    node.prev.next = node.next
    node.next.prev = node.prev
    node.prev = nil
    node.next = nil
}

Akhir sekali, kami melaksanakan kaedah Get dan kaedah Put untuk mendapatkan data cache dan memasukkan data baharu.

func (c *LFUCache) Get(key string) interface{} {
    if node, ok := c.cache[key]; ok {
        c.updateNode(node)
        return node.value
    }
    return nil
}

func (c *LFUCache) Put(key string, value interface{}) {
    if c.size == 0 {
        return
    }
    if node, ok := c.cache[key]; ok {
        node.value = value
        c.updateNode(node)
    } else {
        if len(c.cache) >= c.size {
            c.removeNode(c.frequencyDLL.head.next)
        }
        newNode := &lfuNode{key: key, value: value, frequency: 1}
        c.addNode(newNode)
        c.cache[key] = newNode
    }
}

func (c *LFUCache) updateNode(node *lfuNode) {
    c.removeNode(node)
    node.frequency++
    c.addNode(node)
}

func (c *LFUCache) removeNode(node *lfuNode) {
    dll := c.frequencyDLL.getDLL(node.frequency)
    dll.remove(node)
    if c.minFrequency == node.frequency && dll.head.next == nil {
        c.minFrequency++
    }
    delete(c.cache, node.key)
}

func (c *LFUCache) addNode(node *lfuNode) {
    dll := c.frequencyDLL.getDLL(node.frequency)
    dll.insertAfter(dll.head, node)
    if dll != c.frequencyDLL.head.next && dll.head.next == node {
         c.frequencyDLL.getDLL(node.frequency - 1).remove(node)
    }
    if c.minFrequency == 0 {
        c.minFrequency = node.frequency
    }
    c.cache[node.key] = node
}

Kesimpulan

Di atas ialah dua strategi biasa untuk menangani masalah penghapusan cache serentak dalam bahasa Go: LRU dan LFU. Dengan menggunakan struktur data dan algoritma yang sesuai, kami boleh menyelesaikan masalah pengusiran cache serentak dengan cekap. Semoga contoh kod dalam artikel ini akan membantu pembaca memahami dan menggunakan strategi ini dengan lebih baik.

Atas ialah kandungan terperinci Bagaimana untuk menangani masalah pengusiran cache serentak dalam bahasa Go?. 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