문제 상황
이전에 낙관적 락을 이용하여 동시성 이슈를 해결하려고 했습니다.
저희 서비스는 낙관적 락을 이용하면 데드락(Deadlock)이 발생합니다. 그리고 여러 계정이 동시 요청이 왔을 때 성능 저하가 뚜렷합니다.
해결 방법
Like 엔티티 동시성 이슈 해결
Like 엔티티에 유니크 제약 조건을 걸어 Like 엔티티에 값이 중복되어 들어가는 것을 방지하겠습니다.
LikeEntity
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(uniqueConstraints = {
@UniqueConstraint(
name = "user_board_post_unique",
columnNames = {
"user_id",
"board_post_id"
}
)
})
@Getter
public class Like extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "like_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "board_post_id")
private BoardPost boardPost;
@Builder
public Like(User user, BoardPost boardPost) {
this.user = user;
this.boardPost = boardPost;
}
}
데드락 발생 해결
BoardPost 엔티티에 likeCount 컬럼을 업데이트 하는 로직을 삭제해서 데드락을 피합니다.
유니크 제약 조건 적용 후 테스트
위 코드처럼 유니크 제약 조건을 설정하고 addLikeCount를 사용하지 않았습니다.
Jmeter를 이용하여 스레드100 설정 후 테스트 해보겠습니다.
유니크 제약 조건에 의해 예외가 발생합니다.
이러한 예외는 공통으로 처리해도 무관하다고 합니다.
이러한 방식으로 동시성 문제를 완벽하게 해결할 수 없었습니다.
위에 글에서도 동시성 문제를 해결할 수 없다고 나와있습니다.
조금이라도 문제를 개선하고 싶으면 좋아요, 좋아요 취소 Api를 생성해서 해결할 수 있습니다.
제가 테스트했을 때 이러한 경우에 동시성 문제를 해결할 수 있다고 생각합니다.
현재 서비스에서는 동시성 문제가 터질 일이 적다고 판단하여 Api를 따로 나누지는 않았는데, 추후에 개선해보겠습니다.
과정에서 깨달은 점
1. 유니크 제약 조건을 사용했을 때 발생하는 예외와 예외처리에 대해 알게 되었습니다.
2. 데드락 발생 원인과 해결 방법에 대해 알게 되었습니다.
3. Lock을 사용하는 것보다 유니크 제약 조건을 사용하는게 성능 측면에서 훨씬 우수합니다.
'데이터베이스' 카테고리의 다른 글
동시성) 싱글벙글 게시글 좋아요 Lock을 이용하여 동시성 이슈, 데드락 해결하기 (1) | 2023.10.04 |
---|