실전 프로젝트 5주차.
getConnection()에서 병목현상이 발생한다는 것을 알게 되고 rds에서 성능을 개선해보려고 알아보던 중 MySQL Thread 캐시에 대해 알게되었다.
일단 Hikari 커넥션 풀은 프로세스당 100 씩 세팅해두고 서버가 오토스케일링에 따라 최대 인스턴스 수가 3대가 켜지므로 RDS의 max_connections
는 340정도로 세팅해두었다. 기본 300에 추가 여유로 40을 더 설정했는데 300까지만 늘려놓으면 콘솔쿼리나 추가 다른 작업을 할때 Too Many Connection 에러가 떠서 여유분을 둔 것이다.
MySQL 서버는 멀티쓰레드 프로그램이다. 여기에도 쓰레드풀이 존재하며 새 쓰레드를 생성하는 대신 쓰레드풀에 모아둔 쓰레드를 재활용할 수 있다.
Threads_cache_size : 캐시할수있는 쓰레드의 Max 값
Threads_cached : 현재 캐시된 쓰레드 수
Threads_connected : 현재 연결된 쓰레드 수
Threads_created : 새로 만들어진 쓰레드 수, 최소한으로 줄여야 성능이 좋아진다.
커넥션이 발생할 때 쓰레드가 새로 만들어지면 그 쓰레드가 커넥션에서 해제될 때 Threads_cache_size 만큼 캐시된다. 캐시된 쓰레드는 다음 클라이언트 연결에 재사용된다.
쓰레드를 새롭게 생성할때 오버헤드가 발생할 수 있어 이렇게 재사용하게 되면 오버헤드를 낮출 수 있게되지만, Threads_cache_size 가 너무 크면 불필요한 메모리 사용량이 증가할 수 있어 적절한 수치를 설정해야한다.
cache miss rate = Threads_created / Connections * 100%
이 값이 낮을수록 좋다.
낮을수록 새로 생성한 쓰레드가 없고 쓰레드 캐시를 재사용한 것이기 때문이다.
하지만 현재 프로젝트에서는 커넥션이 한번 연결되면 wait time out이 기본값(8시간)이 설정되어 있고, 테스트 할때마다 서버나 rds를 껐다 키는 경우가 많아 DB 쓰레드 캐시는 크게 의미가 없어 튜닝을 하지 않았다. 실제 서비스에서는 쓰레드 캐시가 오버헤드를 줄여 커넥션 생성에 따른 자원 낭비를 줄일 수 있어 적용하면 유용해 보인다.