아래와 같이 redo log flush 가 굉장히 높은 load를 차지하며 TPS 한계지점을 확인할 수 있었다.
aurora mysql 구조를 참고하면(https://plaid.com/blog/exploring-performance-differences-between-amazon-aurora-and-vanilla-mysql/ ) Master 인스턴스는 redo log 를 storage layer 와 replica 들에 계속해서 보낸다. 리더노드는 어떠한 page도 disk 에 보내는 행위를 하지 않는다. aurora는 마스터, 리더 모두 storage layer를 공유한다는 특이사항이 있다. undo 로그또한 storage layer에 존재한다.
mysql 과 aurora의 구조이다
mysql 에선 primary 인스턴스가 본인의 storage 와 레플리카들에만 동기화 하면 되는데, aurora 에서는 shared 분산 storage와 레플리카들에 동기화 해주어야 한다. 어찌보면 본인의 disk 에 flush 하느냐 아니면 네트워크를 이용한 storage에 flush 하느냐의 차이로 보인다.
redo log를 disk(+ replica) 에 동기화하는 시간을 조정할 수는 없을까? 즉, 얼마나 자주 동기화할 것인지..
mysql 에서는 innodb_flush_log_at_trx_commit 로 그것을 할 수 있었다. 1이면 each commit 당 flush 되는 것이다. 이 세팅은 갑자기 DB가 뻑나더라도 손실데이터가 0인 설정이다. 이 설정이 매우 당연하고 권장된다.
이 설정은 aurora도 마찬가지이다. By default, in Aurora MySQL, the innodb_flush_log_at_trx_commit parameter is set to 1. Each thread committing a transaction waits for confirmation from the Aurora cluster volume. 커밋하는 스레드는 disk로 전달이 되었는지를 기다리게 된다.
결국 redo_log_flush 를 줄이기위해선 커밋수를 줄이는 수 밖에 없다는 결론으로 마무리 된다. 즉, 최대한 하나의 커밋에 여러 쿼리를 합치는 것이다. 그러나 api 하나에서 이미 하나의 커밋으로 처리를 하고 있어서... 이부분은 더이상 줄일 수 없게 되었다.
결론적으로 해당 문제는 전체적으로 적용할 수 있는 인프라적인 해결방안 보다는, 쿼리마다의 디테일한 최적화가 필요한 문제로 생각되고, 전체적인 성능향상을 위해선 DB인스턴스를 증가시키는 대안정도로 마무리 한다.