асинхронное обновление с мемоизацией scalacache

Я хотел бы сделать мемоизацию на основе TTL с активным асинхронным обновлением в scala.

Пример ScalaCache в документации позволяет использовать мемоизацию на основе TTL следующим образом:

import scalacache._
import memoization._

implicit val scalaCache = ScalaCache(new MyCache())

def getUser(id: Int): User = memoize(60 seconds) {
  // Do DB lookup here...
  User(id, s"user${id}")
}

Любопытно, запускается ли поиск в БД после истечения срока действия TTL для существующего значения, синхронно и лениво во время следующего вызова getUser, или если обновление происходит агрессивно и асинхронно - даже до следующего вызова getUser.

Если реализация ScalaCache является синхронной, существует ли альтернативная библиотека, которая обеспечивает возможность активного и асинхронного обновления кеша?


person vishr    schedule 14.06.2015    source источник


Ответы (1)


Истечение срока и обновление тесно связаны, но разные механизмы. Запись с истекшим сроком действия считается устаревшей и не может быть использована, поэтому ее необходимо отбросить и повторно загрузить. Запись, имеющая право на обновление, означает, что контент все еще действителен для использования, но данные должны быть обновлены, так как они могут быть устаревшими. Guava предоставляет эти политики TTL под именами expireAfterWrite и refreshAfterWrite, которые можно использовать вместе, если время обновления меньше времени истечения срока действия.

Дизайн большинства кешей предпочитает отбрасывать неиспользуемый контент. Для активного обновления потребуется выделенный поток, который перезагружает записи независимо от того, использовались ли они. Поэтому большинство кэширующих библиотек сами по себе не обеспечивают активное обновление, но позволяют приложениям легко добавлять эту настройку поверх.

Когда чтение в Guava обнаруживает, что запись имеет право на обновление, этот вызывающий выполняет операцию. Все последующие чтения во время обновления будут получать текущее значение. Это означает, что обновление выполняется синхронно в пользовательском потоке, который его запустил, и асинхронно с другими потоками, считывающими это значение. Обновление может быть полностью асинхронным, если CacheLoader.reload переопределено для выполнения работы с исполнителем.

Caffeine - это переписанный кеш Guava, который немного отличается тем, что всегда выполняет обновление асинхронно для потока пользователя. Кеш делегирует операцию исполнителю, по умолчанию ForkJoinPool.commonPool, который является исполнителем для всей JVM. Policy api предоставляет средства проверки состояния выполнения кеша, такого как возраст записи, для добавления настраиваемого поведения для конкретного приложения.

Для других бэкэндов ScalaCache поддержка смешанная. Ehcache имеет RefreshAheadCache декоратор, который лениво обновляется с использованием собственного пула потоков. Redis и memcached не обновляются, поскольку они не знают о системе записи. LruMap имеет встроенную поддержку истечения срока действия и не имеет возможности обновления.

person Ben Manes    schedule 14.06.2015
comment
stackoverflow.com/questions/44451323/ вы можете помочь? - person Nilesh; 09.06.2017
comment
@Nilesh Я думаю, вы хотите посмотреть раздел реализации в readme. Модульные тесты тоже могут показывать примеры. - person Ben Manes; 09.06.2017
comment
Хорошо, спасибо, Бен Манес - person Nilesh; 09.06.2017