• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

NamedLock을 사용하는 경우 DataSource 분리

24.02.15 20:49 작성 조회수 219

0

NamedLock을 사용하는 경우에 DataSource를 분리하는 것이 좋다고 하여 시도해봤으나 DataSource 설정의 문제인지 정상적으로 동작하지 않아 질문드리게 되었습니다.

 

Main이 JPA에서 사용하게 될 데이터소스이고, Lock이 JdbcTemplate를 사용하기 위해서 사용하는 데이터소스입니다.

spring:
  datasource:
    main:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3308/stock_example?serverTimezone=Asia/Seoul
      username: root
      password: 1234
    lock:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3308/stock_example?serverTimezone=Asia/Seoul
      username: root
      password: 1234
      hikari:
        maximum-pool-size: 20
  jpa:
    database: mysql
    database-platform: org.hibernate.dialect.MySQLDialect
    hibernate:
      ddl-auto: create

logging:
  level:
    root: INFO
    org:
      hibernate:
        SQL: DEBUG
        type.descriptor.sql.BasicBinder: TRACE

애플리케이션 자체에서 사용해야 할 커넥션 풀만 관리를 하면 될 것이라고 생각하여 동일한 데이터베이스를 사용하였습니다.

 

먼저, 메인으로 사용하는 NamedLock을 사용하지 않는 데이터소스설정클래스입니다.

@Configuration
@EnableJpaRepositories(
        basePackages = "com.example.stock.stock",
        entityManagerFactoryRef = "mainEntityManager",
        transactionManagerRef = "mainTransactionManager")
public class MainDataSourceConfiguration {

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.main")
    public DataSourceProperties mainDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    public DataSource mainDataSource() {
        return mainDataSourceProperties()
                .initializeDataSourceBuilder()
                .type(HikariDataSource.class)
                .build();
    }

    @Bean(name = "mainEntityManager")
    @Primary
    public LocalContainerEntityManagerFactoryBean mainEntityManager(
            EntityManagerFactoryBuilder builder) {
        return builder.dataSource(mainDataSource())
                .packages("com.example.stock.stock")
                .build();
    }

    @Bean(name = "mainTransactionManager")
    @Primary
    public PlatformTransactionManager mainTransactionManager(
            @Qualifier("mainEntityManager") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean)
    {
        return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactoryBean.getObject()));
    }
}

다음으로 Lock을 사용하기 위한 데이터소스 설정 클래스입니다.

@Configuration
@EnableTransactionManagement
public class LockDataSourceConfiguration {

    @Bean
    @ConfigurationProperties("spring.datasource.lock")
    public DataSourceProperties lockDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    public DataSource lockDataSource() {
        return lockDataSourceProperties()
                .initializeDataSourceBuilder()
                .type(HikariDataSource.class)
                .build();
    }

    @Bean(name = "lockTransactionManager")
    public JdbcTransactionManager lockTransactionManager(@Qualifier("lockDataSource") DataSource dataSource) {
        return new JdbcTransactionManager(dataSource);
    }
}
@Configuration
public class JdbcTemplateConfiguration {

    @Bean
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate(@Qualifier("lockDataSource") DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }
}

그리고 테스트를 돌려봤는데, 재고가 정상적으로 감소가 되지 않습니다.

 

이상한 점은 업데이트 쿼리가 발생을 하지 않는다는 점입니다.
또 매번, 생성되는 스톡의 id가 1씩 증가한다는 점입니다.

혹시 제가 놓친 부분이 있을까요..?

답변 2

·

답변을 작성해보세요.

0

종운님 안녕하세요.
해당 로직만 보고는 원인을 유추하기 힘들 것 같습니다.

전체로직을 github 에 올리신 후 주소를 공유해주실 수 있으실까요 ?

종운님의 프로필

종운

질문자

2024.02.17

안녕하세요! 답변 감사합니다.
github 주소 첨부드립니다!
https://github.com/bombo-dev/Learning-code/tree/temp/stock-synchronize

종운님 추가 답변이 늦어져서 죄송합니다.
이번주중에는 볼 여력이 되지 않아 주말에 살펴보고 답변을 드리겠습니다.
늦어져서 죄송합니다 ㅠ

종운님의 프로필

종운

질문자

2024.02.24

앗 괜찮습니다! 천천히 봐주세요 도와주시는 것만으로도 정말 감사드립니다!

종운님 안녕하세요.
일단 쿼리가 실행되지 않았던 부분은 JdbcLockRepository 클래스의 getLock, releaseLock 의 반환 타입이 Void 가 아니라 BigInt 였기때문에 에러가 발생하여서 로직이 실행이 되지 않았던 것입니다.

그러나 해당 부분만을 해결한다고 되는 것이 아니라 여러 설정도 변경을 해야하는 것처럼 보입니다.

설정 관련된 부분은 직접 공부해보시면서 고쳐보시면 도움되실 것 같아서 별도의 코멘트는 달지 않겠습니다.

고치시다가 안되셔서 도움이 필요하시다면 새로운 질문을 등록해주시면 살펴보도록 하겠습니다.

답변이 늦어져서 죄송합니다 ㅠㅠ

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.02.15

안녕하세요, 인프런 AI 인턴입니다.

종운님께서 질문하신 NamedLock을 사용하는 경우 DataSource를 분리하는 부분에 대해, 비슷한 문제를 논의한 다른 수강생의 질문이 있습니다. 이전 질문들에서도 DataSource 분리에 대한 의견과 그 이유를 설명하고 있으니 참고하시면 도움이 될 것 같습니다.

주로 DataSource를 분리하는 이유는 NamedLock을 사용할 때, Lock을 획득하기 위해 대기하는 Connection 요청이 기존의 Connection Pool을 모두 차지하여 다른 요청들이 대기 상태에 빠지는 문제를 방지하기 위함입니다. 본래의 비즈니스 로직 처리와는 별개로 Lock 처리를 위한 별도의 Connection Pool을 관리하여 성능상의 이슈를 최소화하려는 전략입니다.

다음은 종운님의 질문과 유사한 문제를 다룬 예전 게시글 링크입니다:

해당 게시글에서 지식공유자는 DataSource를 분리하는 것이 왜 중요한지 구체적으로 설명하고 있으며, 다른 수강생과의 상호 작용을 통해 DataSource 분리에 대한 권장 사항을 제시하고 있습니다.

강의에서 나왔던 설정을 정확히 따라했음에도 불구하고 문제가 발생하는 경우, 설정 파일의 오타, 설정 클래스에서 Bean을 정의할 때 범한 실수, 또는 코드와 데이터베이스 간의 호환성 문제일 수도 있습니다. 설정 클래스와 프로퍼티 파일을 다시 한 번 점검하시고, 만약 여전히 문제를 해결하지 못하시면, 추가적으로 답변을 요청하시면 도움을 받으실 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.