Как указать разные ключи кеша для одного и того же ключевого объекта в simple-spring-memcached

Я пытаюсь реализовать распределенный кеш с помощью spring-memcached. Документы предполагают, что для использования объекта в качестве ключа мне нужно иметь метод в моем доменном классе с аннотацией @CacheKeyMethod на нем.

Но проблема в том, что я использую один и тот же класс домена в разных сценариях, и ключ, который должен быть сгенерирован в каждом случае, имеет разную логику. Например, для класса User в одном из сценариев требуется, чтобы ключ был уникальным с точки зрения city и gender, а в другом случае он должен быть уникальным с точки зрения email пользователя, по сути, это то, на чем основан ваш поиск.

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

Есть ли способ определить разные ключи. Также было бы здорово, если бы логика генерации ключа могла быть выведена из самого доменного класса.

Я прочитал документацию и понял, что что-то под названием CacheKeyBuilder и/или CacheKeyBuilderImpl может помочь, но я не мог понять, как действовать дальше.

Редактировать.. хорошо.. У меня есть одна подсказка! Что делает CacheKeyBuliderImpl, так это то, что он вызывает метод generateKey для экземпляра defaultKeyProvider, который ищет @cachekeyannotation в предоставленных методах класса домена и выполняет найденный метод для получения ключа.

Таким образом, замена либо CacheKeyBuilderImpl на собственный Impl, либо замена реализации KeyProvider по умолчанию в CacheKeyBuilderImpl на вашу может помочь... но ссылка на поставщика ключей жестко связана с DefaultKeyProvider.

Может ли кто-нибудь помочь мне реализовать CacheKeyBuilder (в отношении того, что делают разные методы; документация не разъясняет это), а также как мне внедрить его для использования вместо обычного CacheKeyBuilderImpl


person mickeymoon    schedule 10.07.2013    source источник


Ответы (1)


Простой Spring Memcached (SSM) не предназначен для такой низкоуровневой настройки. Как вы написали, один из способов - заменить CacheKeyBuilderImpl собственной реализацией. Реализация по умолчанию является жесткой, но ее можно легко заменить с помощью пользовательской конфигурации simplem-context.xml.

Насколько я понимаю ваш вопрос, вы хотите кэшировать свои объекты User под разными ключами в зависимости от варианта использования. Он поддерживается «из коробки», потому что по умолчанию SSM использует аргумент метода для генерации ключа кэша, а не результата.

Пример:

@ReadThroughMultiCache(namespace = "userslist.cityandgenre", expiration = 3600
public List<User> getByCityAndGenre(@ParameterValueKeyProvider(order = 0) String city, @ParameterValueKeyProvider(order = 1) String genre) {
  // implementation
}

@ReadThroughSingleCache(namespace = "users", expiration = 3600)
public User getByEmail(@ParameterValueKeyProvider String email) {
  // implementation
}

Как правило, @CacheKeyMethod используется для создания ключа кэша только в том случае, если объект, содержащий метод, передается методу в качестве параметра, а параметр аннотируется с помощью @ParameterValueKeyProvider.

person ragnor    schedule 16.07.2013
comment
Мой сценарий немного надуманный. Первый метод заключается не в поиске пользователей по городу и полу, а в поиске релевантных предложений для конкретного пользователя. Тип возвращаемого значения — Список‹Сделка›. Список сделок также может кэшироваться по электронной почте, но релевантность сделок зависит от города и пола пользователя. Поэтому лучше кешировать их по ключу, основанному на них, а не по электронной почте, чтобы одна запись могла обслуживать всех пользователей одного города и пола. В настоящее время метод принимает пользователя в качестве параметра. Одним из способов может быть делегирование вызова другому методу с помощью city и gnder, переданного в метод, и использование их в качестве ключей. - person mickeymoon; 17.07.2013
comment
это как public List<Deal> getDealsForUser(User user){ String city = user.getCity(); String gender = user.getGender(); //orm's call for fetching deals for user } - person mickeymoon; 17.07.2013
comment
Можете ли вы изменить сигнатуру метода и вместо параметра пользователя использовать город и пол? Это решит вашу проблему и позволит кэшировать список сделок по городам и полу. Вы также можете создать новый bean-компонент с выделенным методом getDealsByCityAndGender и вызвать его из getDealsForUser (самостоятельные вызовы не перехватываются, поэтому кэш не работает) - person ragnor; 17.07.2013
comment
это то, что я в конечном итоге сделал, но это заставляет меня вносить много изменений в код, которые имеют отношение только к этому сценарию кэширования. переход к другой реализации кеша может потребовать его отмены ... как я в конечном итоге перешел к интеграции SSM с использованием абстракции Spring Cache - person mickeymoon; 18.07.2013