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!