Ответ
Реализация кэша в Go зависит от требований к производительности, согласованности данных и сложности.
1. Простая реализация (in-memory)
Для базового кэша можно использовать map
с sync.RWMutex
для обеспечения потокобезопасности.
type Cache struct {
sync.RWMutex
items map[string]interface{}
}
func (c *Cache) Set(key string, value interface{}) {
c.Lock()
defer c.Unlock()
c.items[key] = value
}
func (c *Cache) Get(key string) (interface{}, bool) {
c.RLock()
defer c.RUnlock()
item, found := c.items[key]
return item, found
}
2. Кэш с TTL (Time-To-Live)
Для автоматического удаления устаревших записей кэш дополняется временем жизни.
type CacheItem struct {
Value interface{}
Expiration int64
}
// При добавлении элемента
expiration := time.Now().Add(5 * time.Minute).UnixNano()
c.items[key] = CacheItem{Value: value, Expiration: expiration}
// При получении нужна проверка
if item.Expiration < time.Now().UnixNano() {
// Элемент устарел
return nil, false
}
3. Стратегии инвалидации кэша
Выбор стратегии — ключевой аспект работы с кэшем:
- Cache-Aside (Чтение/запись с кешированием): Самый распространенный паттерн. Приложение при чтении сначала проверяет кэш. Если данных нет (cache miss), оно читает их из БД, сохраняет в кэш и возвращает. При записи приложение обновляет БД, а затем инвалидирует (удаляет) соответствующую запись в кэше.
- Write-Through (Сквозная запись): Приложение пишет данные одновременно и в кэш, и в БД. Гарантирует консистентность, но увеличивает задержку записи.
- Write-Back (Отложенная запись): Приложение пишет данные только в кэш, который, в свою очередь, асинхронно записывает их в БД через некоторое время. Очень быстрые операции записи, но есть риск потери данных при сбое кэша до того, как данные попали в БД.
4. Готовые решения
Для сложных сценариев (LRU/LFU-вытеснение, шардирование) лучше использовать проверенные библиотеки:
github.com/patrickmn/go-cache
: Простой in-memory кэш с TTL.github.com/dgraph-io/ristretto
: Высокопроизводительный, конкурентный кэш.github.com/allegro/bigcache
: Эффективный in-memory кэш для больших объемов данных.