spring

spring boot 가상 스레드로 Redis 사용

kimbs0301 2024. 10. 12. 10:04

Spring Boot에 Java 21 LTS 가상 스레드에 레디스 사용 하기

 

스프링 부트 자동 설정의 LettuceConnectionFactory 사용해서 레디스 연결

// RedisAutoConfiguration
...
	@Bean
	@ConditionalOnMissingBean(RedisConnectionFactory.class)
	@ConditionalOnThreading(Threading.VIRTUAL)
	LettuceConnectionFactory redisConnectionFactoryVirtualThreads(
			ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
			ClientResources clientResources) {
		LettuceConnectionFactory factory = createConnectionFactory(builderCustomizers, clientResources);
...
		executor.setVirtualThreads(true);
		factory.setExecutor(executor);
		return factory;
	}
...
}

 

build.gradle

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.2.5'
	id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example.vt'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '21'
}

configurations {
	all {
		exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
	}
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
	maven { url 'https://repo.spring.io/release/' }
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-data-redis'
	implementation 'org.springframework.boot:spring-boot-starter-log4j2'
	implementation 'org.apache.commons:commons-pool2'
	compileOnly 'org.projectlombok:lombok:1.18.32'
	annotationProcessor 'org.projectlombok:lombok:1.18.32'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.withType(JavaCompile).configureEach {
	options.encoding = 'UTF-8'
}

tasks.named("jar") {
	enabled = false
}

tasks.named('test') {
	useJUnitPlatform()
}

 

apache commons pool2 라이브러리 사용으로 커넥션 풀 활성화

 

application.yml

server:
  shutdown: graceful

spring:
  threads:
    virtual:
      enabled: true

  data:
    redis:
      host: redishost
      port: 6379
      password: redistest
      connect-timeout: 3s
      timeout: 10s
      lettuce:
        pool:
          max-active: 4
          max-idle: 4
          min-idle: 4

 

RedisClientConfig.java

package com.example.vt.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
//import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisClientConfig {

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setValueSerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        redisTemplate.setHashValueSerializer(RedisSerializer.string());
        //redisTemplate.setDefaultSerializer(new StringRedisSerializer());
        redisTemplate.setDefaultSerializer(RedisSerializer.string());
        return redisTemplate;
    }
}

 

디폴트 RedisTemplate 사용하지 않고 직접 생성한 빈을 사용

저장 데이터 타입을 json으로 할 경우 RedisSerializer.json() 또는 RedisSerializer.byteArray() 사용

 

 

package com.example.vt.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Log4j2
@RequiredArgsConstructor
@RestController
public class ApiController {
    private final RedisTemplate<String, String> redisTemplate;

    @GetMapping("/")
    public RedisTestRes redisTest() {
...
        Long elapsedTime = redisTemplate.execute((RedisCallback<Long>) conn -> {
            long start = System.currentTimeMillis();
            conn.ping();
            return System.currentTimeMillis() - start; // elapsedTime
        });
        log.info("elapsedTimeMillis {}", elapsedTime);
...
    }
}

 

references
https://docs.spring.io/spring-data/redis/reference/redis.html