Вопрос или проблема
Я разрабатываю функцию “лайк” с использованием Redis. Прежде всего, я пытаюсь реализовать логику, которая сохраняет в Redis количество лайков и кто их запросил, а затем синхронизирует это с БД через определенные промежутки времени.
Тем не менее, возникло исключение, когда я запросил 1000 одновременно с помощью jmeter.
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException
@Configuration
public class ProductRedisConfig {
private final String redisHost = "localhost";
private final int redisPort = 6379;
private final String redisPassword = "systempass";
@Bean
public Jedis jedis() {
Jedis jedis = new Jedis(redisHost, redisPort, 5000);
jedis.auth(redisPassword);
jedis.getClient().setSoTimeout(5000);
return jedis;
}
}
public void addLike(UUID userId, UUID productId) {
String likeCountKey = productId.toString() + ":likeCount";
String userListKey = productId.toString() + ":userList";
String lockKey = "post:like:" + productId;
String likeCount = jedis.get(likeCountKey);
if (likeCount == null) {
Product product = productRepository.findByIdAndIsDeleteFalse(productId)
.orElseThrow(() -> new IllegalArgumentException("не найден."));
likeCount = product.getProductLike().getLikeCount().toString();
jedis.set(likeCountKey, likeCount);
}
jedis.incr(likeCountKey);
jedis.sadd(userListKey, userId.toString());
}
Вот код.
Ответ или решение
Когда вы выполняете нагрузочное тестирование логики, используя Jedis, и сталкиваетесь с проблемой отключения соединения, необходимо внимательно проанализировать разные аспекты конфигурации и архитектуры решения. Рассмотрим более детально вашу реализацию, а также возможные причины возникновения исключения JedisConnectionException: java.net.SocketException
, которое вы наблюдаете при использовании JMeter.
Общая архитектура и ключевые моменты
Ваше приложение использует Redis для учета количества лайков к продуктам, что подразумевает высокую степень конкуренции, особенно при запросах, генерируемых нагрузочным тестированием (например, 1000 запросов одновременно). Прежде всего, необходимо понимать, что Redis, несмотря на свои высокие показатели производительности, может стать узким местом в случае неправильной конфигурации или использования.
1. Импорт и инициализация Jedis
Вы используете класс Jedis
для взаимодействия с Redis, однако в вашем текущем подходе наблюдаются некоторые недочеты:
- Отсутствие пула подключений: Каждый раз, когда вы вызываете метод
addLike
, вы, вероятно, используете одно и то же соединение Jedis. Это приводит к его быстрой исчерпаемости в условиях большого количества параллельных запросов. Рекомендуется использовать пул соединенийJedisPool
, который автоматически управляет несколькими соединениями и обеспечивает масштабируемость.
@Bean
public JedisPool jedisPool() {
return new JedisPool(new JedisPoolConfig(), redisHost, redisPort, 5000, redisPassword);
}
2. Автоматическое закрытие соединений
Если каждое соединение не закрывается после использования, это может привести к утечкам памяти и исчерпанию ресурсов, что непосредственно влияет на производительность. При использовании пула вы получите Jedis
из пула и должны убедиться, что оно возвращается обратно после выполнения операции:
try (Jedis jedis = jedisPool.getResource()) {
// ваше логика работы с Redis
} catch (Exception e) {
// обрабатываем исключения
}
3. Параметры таймаута и конфигурации
Параметры таймаута, которые вы установили, могут оказаться недостаточными для высоконагруженных сценариев. Также стоит проверить настройки вашего Redis-сервера. Настройки конфигурации, такие как максимальное количество подключений и тайм-ауты, следует оптимизировать с учетом ожидаемой нагрузки.
4. Обработка конкуренции
Ваш код также не учитывает конкуренцию между запросами, которые пытаются одновременно увеличить количество лайков и добавить пользователей в список. Рассмотрите использование механизмов блокировки Redis (например, с использованием SETNX
для реализации разделяемых блокировок) или же измените подход к исчислению лайков, чтобы минимизировать конфликты.
5. Проблемы с сетью и серверной инфраструктурой
Также стоит обратить внимание на сетевые настройки и возможные ограничения со стороны серверного окружения (например, фаерволы или пределы на количество соединений). Убедитесь, что ваш сервер Redis имеет достаточно ресурсов для обработки множества параллельных подключений.
Заключение
Для устранения проблемы с отключением соединения при нагрузочном тестировании с использованием Jedis, необходимо перейти на использование пула соединений, корректировать рабочий процесс с учетом управления конкурентностью и оптимизировать параметры сервера. Эти шаги должны помочь вам справиться с возникшими исключениями и обеспечить стабильную работу вашего приложения под нагрузкой.