
즐겨찾기 하나를 생성하는 데 발생하는 쿼리의 수다.
우선, 쿼리가 많다는 것 자체가 개선이 필요한 부분이라고 생각했다.
현재 구조에서는 member와 bin을 각각 따로 조회하고, bin을 조회하면서 bin_registration까지 같이 조회해야 한다.
이걸 하나의 쿼리로 끝낼수는 없을까?
SELECT b1_0.id, m1_id
FROM bookmark b1_0
LEFT JOIN member m1_0 ON m1_0.id = b1_0.member_id
LEFT JOIN bin_registration br1_0 ON br1_0.bin_id = b1_0.bin_id
WHERE b1_0.id = ? AND b1_0.deleted_at IS NULL AND b1_0.bin_id = ?
이런식으로 가져온 다음에 연관관계만 잘 맵핑해주면 될 거라고 생각했다.


이런식으로 id만 갖고서 맵핑을 해줘도 값은 잘 들어간다!.. 그러면 select로 하나씩 조회하지 않고 join으로 id만 가져와서 넣는 게 가능한 것이다.
이건 일종의 테스트를 위한 시도였고
내가 지금 하려고 하는 것은 즐겨찾기 생성한 것을 바로 DB에 넣지 않고
레디스에 넣어놓은 다음 1시간 간격 정도로 JDBC Template를 써서 벌크 인서트를 하는 것이다.
벌크로 하는 게 왜 더 좋을까? 이에 대해서 내가 정리해놓은 글이 있다.
요약하면, 여러 건으로 보내는 대신 벌크성으로 보내면 트랜잭션이 하나로 처리되면서 오버헤드가 줄어든다. 또한, 데이터를 추가하거나 수정하면 충돌을 피하기 위해서 locking이 발생하는데 이 횟수를 줄일 수 있고, 인덱스 관점에서도 데이터를 한번에 넣으면 인덱스 테이블을 정리하는 데 드는 오버헤드가 줄어든다.
생각하는 흐름은 다음과 같다.
1)이용자가 쓰레기통에 대한 즐겨찾기를 누른다.
2)레디스에 현재 이용자의 쓰레기통 즐겨찾기 정보가 없으면, 목록을 가져온 다음에 새로운 즐겨찾기 내역을 더해서 레디스에 넣는다.
3)특정 시간 간격마다 레디스에 저장해놓은 내역을 DB에 반영한다.
-이용자와 쓰레기통을 연결하는 중간 레코드 bookmark를 벌크 업데이트로 생성(이를 위해서 bin의 id와 member의 id 목록이 레디스에 저장돼 있어야 한다)
-쓰레기통에는 bookmark 카운트가 있다. 데이터 정합성을 맞춰줘야 하는데, 그렇기 때문에서라도 레디스에 다 넣어놓은 다음에 한번에 업데이트할 필요가 있다. bin id마다 추가된 bookmark count를 모아놓는다.
4)이용자는 북마크를 취소할 수도 있다. 이 때문에, 레디스에 북마크 내역(member id(key)로 bin id가 있는지 확인)을 보고서 레디스에 저장된 내역이면 삭제(북마크 카운트 -1)을 해준다.
5)북마크 삭제도 발생하는 쿼리가 많지는 않지만, bin의 bookmark 카운트를 계속 업데이트해야 하기 떄문에 업데이트로 인한 잠금이 빈번할 수밖에 없다. bookmark count의 정합성을 맞춰주기도 쉽지 않다.
6)그래서, 북마크 취소 내역도 레디스에 담아 놓는다. 이걸 나중에 db에 한번에 반영한다.
데이터 정합성에 대한 내용은 여기에 정리해두었다. 요약하면, 동시성 문제로 데이터 정합성에 문제가 발생할 수 있다는 것이다.
레디스와 애플리케이션 서버 혹은 DB 서버를 같이 쓰면 리소스를 경합해서 레디스의 캐시 성능이 떨어진다고 들었다.
여러 애플리케이션에서 레디스에 내역을 저장하는 상황을 가정해두고, 레디스를 위한 별도의 서버를 하나 만들 계획이다.