created at 2024-10-12
Table of contents
유저들의 등급을 매월 업데이트하는 배치 프로세스
해당 프로세스를 개발하면서 성능 향상 결과를 정리합니다.
- 100만명 유저 등급 업데이트에 소요되는 시간 변화
- 19m 13s : 커넥션풀 10개, 커널스레드, offset limit 조회
- 8m 15s : 커넥션풀 30개, 커널스레드, offset limit 조회
- 53s : 커넥션풀 30개, VirtualThread, id range 조회
- 바꾼 포인트 설명
- b-tree 시작부터 offset 값 까지 전부 인덱스 스캔하는 과정이 필요한 offset limit 는 sliding window 방식 id range 조회로 변경.
- step 실행 chunk size 를 100 -> 5 로 변경하면서 스레드를 더 많이 사용하도록 변경( + 그에 맞춰 CP 도 증가)
- VirtualThread 를 사용하는 대신 기존 ThreadLocal 로 사용하던 Reader 내부 list 말고 override read() 메서드 내부에 stack 에만 저장하고 즉시 반환하도록 변경
- 업데이트 쿼리 날리는 거 벌크처리
- select 쿼리 날리는 거 필요칼럼만 가져오도록 변경
- sliding window id range 조회 시, 만약 빈 리스트 반환하여도 최대 user.id 값 도달하지 않았으면 window 반복 sliding
id 값이 건너뛸 경우가 있기 때문. e.g. 1,2,3, 1000, 1001, 1002.
- 롤백 시 id 값은 INSERT 시 MYSQL auto_increment 로 증가하고 있습니다. 만약 1000번째 유저가 롤백되면 1000번째 유저는 삭제되지만 id increment 는 TX 외부에서 실행되어 롤백되지 않죠. 즉, 1000번째 유저가 다시 삽입되면 1001 id 값을 갖게 됩니다.
- sequence 로 미리 id 값을 할당받아서 땡겨올 경우, 마찬가지로 롤백 시 or 서버 셧다운 시 db 의 이미 증가된 sequence 값은 그대로라 다음 유저가 그 id 값을 사용합니다.
결과로 19m 13s 걸리던 프로세스가 53s 까지 줄어들었습니다. 21배 빨라진거죠. 만약 insert 쿼리 배치라면 sequence + jdbc bulk insert 를 이용할 수 있을것 같습니다.