[입 개발] Redis에서의 max memory 정책 알아보기!

예전에, memcached는 무조건 메모리가 넘치면 덮어쓰고, Redis 도 그런걸로 굳게 믿었던 적이 있었습니다. 음, 이렇게 적는다는 건 사실 -_- 그렇지 않다는 의미겠지요? memcached도 옵션을 이용해서 메모리가 더 차면 set 연산이 실패하도록 설정이 가능합니다. 그리고 redis도 그런 정책이 가능합니다. 쿨럭…

 

일단 Redis가 maxmemory 설정을 어떻게 하는지 알아보도록 하겠습니다. 실행시에 redis.conf를 읽게 되는데, 안 읽으면 뭐 디폴트 쿨럭… 일단 redis.c 의 initServerConfig() 을 보시면 다음과 같습니다.


server.maxmemory = 0;

server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU;

 

그러나 redis.conf의 값을 사용하겠죠? 그리고 32bit 머신에서 설정값이 없으면 기본적으로 3G로 설정됩니다.


/* 32 bit instances are limited to 4GB of address space, so if there is
 * no explicit limit in the user provided configuration we set a limit
 * at 3 GB using maxmemory with 'noeviction' policy'. This avoids
 * useless crashes of the Redis instance for out of memory. */
 if (server.arch_bits == 32 && server.maxmemory == 0) {
 redisLog(REDIS_WARNING,"Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.");
 server.maxmemory = 3072LL*(1024*1024); /* 3 GB */
 server.maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION;
 }

 

maxmemory를 1MB 이하로 잡으면 다음과 같이 로그도 남겨줍니다.


/* Warning the user about suspicious maxmemory setting. */
 if (server.maxmemory > 0 && server.maxmemory < 1024*1024) {
 redisLog(REDIS_WARNING,"WARNING: You specified a maxmemory value that is less than 1MB (current value is %llu bytes). Are you sure this is what you really want?", server.maxmemory);
 }

 

그리고 이 maxmemory를 체크하는 부분은 전체에서 딱 한곳 redis.c의 freeMemoryIfNeeded()에서 하게 됩니다. 그리고 이것은 레디스 패킷이 만들어져서 처리되는 redic.c 의 processCommand() 와 luaScripting 처리를 위한 scripting.c 의 luaRedisGenericCommand() 함수에서만 호출됩니다. 즉 명령어가 들어왔을 때, 메모리를 체크하게 됩니다. 간단하게 현재 메모리 사용량과 maxmemory를 비교해서 현재 메모리 사용량이 많으면  정책에 따라서 처리하게 됩니다.

 

정책들은 다음과 같습니다.

# volatile-lru -> remove the key with an expire set using an LRU algorithm

# allkeys-lru -> remove any key accordingly to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys->random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don’t expire at all, just return an error on write operations

 

ps. 그리고 중요한 것 하나, 저도 소스 코드를 보면서 발견한건데 redis.conf 에 기본적으로 maxmemory 와  maxmemory_policy 가 지정되어 있지 않습니다. 그리고 maxmemory 가 0이면 -_- ㅋㅋㅋ, 32bit 머신이 아닌이상은 가상메모리가 허용할 때 까지 -_- 그냥 쭈욱 메모리 사용합니다. swap 되면서 점점 느려지겠지만, 스토리지 처럼 쓰고 싶은분에게 알맞은 구조입니다. ㅋㅋㅋ 코드에서 maxmemory가 0이면 검사를 안해요. 크하하하하하 저처럼 모르셨던 분들 꽤 있으실듯 ㅋㅋㅋ