Redis - Jedis 사용 시 겪었던 문제.

2018. 10. 13. 15:03개발/기타

최근, Redis 의 java 프레임워크인 Jedis를 사용하면서, 


"Could not get a resource from pool" 


이라는 메시지를 받으며, 서버와 Redis 연결이 끊기는 문제가 발생하였다.


Redis의 상태를 보니 Clients의 갯수가 1000개 언저리에서 머물고 있었다. 


하지만, Redis 서버의 Config에는 "maxclients" 값이 default (4096)로 설정되어 있었다.


그럼에도 Clients는 1000개를 넘지 못하고 있었다.


이는, Redis의 Client가 되는 서버 소스 상에서 JedisPool의 설정값이 1000으로 설정되어 있어서 생기는 문제였다.



위와 같은 상태로 JedisPool에서 resource를 받아오고 있었다. 


위 소스코드에서 "setMaxTotal" 메서드를 통해 JedisPool의 최대 resource 수. (RDS 서버 입장에서는 Clients 수) 를 설정하고 있었다. 


즉 RDS 서버의 maxclients config 값과 jedispool의 setMaxTotal 값을 맞춰 줄 필요가 있었던 것이다.


RDS 에 접근할 때에 속도에 있어서는 문제가 없었기에, 해당 값을 2000으로 설정해주었고, RDS 서버의 Clients는 1200개 언저리로 유지되는 것을 볼 수 있었다.




문제는 해결되었으나, 근본적인 원인을 해결한 것은 아니었다.


기존에 1000개의 clients 제한으로 잘 작동하던 rds와의 연결이 왜 clients가 치솟았는지를 보아야 했다.


이는 jedis resource를 사용하는 방법의 문제였다.


문제가 생기기 전에 추가되었던 소스코드에서, 


1. jedispool에서 resource를 받아옴.


2. RDS에 쓸 데이터 정제 (Stream 연산 사용)


3. RDS에 씀.


4. jedispool에 resource 반환.


의 순서로 로직이 작동하고 있었다.


확신은 못하겠지만, 아마 리소스를 받고 반환하는 과정 사이에서 Stream 연산이 있어서, jedis client의 pool 점유 시간이 늘어났고, 이 때문에 I/O 작업만 하고 반납되어야 할 resource가 그러지 못하고 있었던 것 같다.


해당 stream 연산을 일반 연산으로 바꾸고, 로직 부분을 아래와 같이 수정했다.


1. RDS에 쓸 데이터 정제 (Stream 연산 다른 로직으로 대체)


2. jedispool에서 resource를 받아옴.


3. RDS에 씀.


4. jedispool에 resource 반환.


사실, 1번과 2번 과정이 바뀐 시점에서 데이터 정제 시에 Stream의 사용 여부는 아무 상관이 없게 되었다.


중요한 것은 RDS Pool을 빌리고 반환하는 시점 사이에는 I/O 외에는 아무 작업도 하지 않게 되었다는 것이다.


해당 소스코드 수정 후, clients가 다시 정상적인 수치로 내려온 것을 확인할 수 있었다.


추측성으로 해결했지만, 아마 해당 부분의 문제가 맞았던 것 같다.