2010-09-29 2 views
4

У меня есть веб-служба, которая имеет ~ 1k запросы потоков, работающих одновременно в среднем. Эти потоки обращаются к данным из кеша (в настоящее время на ehcache). Когда записи в кеше истекают, поток, который попадает в истеченную запись, пытается получить новое значение из БД, тогда как другие потоки также пытаются попасть в этот блок ввода, т. Е. Я использую декоратор BlockingEhCache. Вместо того, чтобы другие потоки ожидали «выборки потока», я хотел бы, чтобы другие потоки использовали значение «stale», соответствующее «пропущенному» ключу. Есть ли какие-либо сторонние разработчики ehcache для этой цели? Знаете ли вы о других решениях кэширования, которые имеют такое поведение? Другие предложения?Java многопоточное кэширование с одним обновлением Thread

+0

Что происходит с записями в кеше, когда они истекают? Удаляются ли они из кеша или просто помечены? – mlschechter

+0

Хорошая идея. Если элемент отмечен как истек, значение возвращается, а затем инициируется обновление. –

+0

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

ответ

1

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

Предположим, что все потоки обращаются к этому кешу, используя интерфейс службы, называемый FooService, и сервисный компонент, называемый SimpleFooService. Служба будет иметь методы, необходимые для получения необходимых данных (которые также кэшируются). Таким образом, вы скрываете тот факт, что он кэшируется из внешнего интерфейса (объекты HTTP-запросов).

Вместо простого хранения данных, которые будут кэшироваться в свойстве службы, мы создадим для него специальный объект. Назовем его FooCacheManager. Он будет хранить кеш в свойстве в FooCacheManger (скажем, его типа Map). У него есть получатели, чтобы получить кеш. Он также будет иметь специальный метод reload(), который будет загружать данные из БД (путем вызова методов службы для получения данных или через DAO) и заменить содержимое кеша (сохраненного в свойстве) ,

Хитрость здесь заключается в следующем:

  1. Объявите свойство кэша в FooCacheManger в AtomicReference (новый объект, объявленный в Java 1.5). Это гарантирует безопасность потока при чтении и назначении. Ваши действия чтения/записи никогда не сталкиваются или не читают полузаписанное значение.
  2. Перезагрузка() сначала загрузит данные во временную карту, а затем, когда она будет завершена, она назначит новую карту для свойства, сохраненного в FooCacheManager. Поскольку свойство AtomicReference, присвоение является атомарным, поэтому оно в основном позволяет мгновенно отображать карту без необходимости блокировки.
  3. TTL-реализация - Имейте FooCacheManager реализовать интерфейс QuartzJob и эффективно выполнять кварцевое задание. В методе выполнения задания запустите перезагрузку(). В Spring XML задайте это задание для запуска каждые xx минут (TTL), которые также могут быть определены в файле свойств, если вы используете PropertyPlaceHolderConfigurer.

Этот метод эффективен, так как для чтения нитей:

  1. Не блокировать для чтения
  2. Не называется isExpired() на каждом чтения, который является 1k/сек.

Также при записи данных поток записи не блокируется.

Если это неясно, я могу добавить пример кода.

0

Поскольку ehcache удаляет устаревшие данные, другой подход может быть для обновления данных с вероятностью, которая увеличивается по мере приближения времени истечения срока действия и равна 0, если время истечения достаточно «далеко».

Итак, если для потока 1 нужен некоторый элемент данных, он может обновить его, хотя данные еще не старые. Тем временем нить 2 нуждается в тех же данных, это может использовать существующие данные (пока обновленная нить еще не закончена). Возможно, поток 2 может попытаться сделать обновление.

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

Смежные вопросы