Project/URL 단축 서비스

MySQL에서 MongoDB로 마이그레이션

hu6r1s 2024. 5. 27. 16:01

변경 이유

MySQL은 RDBMS이고, MongoDB는 NoSQL이다.

NoSQL은 대규모 데이터 및 트래픽 증가에 따라 쉽게 서버를 추가하여 성능을 향상시킬 수 있다. 이는 URL 단축 서비스와 같은 읽기 및 쓰기 요청이 빈번한 애플리케이션에서 매우 유리하다.

그리고 추후에 여러가지 기능을 붙일 것이기 때문에 데이터베이스 스키마가 유연한 것이 좋을 것 같다고 생각하여 변경하게 되었다.

Spring Boot + MongoDB

implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

먼저 MongoDB 의존성을 추가해준다.

spring.data.mongodb.host=
spring.data.mongodb.port=
spring.data.mongodb.database=
spring.data.mongodb.authentication-database=

그리고 환경변수 설정도 해준다.

 

MySQL을 사용했을 때 id 타입을 Long으로 했지만 MongoDB는 ObjectId로 문자열이 된다.

그래서 방법을 찾아보니 id를 숫자 타입으로 Auto Increment할 수 있다고 한다.

@Getter
@ToString
@NoArgsConstructor
@Document(collection = "shorten_urls")
public class ShortenUrl {

    @Transient
    public static final String SEQUENCE_NAME = "shorturl_sequence";

    @Id
    private Long id;

    private String originalUrl;

    private LocalDateTime createdAt = LocalDateTime.now();

    public ShortenUrl(String originalUrl) {
        this.originalUrl = originalUrl;
    }

    public void setId(Long id) {
        this.id = id;
    }
}
public interface ShortUrlRepository extends MongoRepository<ShortenUrl, Long> {

}
@Getter
@Setter
@Document(collection = "auto_sequence")
public class AutoIncrementSequence {

  @Id
  private String id;
  private Long seq;
}
@RequiredArgsConstructor
@Service
public class SequenceGeneratorService {

  private final MongoOperations mongoOperations;

  public Long generateSequence(String seqName) {
    AutoIncrementSequence counter = mongoOperations.findAndModify(Query.query(where("_id").is(seqName)),
        new Update().inc("seq", 1), options().returnNew(true).upsert(true), AutoIncrementSequence.class);

    return !Objects.isNull(counter) ? counter.getSeq() : 1;
  }

}
@RequiredArgsConstructor
@Component
public class ShortUrlListener extends AbstractMongoEventListener<ShortenUrl> {

  private final SequenceGeneratorService generatorService;

  @Override
  public void onBeforeConvert(BeforeConvertEvent<ShortenUrl> event) {
    event.getSource().setId(generatorService.generateSequence(ShortenUrl.SEQUENCE_NAME));
  }
}

 

자세한 설명을 해당 블로그를 통해 참고하면 좋을 것 같다.

이렇게 설정을 해주고 테스트를 해보니 잘 동작한다.

성능 테스트

JMeter를 통해 성능이 얼마나 달라졌을지 궁금하여 테스트를 진행해봤다.

10000명의 사용자가 URL을 단축하는 것으로 설정하고 테스트를 진행했다.

MySQL로 진행했을 때는 평균 응답시간은 1960ms이고, TPS는 888.3이다.

MongoDB로 진행했을 때는 평균 응답시간이 12ms이고, TPS는 999.5로 향상된 것을 확인할 수 있었다.

Reference

https://zzang9ha.tistory.com/384