Go: lcache

Ранее я уже рассказывал о библиотеке кэширования groupcache от Google, которая используется для кэирования файлов на dl.google.com, Google Monitoring и др. Она прекрасно работает когда нужно держать в памяти массивы байтов и не думать о времени их жизни в кэше. Но на практике частые случаи, когда кэшировать удобней и эффективней объекты в их внутреннем представлении с заданием срока их жизни в кэше, в этом случаю groupcache нам не помощник. Поэтому сегодня я решил рассказать о библиотеке lcache.

Характерные особенности

  • Написана на чистом Go

  • Распространяется под лицензией MIT

  • Для использования встраивается в приложение

  • Хранит данные в первоначальном виде, тем самым снижаются расходы на сериализацию данных

  • Не порождает фоновых потоков

  • Оптимизирована для использования в многопоточной среде и потокобезопасное

  • Хранит данные в виде ключ/значение

  • Позволяет задать время жизни значений в рамках одного кэша

  • Поддержка доступа через кэш

  • Атомы кэширования

Установка

go get github.com/belfinor/lcache

Работа с библиотекой

Подключение

import "github.com/belfinor/lcache"

Создание объекта кэша

var cfg *lcache.Config = &lcache.Config{TTL: 86400, 
                         Size: 102400, Nodes: 16}
var cache *lcache.Cache = lcache.New(cfg)

В этом примере создается объект кэша, в котором будут хранится максимум 102400 значений, распределенные внутри по 16 нодами (для оптимизации параллельного доступа, а для синхронизации используется RWMutex, свой для каждой ноды) с временем жизни 86400 секунд.

В программе можно создавать неограниченное число объектов-кэшей индивидуальных под конкретные нужды (новый кэш не порождает новых горутин).

В случае достижения максимального количества элементов наиболее старые элементы удаляются.

В качестве ключей кэша используются строки, а в качестве значений могут быть использованы произвольные объекты.

Set/Get

При помощи методов Get/Set можно задать получить значение из кэша. Если значения в кэше нет, то возвращается nil.

cache.Set("1", "11")
cache.Set("2",int64(22))

fmt.Println( cache.Get("1").(string), cache.Get("2").(int64) )
fmt.Println( cache.Get("3") == nil )

Доступ через кэш (Fetch)

tm := cache.Fetch( "123", func(k string) interface{} {
  return time.Now().Unix()
  }).(int64)

Метод Fetch работает следующим образом, если значение есть в кэше, то он сразу возвращает его. Если его нет, то для получения значения используется переданная функция. В случае отличного от nil значения оно помещается в кэш и возвращается в качестве значения Fetch. Если nil, то в кэш ничего не кладется и возвращается nil.

Delete

Удаляет переданный ключ из кэша

cache.Delete("123")

Удаление всех ключей

cache.Flush()

Инкрементальный счетчик

cache.Inc("inc")
cache.Inc("inc")
cache.Inc("inc")

fmt.Println( cache.Get("inc").(int64)) // 3

Атомы кэширования

Атомы кэширования lcache.Atom - это упрощенная реализация lcache.Cache, которая позволяет закэшировать один объект на заданное время, после истечения времени значение станет равным nil. Atom — потокобезопасен. Пример работы с атомом ниже:

package main

import "fmt"
import "github.com/belfinor/lcache"

func main() {

  atom := lcache.NewAtom(600) // TTL = 600 секунд

  fmt.Println( atom.Get() ) // <nil>

  atom.Set("12")

  fmt.Println( atom.Get().(string) ) // 12

  atom.Set(nil)
  fmt.Println( atom.Get() ) // <nil>

  res := atom.Fetch( func() interface{} {
    return []int{1,2,3}
  } )

  fmt.Println( res.([]int) ) // [1 2 3]

}

 

01.03.2019









 
архив

подписка