Skip to content

Commit

Permalink
DB Replication 적용 (#724)
Browse files Browse the repository at this point in the history
* chore: DB Replica 설정

* chore: transaction 테스트

* refactor: @transactional 클래스 상단으로 통일

* refactor: CustomTransactionManager 추가

* refactor: CustomTransactionManager 삭제

* refactor: DataSourceConfig prod profile 추가

* chore: 디버깅 코드 삭제

* chore: prod db 환경설정 및 p6spy 설정 추가

* refactor: DataSourceType enum 생성

* refactor: p6spy 제거

* refactor: DataSourceConfig 패키지 변경

* refactor: p6spy 제거 submodule 업데이트

---------

Co-authored-by: LJW25 <dbjwlee@gmail.com>
  • Loading branch information
mcodnjs and LJW25 authored Oct 19, 2023
1 parent d055516 commit 7c44150
Show file tree
Hide file tree
Showing 13 changed files with 111 additions and 7 deletions.
2 changes: 1 addition & 1 deletion backend/backend-submodule
1 change: 0 additions & 1 deletion backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.528'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Transactional
public class CategoryService {

private final CategoryRepository categoryRepository;

@Transactional(readOnly = true)
public List<CategoryResponse> getExpenseCategories() {
final List<Category> expenseCategories = categoryRepository.findExpenseCategory();
return expenseCategories.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class CityService {

private final CityRepository cityRepository;

@Transactional(readOnly = true)
public List<CityResponse> getAllCities() {
final List<City> cities = cityRepository.findAll();
return cities.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Transactional
@Slf4j
public class CommunityService {

private static final int RECOMMEND_AMOUNT = 5;
Expand All @@ -44,13 +46,15 @@ public class CommunityService {
private final RecommendStrategies recommendStrategies;
private final PublishedTripRepository publishedTripRepository;

@Transactional(readOnly = true)
public CommunityTripListResponse getCommunityTripsByPage(final Accessor accessor, final Pageable pageable) {
final List<Trip> trips = tripRepository.findPublishedTripByPageable(pageable.previousOrFirst());
final List<CommunityTripResponse> communityTripResponses = getCommunityTripResponses(accessor, trips);
final Long lastPageIndex = getLastPageIndex(pageable.getPageSize());
return new CommunityTripListResponse(communityTripResponses, lastPageIndex);
}

@Transactional(readOnly = true)
public RecommendTripListResponse getRecommendTrips(final Accessor accessor) {
final RecommendStrategy recommendStrategy = recommendStrategies.mapByRecommendType(LIKE);
final Pageable pageable = Pageable.ofSize(RECOMMEND_AMOUNT);
Expand Down Expand Up @@ -107,6 +111,7 @@ private Long getLastPageIndex(final int pageSize) {
return lastPageIndex + 1;
}

@Transactional(readOnly = true)
public TripDetailResponse getTripDetail(final Accessor accessor, final Long tripId) {
final Trip trip = tripRepository.findById(tripId)
.orElseThrow(() -> new BadRequestException(NOT_FOUND_TRIP_ID));
Expand Down
62 changes: 62 additions & 0 deletions backend/src/main/java/hanglog/global/config/DataSourceConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package hanglog.global.config;

import static hanglog.global.config.datasource.DataSourceType.REPLICA;
import static hanglog.global.config.datasource.DataSourceType.SOURCE;

import hanglog.global.config.datasource.RoutingDataSource;
import java.util.HashMap;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy;

@Profile({"dev", "prod"})
@Configuration
public class DataSourceConfig {

private static final String SOURCE_SERVER = "SOURCE";
private static final String REPLICA_SERVER = "REPLICA";

@Bean
@Qualifier(SOURCE_SERVER)
@ConfigurationProperties(prefix = "spring.datasource.source")
public DataSource sourceDataSource() {
return DataSourceBuilder.create().build();
}

@Bean
@Qualifier(REPLICA_SERVER)
@ConfigurationProperties(prefix = "spring.datasource.replica")
public DataSource replicaDataSource() {
return DataSourceBuilder.create().build();
}

@Bean
public DataSource routingDataSource(
@Qualifier(SOURCE_SERVER) final DataSource sourceDataSource,
@Qualifier(REPLICA_SERVER) final DataSource replicaDataSource
) {
final RoutingDataSource routingDataSource = new RoutingDataSource();

final HashMap<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put(SOURCE, sourceDataSource);
dataSourceMap.put(REPLICA, replicaDataSource);

routingDataSource.setTargetDataSources(dataSourceMap);
routingDataSource.setDefaultTargetDataSource(sourceDataSource);

return routingDataSource;
}

@Bean
@Primary
public DataSource dataSource() {
final DataSource determinedDataSource = routingDataSource(sourceDataSource(), replicaDataSource());
return new LazyConnectionDataSourceProxy(determinedDataSource);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package hanglog.global.config.datasource;

public enum DataSourceType {

SOURCE, REPLICA
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package hanglog.global.config.datasource;

import static hanglog.global.config.datasource.DataSourceType.REPLICA;
import static hanglog.global.config.datasource.DataSourceType.SOURCE;

import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.transaction.support.TransactionSynchronizationManager;

@Slf4j
public class RoutingDataSource extends AbstractRoutingDataSource {

@Override
protected Object determineCurrentLookupKey() {
final String currentTransactionName = TransactionSynchronizationManager.getCurrentTransactionName();
final boolean isReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
if (isReadOnly) {
log.info(currentTransactionName + " Transaction:" + "Replica 서버로 요청합니다.");
return REPLICA;
}

log.info(currentTransactionName + " Transaction:" + "Source 서버로 요청합니다.");
return SOURCE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private Member createMember(final String socialLoginId, final String nickname, f
throw new AuthException(FAIL_TO_GENERATE_RANDOM_NICKNAME);
}

public String generateRandomFourDigitCode() {
private String generateRandomFourDigitCode() {
final int randomNumber = (int) (Math.random() * FOUR_DIGIT_RANGE);
return String.format("%04d", randomNumber);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ public void delete(final Long itemId) {
item.getImages().forEach(image -> publisher.publishEvent(new S3ImageEvent(image.getName())));
}

@Transactional(readOnly = true)
public List<ItemResponse> getItems() {
return itemRepository.findAll().stream()
.map(ItemResponse::of)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Transactional
public class LedgerService {

private final TripRepository tripRepository;
private final CurrencyRepository currencyRepository;
private final CityRepository cityRepository;
private final CategoryRepository categoryRepository;

@Transactional(readOnly = true)
public LedgerResponse getAllExpenses(final Long tripId) {
final Trip trip = tripRepository.findById(tripId)
.orElseThrow(() -> new BadRequestException(NOT_FOUND_TRIP_ID));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public Long getTripId(final String sharedCode) {
return sharedTrip.getTrip().getId();
}

@Transactional(readOnly = true)
public TripDetailResponse getSharedTripDetail(final Long tripId) {
final Trip trip = tripRepository.findById(tripId)
.orElseThrow(() -> new BadRequestException(NOT_FOUND_TRIP_ID));
Expand Down
4 changes: 3 additions & 1 deletion backend/src/main/java/hanglog/trip/service/TripService.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ private void saveDayLogs(final Trip savedTrip) {
customDayLogRepository.saveAll(dayLogs);
}

@Transactional(readOnly = true)
public List<TripResponse> getAllTrips(final Long memberId) {
final List<Trip> trips = tripRepository.findAllByMemberId(memberId);
return trips.stream()
Expand All @@ -106,7 +107,8 @@ private TripResponse getTripResponse(final Trip trip) {
final List<City> cities = cityRepository.findCitiesByTripId(trip.getId());
return TripResponse.of(trip, cities);
}


@Transactional(readOnly = true)
public TripDetailResponse getTripDetail(final Long tripId) {
final Trip trip = tripRepository.findById(tripId)
.orElseThrow(() -> new BadRequestException(NOT_FOUND_TRIP_ID));
Expand Down

0 comments on commit 7c44150

Please sign in to comment.