-
Notifications
You must be signed in to change notification settings - Fork 0
[Book][Fix] 카테고리 저장 동시성 이슈 해결 #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- PR에 자세한 설명
Summary of ChangesHello @sunwon12, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 PR은 기존의 순차적 책 크롤링 및 저장 방식을 병렬 처리로 전환하면서 발생한 동시성 문제를 해결하는 데 중점을 둡니다. 책과 카테고리 저장 로직에 각각 최적화된 동시성 처리 전략을 적용하여 데이터 무결성을 보장하고 성능을 유지합니다. 특히 카테고리 계층 구조의 동시성 문제를 해결하기 위해 Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a robust system for managing hierarchical book categories, with a strong focus on handling concurrent creation. The BookCategory entity was updated to correctly process 'ROOT' categories in path generation. A new BookCategoryInitializer ensures a 'ROOT' category with ID 0 is created on application startup. The BookCategoryRepository now includes an insertRoot() method. The BookCategoryService was significantly refactored, introducing a getOrCreateByFullPath() method to handle hierarchical category creation, and implementing a concurrency strategy using INSERT IGNORE and READ_COMMITTED transaction isolation for category creation, with detailed explanations for these choices. The BookSaveService was updated to utilize the new category service and also uses READ_COMMITTED isolation, employing a try-catch block for DataIntegrityViolationException for book saving, again with detailed concurrency strategy comments. New concurrency tests were added for category creation, and existing book saving tests were adjusted. Review comments highlighted an inconsistency in the 'ROOT' category ID (0 vs. 1) across different components, suggested externalizing the 'ROOT' string as a constant for better maintainability, pointed out a redundant find call within the create method in BookCategoryService, and recommended improving the readability and robustness of chained findByNameAndParent().get() calls in the concurrency test.
src/main/java/book/book/book/repository/BookCategoryRepository.java
Outdated
Show resolved
Hide resolved
src/test/java/book/book/book/service/BookCategoryServiceConcurrencyTest.java
Show resolved
Hide resolved
Test Results101 files 101 suites 18s ⏱️ Results for commit ba104c3. ♻️ This comment has been updated with latest results. |
🌻 테스트 커버리지 리포트
|
동시성 처리 전략 보고서 (Concurrency Strategy Report)
이 문서는
BookSaveService와BookCategoryService에서 병렬 처리 시 발생하는 동시성 문제(중복 생성)를 해결하기 위해 채택한 전략과 기술적 배경을 정리한 문서입니다.1. 개요 및 배경
기존의 책 검색 및 저장 로직은 20권의 책을 순차적으로 크롤링하고 저장하는 방식으로, 사용자 응답 속도가 매우 느린 문제가 있었습니다. 이를 개선하기 위해 20개의 스레드가 동시에 크롤링 및 저장을 수행하는 병렬 처리 방식으로 전환했습니다.
그러나 성능 향상을 위한 이 병렬 처리는 **동일한 책이나 카테고리에 대한 동시 접근(Race Condition)**을 유발하여 데이터 중복 및 데드락 이슈를 발생시켰습니다. 본 PR은 이러한 동시성 문제를 해결하고 성능과 데이터 무결성을 모두 해결한 PR입니다.
2. 전략 비교 및 선택
A. 책 저장 (
BookSaveService)전략: Try-Catch (Optimistic Locking 관점)
findByAladingBookId로 존재 여부를 검사합니다. 따라서save()단계에서 중복이 발생하는 것은 극히 드문 엣지 케이스입니다.Insert Ignore + Select방식은 항상 2회의 DB 왕복(RTT)이 발생하지만,Try-Catch방식은 대부분의 경우(성공 시) 1회만 발생하므로 평균 성능이 더 좋습니다.Book엔티티는 필드와 연관관계가 많아, 이를 Native Query(INSERT IGNORE)로 일일이 매핑하는 것은 복잡도가 높고 유지보수가 어렵습니다.B. 카테고리 저장 (
BookCategoryService)전략: INSERT IGNORE + READ_COMMITTED
이유 1: INSERT IGNORE 사용 이유 (Transaction Safety)
국내도서 > 소설 > 한국소설처럼 계층적으로 연속 생성됩니다.Try-Catch를 사용하여DataIntegrityViolationException이 발생하면, 스프링의 트랜잭션은 **'Rollback-Only'**로 마킹됩니다.INSERT IGNORE는 DB 차원에서 무시하므로 예외가 터지지 않아 트랜잭션을 안전하게 유지할 수 있습니다.이유 2: READ_COMMITTED 격리 수준 사용 이유 (Visibility)
이유 3: ROOT 카테고리 별도 처리 (Unique Constraint Issue)
parent_id가NULL입니다. MySQL의 Unique Constraint(parent_id, name)는NULL값에 대해 중복 체크를 하지 않는 특성이 있습니다.1로 강제 지정하여 삽입합니다. PK 제약조건을 활용하여 Unique Constraint의 한계를 극복했습니다.3. 요약 (Summary)
Rollback-Only회피), 계층 구조 안정성INSERT IGNORE후 최신 데이터 조회 보장 (Phantom Miss해결)REQUIRES_NEW사용 시 커넥션 풀 고갈 및 데드락 위험 방지