Введение: Зачем нужно кэширование в Java?
В современной высоконагруженной разработке скорость доступа к данным — критический фактор. Каждый запрос к базе данных или внешнему API увеличивает время отклика и нагрузку на инфраструктуру. Кэширование в Java позволяет хранить часто запрашиваемые данные в быстродействующей памяти (RAM), сокращая время ответа с десятков миллисекунд до микросекунд.
В этой статье мы разберём три основных подхода к кэшированию: встроенные решения (HashMap, Caffeine, Ehcache), Redis и Memcached. Вы узнаете, как выбрать подходящий инструмент, и увидите рабочие примеры кода.
1. Встроенные решения для кэширования в Java
Для небольших проектов или однопоточных приложений часто достаточно встроенных коллекций. Однако для продакшн-среды лучше использовать специализированные библиотеки.
1.1. Простой кэш на HashMap
Самый простой способ — использовать ConcurrentHashMap с ручным управлением временем жизни. Подходит для прототипов, но не имеет механизмов вытеснения (eviction).
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class SimpleCache {
private final ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();
public void put(String key, Object value, long ttlMs) {
cache.put(key, new CacheEntry(value, System.currentTimeMillis() + ttlMs));
}
public Object get(String key) {
CacheEntry entry = cache.get(key);
if (entry == null || System.currentTimeMillis() > entry.expiry) {
cache.remove(key);
return null;
}
return entry.value;
}
private record CacheEntry(Object value, long expiry) {}
}
1.2. Caffeine — высокопроизводительный кэш для Java
Caffeine — современная библиотека, используемая в Spring Cache. Поддерживает автоматическое вытеснение по времени, размеру и частоте использования.
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
public class CaffeineExample {
public static void main(String[] args) {
Cache<String, String> cache = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(1000)
.build();
cache.put("user_1", "Алексей");
String user = cache.getIfPresent("user_1");
System.out.println(user); // Алексей
}
}
1.3. Ehcache — корпоративный стандарт
Ehcache — зрелое решение с поддержкой кластеризации и персистентности на диск. Часто используется в связке с Hibernate.
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
public class EhcacheExample {
public static void main(String[] args) {
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.withCache("users",
CacheConfigurationBuilder.newCacheConfigurationBuilder(
String.class, String.class,
ResourcePoolsBuilder.heap(100))
).build();
cacheManager.init();
Cache<String, String> cache = cacheManager.getCache("users", String.class, String.class);
cache.put("user_2", "Мария");
System.out.println(cache.get("user_2")); // Мария
cacheManager.close();
}
}
2. Redis — распределённое кэширование для Java
Redis — это in-memory хранилище данных, работающее как отдельный сервер. Поддерживает сложные структуры данных (списки, хэши, множества) и персистентность. Для работы с Redis в Java используется библиотека Jedis или Lettuce.
2.1. Подключение и базовые операции с Jedis
import redis.clients.jedis.Jedis;
public class RedisExample {
public static void main(String[] args) {
// Подключение к локальному Redis
try (Jedis jedis = new Jedis("localhost", 6379)) {
jedis.set("session:123", "user_token_abc");
// Устанавливаем TTL 1 час
jedis.expire("session:123", 3600);
String value = jedis.get("session:123");
System.out.println("Получено: " + value); // user_token_abc
}
}
}
2.2. Кэширование объектов с сериализацией
Для кэширования сложных объектов используйте сериализацию (например, JSON или Java Serialization).
import com.fasterxml.jackson.databind.ObjectMapper;
import redis.clients.jedis.Jedis;
public class RedisObjectCache {
private static final ObjectMapper mapper = new ObjectMapper();
public static void main(String[] args) throws Exception {
User user = new User("ivan", "ivan@example.com");
try (Jedis jedis = new Jedis()) {
String json = mapper.writeValueAsString(user);
jedis.setex("user:ivan", 600, json); // TTL 10 минут
String cached = jedis.get("user:ivan");
User cachedUser = mapper.readValue(cached, User.class);
System.out.println(cachedUser.email()); // ivan@example.com
}
}
record User(String name, String email) {}
}
3. Memcached — простое и быстрое кэширование
Memcached — распределённая система кэширования, ориентированная на простоту. В отличие от Redis, не поддерживает персистентность и сложные структуры, но работает быстрее на базовых операциях get/set. Для Java используется библиотека Spymemcached.
3.1. Пример работы с Spymemcached
import net.spy.memcached.MemcachedClient;
import java.net.InetSocketAddress;
public class MemcachedExample {
public static void main(String[] args) throws Exception {
try (MemcachedClient client = new MemcachedClient(
new InetSocketAddress("localhost", 11211))) {
// Сохраняем значение на 1 час (3600 секунд)
client.set("page:home", 3600, "<html>...</html>");
Object cached = client.get("page:home");
System.out.println("Кэш: " + cached);
}
}
}
Сравнение: когда что выбрать?
| Критерий | Встроенные решения | Redis | Memcached |
|---|---|---|---|
| Скорость | Высокая (in-process) | Высокая (сеть) | Очень высокая |
Перси
БлогиРекомендаций по книгамЧитайте также |