Что касается Темы 1:
Просто Sidenote: Пожалуйста, не путайте их действия и выселение. Срок действия означает, что запись больше не может быть возвращена кешем и может произойти в определенный момент времени или после продолжительности. Выселение - это действие для свободных ресурсов, запись удаляется из кеша. По истечении срока выселения могут произойти в одно и то же время или позже.
Все распространенные продукты кеша не поддерживают точную, так называемую «точку во времени», истекают. Нам очень нужна эта функция в наших приложениях, поэтому я потратил некоторое усилие на cache2k, чтобы поддержать это.
Вот план для cache2k:
static class MetricsEntry {
long nextUpdate;
List<Metrics> metrics;
}
static class MyEntryExpiryCalculator implements EntryExpiryCalculator<Integer, MetricsEntry> {
@Override
public long calculateExpiryTime(Integer _key, MetricsEntry _value, long _fetchTime, CacheEntry _oldEntry) {
return _value.nextUpdate;
}
}
Cache createTheCache() {
Cache<Integer, MetricsEntry> cache =
CacheBuilder.newCache(Integer.class, MetricsEntry.class)
.sharpExpiry(true)
.entryExpiryCalculator(new MyEntryExpiryCalculator())
.source(new MySource())
.build();
return cache;
}
Если у вас есть ссылки времени в объектах метрик, вы можете использовать это, и вы можете пропустить дополнительный класс входа. sharpExpiry(true)
инструктирует cache2k для точного истечения срока действия. Если вы оставите это, истечение срока действия может занять несколько миллисекунд, но время доступа будет немного быстрее.
Что касается темы 2:
Прямой вперед подход будет использовать интервал минут как ключ кэша.
Вот источник кэша (так называемый загрузчик кэша), который строго возвращает метрики предыдущего интервала:
static class MySource implements CacheSource<Integer, MetricsEntry> {
@Override
public MetricsEntry get(Integer interval) {
MetricsEntry e = new MetricsEntry();
boolean crossedIntervalEnd;
do {
long now = System.currentTimeMillis();
long intervalMillis = interval * 1000 * 60;
long startOfInterval = now % (intervalMillis);
e.metrics = calculateMetrics(startOfInterval, interval);
e.nextUpdate = startOfInterval + intervalMillis;
now = System.currentTimeMillis();
crossedIntervalEnd = now >= e.nextUpdate;
} while (crossedIntervalEnd);
return e;
}
}
Это был бы вернуть показатели для 10: 00-10: 05, если вы делаете запрос на скажем 10:07.
Если вы просто хотите, чтобы вычислить мгновенно метрики прошлого интервала, то проще:
static class MySource implements CacheSource<Integer, MetricsEntry> {
@Override
public MetricsEntry get(Integer interval) {
MetricsEntry e = new MetricsEntry();
long intervalMillis = interval * 1000 * 60;
long startOfInterval = System.currentTimeMillis();
e.metrics = calculateMetrics(startOfInterval, interval);
e.nextUpdate = startOfInterval + intervalMillis;
return e;
}
}
Использование источника кэша имеет преимущество над put()
. cache2k блокируется, поэтому, если для одной метрики приходит несколько запросов, запускается только один метрический расчет.
Если вам не требуется точное истечение срока действия миллисекунды, вы можете использовать и другие кеши. Вещь, которую вам нужно сделать, это сохранить время, необходимое для вычисления показателей в вашем кеш-значении, а затем соответствующим образом исправить продолжительность срока действия.
Имейте хороший!
Но тогда я должен написать поток для периодического удаления старых записей. Разве не все, что нужно использовать из коробки, выталкивающей кеши, чтобы избежать этого? Вы правы, что в этой проблеме нет аспекта ключа/ценности. Я просто использовал хеш-коды в качестве ключей, потому что я не мог найти временные высекающие очереди. –
Не могли бы вы просто удалить истекшие записи при добавлении новых записей или, возможно, когда вызывается один из ваших методов чтения записей? По сути, это то, что делает «Cache»: он удаляет выселенные записи во всех файлах записи (для того, что записывается в любом случае) и при случайных чтениях. – ColinD
@Rohitchauhan Выселение из кеша - это всего лишь «крошечная дополнительная функция» для кеширования, которую вы не смогли бы эффективно реализовать. Главное - кеширование; Отсутствие ключей подразумевает отсутствие причины использовать кеш. Сначала я хотел предложить использовать один 30-минутный кеш и фильтр вручную, но «Deque» или, может быть, «PriorityQueue», кажется, имеет гораздо больше смысла. Добавление выселения довольно тривиально. – maaartinus