Caching(draft)
Caching Algorithm
์บ์ฑ ์๊ณ ๋ฆฌ์ฆ์ ๋ฐ์ดํฐ์ ์ฌ์ฌ์ฉ์ ์ต์ ํํ๊ณ , ์ฑ๋ฅ์ ํฅ์์ํค๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์ฌ๋ฌ ์ ๋ต ์ค ํ๋๋ค.
์ฃผ๋ก ๊ฐ์ฅ ์ต๊ทผ์ ์ฌ์ฉ๋, ํน์ ๊ฐ์ฅ ์์ฃผ ์ฌ์ฉ๋๋ ๋ฐ์ดํฐ๋ฅผ ๋น ๋ฅด๊ฒ ์ ๊ทผํ ์ ์๋๋ก ๋ฉ๋ชจ๋ฆฌ์ ๋ณด๊ดํ๋ค.
์ด๋ I/O ์์ ์ ๋น์ฉ์ ์ค์ด๊ณ ์๋ต ์๊ฐ์ ๋จ์ถํ๋ ๋ฐ ๋์์ด ๋๋ค.
๋ค์์ ์บ์ฑ ์๊ณ ๋ฆฌ์ฆ์ ๋ช ๊ฐ์ง ์์ ์ด๋ค
LRU (Least Recently Used)
๊ฐ์ฅ ์ค๋์ ์ ์ฌ์ฉ๋ ํญ๋ชฉ์ ์บ์์์ ์ ๊ฑฐํ๋ ๋ฐฉ์์ ๋งํ๋ค.
์๋ก์ด ํญ๋ชฉ์ด ์บ์์ ์ถ๊ฐ๋ ๋, ๊ฐ์ฅ ์ค๋์ ์ ์ ๊ทผํ ํญ๋ชฉ๋ถํฐ ์ ๊ฑฐํ๋ค.
์ด ๋ฐฉ์์ **'๊ฐ์ฅ ์ต๊ทผ์ ์ฌ์ฉํ์ง ์์ ํญ๋ชฉ์ด ๊ฐ์ฅ ๋์ค์ ๋ค์ ์ฌ์ฉ๋ ๊ฐ๋ฅ์ฑ์ด ์๋ค'**๋ ์ถ์ ์ ๊ธฐ๋ฐ์ ๋๊ณ ์๋ค.
Redis๋ฅผ ์ฌ์ฉํด๋ดค๋ค๋ฉด ๋ค์ด๋ดค์ ๋ฒํ ์ฉ์ด์ผ ๊ฒ์ด๋ค.
์ง์ LRU๋ฅผ ๊ตฌํํ๋ค๋ฉด ์ด๋ค์์ผ๋ก ๊ตฌํํ ์ ์์๊น?
Linked list์ map์ ์ด์ฉํด์ ๊ฐ๋จํ๊ฒ ๊ตฌํ ๊ฐ๋ฅํ๋ค.
package main
import (
"container/list"
"fmt"
)
type LRUCache struct {
size int
evictList *list.List
items map[interface{}]*list.Element
}
type entry struct {
key interface{}
value interface{}
}
func NewLRUCache(size int) *LRUCache {
return &LRUCache{size: size, evictList: list.New(), items: make(map[interface{}]*list.Element)}
}
// Set adds a value to the cache.
func (c *LRUCache) Set(key, value interface{}) {
// Check if item already exists
if ee, ok := c.items[key]; ok {
c.evictList.MoveToFront(ee)
ee.Value.(*entry).value = value
return
}
// Add new item
ent := &entry{key, value}
entry := c.evictList.PushFront(ent)
c.items[key] = entry
if c.evictList.Len() > c.size {
c.removeOldest()
}
}
// Get retrieves an item from the cache.
func (c *LRUCache) Get(key interface{}) (value interface{}, ok bool) {
if ent, ok := c.items[key]; ok {
c.evictList.MoveToFront(ent)
return ent.Value.(*entry).value, true
}
return
}
// removeOldest removes the oldest item from the cache.
func (c *LRUCache) removeOldest() {
ent := c.evictList.Back()
if ent != nil {
c.removeElement(ent)
}
}
// removeElement removes a given list element from the cache.
func (c *LRUCache) removeElement(e *list.Element) {
c.evictList.Remove(e)
kv := e.Value.(*entry)
delete(c.items, kv.key)
}
func main() {
lru := NewLRUCache(2)
lru.Set("1", 1)
lru.Set("2", 2)
fmt.Println(lru.Get("1")) // returns 1
lru.Set("3", 3) // evicts key "2"
fmt.Println(lru.Get("2")) // returns nil
lru.Set("4", 4) // evicts key "1"
fmt.Println(lru.Get("1")) // returns nil
fmt.Println(lru.Get("3"))
fmt.Println(lru.Get("4"))
}LFU (Least Frequently Used)
๊ฐ์ฅ ์ ๊ฒ ์ฌ์ฉ๋ ํญ๋ชฉ์ ์บ์์์ ์ ๊ฑฐํ๋ ๋ฐฉ์์ ๋งํ๋ค.
์บ์๊ฐ ๊ฝ ์ฐผ์ ๋, ๊ฐ์ฅ ์ ๊ฒ ์ ๊ทผ๋ ํญ๋ชฉ์ด ์ ๊ฑฐ๋๋ค.
์ด๋ **'๊ณผ๊ฑฐ์ ์์ฃผ ์ฌ์ฉ๋์ง ์์ ํญ๋ชฉ์ ์์ผ๋ก๋ ์์ฃผ ์ฌ์ฉ๋์ง ์์ ๊ฐ๋ฅ์ฑ์ด ํฌ๋ค'**๋ ์ถ์ ์ ๊ธฐ๋ฐํ๋ค.
LFU๋ ์ฃผ๋ก min heap์ ์ด์ฉํด์ ๊ตฌํํ๋๋ฐ, ์ฝ๋๊ฐ ๊ฝค ๊ธธ ๊ฒ ๊ฐ์ผ๋ฏ๋ก ํด๋น ๋ถ๋ถ์ ์๋ตํ๊ฒ ๋ค.
FIFO (First In, First Out)
๊ฐ์ฅ ์ ๋ช ํ๋ค. ์ ์ ์ ์ถ.
์๋ก์ด ํญ๋ชฉ์ด ์บ์์ ์ถ๊ฐ๋ ๋, ์บ์์ ๊ฐ์ฅ ๋จผ์ ๋ค์ด์จ ํญ๋ชฉ์ด ์ ๊ฑฐ๋๋ค.
์ด ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํ์ด ์ฝ๊ณ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ์์ด์ ์ผ๊ด์ฑ์ด ์์ง๋ง ๋ ์ต์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ด์ง๋ ๋ชปํ ์ ์๋ค.
๊ฐ ์๊ณ ๋ฆฌ์ฆ์ ํน์ ์ํฉ์์ ์ฅ์ ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ์ด๋ค ์๊ณ ๋ฆฌ์ฆ์ด ๊ฐ์ฅ ์ ํฉํ์ง๋ ํน์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ค.
์๋ฅผ ๋ค์ด, ๋ฐ์ดํฐ์ ์ ๊ทผ ํจํด์ด ์๊ฐ์ ๋ฐ๋ผ ๋ณํ์ง ์๋๋ค๋ฉด LFU๊ฐ ์ข์ ์ฑ๋ฅ์ ๋ณด์ผ ์ ์๋ค. ๋ฐ๋ฉด, ๋ฐ์ดํฐ์ ์ ๊ทผ ํจํด์ด ์๊ฐ์ ๋ฐ๋ผ ํฌ๊ฒ ๋ณํ๋ค๋ฉด LRU๊ฐ ๋ ์ ํฉํ ์ ์๋ค.
Last updated