💬

레디스(Redis)에 대해 찾아보면 여러 글에서 실제 애플리케이션 환경에서는 keys명령어를 사용하지 말라고 하고 있다. 시간 복잡도가 O(N)이기 때문에, 사용할 경우 keys명령어를 처리하는데 너무 오래 걸려 문제가 발생할 수 있다고 한다. 공식 문서에서도 keys명령어는 주의해서 사용하기를 권고한다.

Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don’t use KEYS in your regular application code. If you’re looking for a way to find keys in a subset of your keyspace, consider using SCAN or sets .

keys명령어는 모든 키 데이터를 가져오는 명령어다. 따라서 레디스에 키 데이터가 많으면 많을수록 데이터를 가져오는데 시간이 오래 걸린다. 그런데 시간이 오래 걸려도 괜찮다면 어떨까? 이 오래 걸리는 작업을 수행하면 안될까? 전체 키를 가져와 처리하는 배치 작업이 있고 이 작업은 오래 걸려도 상관이 없다면 keys명령어를 사용해도 되지 않을까?

여기서 주의할 점은 ‘누가 오래 걸리는 것인가?’이다. 배치 작업에서 시간에 대한 제한이 없다면 상관이 없지만, 오랜 시간 동안 명령어를 처리하는 것은 레디스이다. 즉 레디스 자체가 keys명령어를 처리하기 위해 오래 걸리는 것이다. 그렇다면 레디스는 오래 걸리는 작업을 처리하면 안될까? 맞다. 실제 운영 환경에서의 레디스는 여러 요청이 들어오고 keys와 같이 오랜 시간이 걸리는 작업으로 인해 다른 요청을 처리하지 못하기 때문이다.
왜 그럴까? 생각해보면 레디스의 특징 때문이다. 레디스는 모든 연산을 싱글 스레드(single thread)로 처리한다. 한번에 단 하나의 연산을 처리하기 때문에, 먼저 수행한 연산의 수행 속도가 뒤에 있는 다른 연산에 영향을 주는 것이다. keys는 복잡도가 선형이지만, 데이터가 많을 수록 문제가 된다. 그렇다면 모든 키를 가져올 수 있는 방법이 없는걸까?
레디스에는 scan명령어를 제공하고 있다. 이 글을 보면 scan명령어 대해서 더 자세히 알 수 있다.

References