콘텐츠로 이동

Redis 설정 및 성능 튜닝

Redis 메모리, eviction policy, latency, Linux kernel 및 systemd 운영 설정을 정리함.


1. Redis 메모리 및 eviction policy 설정

Redis 운영에서 maxmemory는 반드시 명시적으로 설정하는 것이 좋음.

maxmemory는 Redis dataset이 사용할 메모리 상한을 지정함. Redis가 해당 상한에 도달하면 maxmemory-policy에 따라 key를 제거하거나 write 명령을 거부함.

Redis는 메모리가 부족하다고 자동으로 디스크 기반 DB처럼 동작하지 않음. 메모리 상한을 초과하면 eviction policy 또는 write error로 처리됨.

1.1 maxmemory 산정 기준

maxmemory는 서버 전체 RAM보다 충분히 낮게 설정함.

고려할 항목은 다음과 같음.

  • OS 및 systemd가 사용하는 메모리
  • 같은 서버의 애플리케이션이 사용하는 메모리
  • Redis allocator fragmentation
  • client output buffer
  • replication buffer
  • RDB/AOF rewrite 시 fork에 따른 copy-on-write 메모리
  • 백업/모니터링 agent 메모리
  • 장애 상황에서의 여유 메모리

예시 기준:

서버 RAM Redis가 유일한 주요 프로세스인 경우 웹/앱과 공존하는 경우
2GB 512MB ~ 1GB 256MB ~ 512MB
4GB 1GB ~ 2.5GB 512MB ~ 1.5GB
8GB 4GB ~ 6GB 1GB ~ 3GB
16GB 8GB ~ 12GB 2GB ~ 6GB
32GB 18GB ~ 26GB 4GB ~ 12GB

위 값은 시작점임. 실제 운영에서는 INFO memory, latency, OOM, fork 실패 여부, 애플리케이션 메모리 사용량을 보면서 조정함.

1.2 캐시 용도 설정 예시

캐시 전용이고 데이터 유실이 허용되는 경우:

maxmemory 512mb
maxmemory-policy allkeys-lru

또는 접근 빈도 기반 캐시를 원하면 다음을 검토함.

maxmemory 512mb
maxmemory-policy allkeys-lfu

1.3 TTL 기반 캐시 설정 예시

모든 캐시 key에 TTL을 부여하고 TTL 기반 제거를 우선하려면 다음을 검토함.

maxmemory 512mb
maxmemory-policy volatile-ttl

주의 volatile-* 정책은 expire가 설정된 key만 제거 대상으로 삼음. expire가 없는 key가 많으면 메모리 부족 시 write 오류가 발생할 수 있음.

1.4 데이터 저장소 성격이 강한 경우

Redis를 임시 캐시가 아니라 중요 상태 저장소로 사용하는 경우에는 임의 eviction이 위험할 수 있음.

maxmemory 2gb
maxmemory-policy noeviction

noeviction에서는 메모리 상한에 도달하면 write 명령이 실패할 수 있음. 따라서 애플리케이션에서 Redis write 실패를 처리해야 함.

1.5 설정 적용 및 확인

설정 파일 수정 후 Redis를 재시작함.

sudo systemctl restart redis

설정값을 확인함.

redis-cli CONFIG GET maxmemory
redis-cli CONFIG GET maxmemory-policy
redis-cli INFO memory

인증이 있는 경우:

redis-cli --user ops --askpass CONFIG GET maxmemory
redis-cli --user ops --askpass CONFIG GET maxmemory-policy
redis-cli --user ops --askpass INFO memory

2. Redis latency 방지 설정

Redis는 명령 실행 경로가 대부분 단일 스레드 이벤트 루프 중심으로 동작함. 따라서 대형 key 삭제, TTL 대량 만료, eviction, AOF rewrite, RDB snapshot, 디스크 I/O 포화가 Redis 전체 latency spike로 이어질 수 있음.

운영 환경에서는 다음 설정을 검토함.

2.1 Lazy Freeing 설정

대형 Hash/List/Set/ZSet, TTL 대량 만료, eviction이 발생할 수 있는 Redis에서는 lazyfree 계열 설정을 활성화함.

lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
replica-lazy-flush yes

설정 의미:

설정 설명
lazyfree-lazy-eviction yes eviction으로 제거되는 key의 메모리 해제를 백그라운드로 넘김
lazyfree-lazy-expire yes TTL 만료 key의 메모리 해제를 백그라운드로 넘김
lazyfree-lazy-server-del yes 서버 내부 delete 처리의 메모리 해제를 백그라운드로 넘김
replica-lazy-flush yes replica가 full resync 등으로 기존 dataset을 비울 때 lazy flush 사용

주의 lazyfree는 Redis 메인 이벤트 루프 blocking을 줄이는 데 도움이 되지만, 백그라운드 free 작업이 밀릴 수 있음. 대량 삭제 작업 이후에는 INFO memory, lazyfree_pending_objects, CPU 사용률을 확인함.

2.2 AOF rewrite 중 fsync block 완화

AOF를 사용하는 경우 다음 설정을 검토함.

appendonly yes
appendfsync everysec

BGSAVE 또는 BGREWRITEAOF 중 디스크 I/O가 포화되면 메인 스레드가 fsync에서 지연될 수 있음. latency spike 방지를 우선하는 운영 환경에서는 다음 설정을 검토함.

no-appendfsync-on-rewrite yes

설정 의미:

  • yes: AOF rewrite 또는 RDB save 중 fsync를 유예하여 latency spike를 줄임
  • trade-off: OS flush 정책에 따라 장애 시 수 초에서 수십 초 수준의 데이터 유실 가능성이 증가할 수 있음

주의 결제, 정산, 원장성 데이터처럼 데이터 유실이 허용되지 않는 정보를 Redis에 primary durable storage로 저장하지 않음. Redis는 빠른 in-memory store이며, durable system of record가 필요한 경우 RDBMS 또는 별도 durable queue/storage를 사용함.

2.3 대량 삭제 명령 사용 기준

운영 Redis에서 대형 key를 삭제할 때는 DEL보다 UNLINK를 우선 검토함.

UNLINK big:key

UNLINK는 key를 keyspace에서 제거한 뒤 실제 메모리 해제를 백그라운드로 넘겨 blocking 위험을 줄임.

대량 key 삭제가 필요하면 KEYS + DEL 조합을 사용하지 않음. SCAN + UNLINK를 사용함.

인증이 없는 로컬 테스트 환경 예시:

redis-cli --scan --pattern 'app:cache:*' \
  | xargs -r -L 100 redis-cli UNLINK

운영 ACL 환경 예시:

export REDISCLI_AUTH="$REDIS_PASSWORD"

redis-cli --user ops --scan --pattern 'app:cache:*' \
  | xargs -r -L 100 redis-cli --user ops UNLINK

unset REDISCLI_AUTH

원격 Redis 운영 ACL 환경 예시:

export REDISCLI_AUTH="$REDIS_PASSWORD"

redis-cli \
  -h 192.168.1.50 \
  -p 6379 \
  --user ops \
  --scan \
  --pattern 'app:cache:*' \
  | xargs -r -L 100 redis-cli \
      -h 192.168.1.50 \
      -p 6379 \
      --user ops \
      UNLINK

unset REDISCLI_AUTH

TLS 환경 예시:

export REDISCLI_AUTH="$REDIS_PASSWORD"

redis-cli --tls \
  -h 192.168.1.50 \
  -p 6379 \
  --cacert /etc/redis/certs/ca.crt \
  --user ops \
  --scan \
  --pattern 'app:cache:*' \
  | xargs -r -L 100 redis-cli --tls \
      -h 192.168.1.50 \
      -p 6379 \
      --cacert /etc/redis/certs/ca.crt \
      --user ops \
      UNLINK

unset REDISCLI_AUTH

주의
xargs가 호출하는 두 번째 redis-cli에도 --user, --tls, --cacert, -h, -p 등 동일한 접속 옵션이 필요함.
REDISCLI_AUTH는 환경 변수로 상속되지만, username, host, port, TLS 옵션은 명령 인수로 명시해야 함.
삭제 대상 key 수가 매우 많으면 xargs -L 100 값을 더 작게 조정하고, 서비스 peak time을 피해서 수행함.


3. Linux 커널 및 systemd 운영 설정

Redis 운영 서버에서는 Linux 커널 설정도 함께 확인해야 함.

3.1 vm.overcommit_memory 설정

Redis는 RDB snapshot 또는 AOF rewrite 과정에서 fork를 사용함. 이때 Linux memory overcommit 정책에 따라 fork 실패가 발생할 수 있음.

운영 서버에서는 다음 설정을 적용함.

echo 'vm.overcommit_memory = 1' | sudo tee /etc/sysctl.d/99-redis.conf
sudo sysctl --system

확인함.

sysctl vm.overcommit_memory

예상 출력:

vm.overcommit_memory = 1

3.2 Transparent Huge Pages 비활성화

Transparent Huge Pages(THP)는 Redis latency와 memory overhead에 영향을 줄 수 있으므로 운영 Redis 서버에서는 비활성화함.

현재 상태를 확인함.

cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag

즉시 비활성화함.

echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

Rocky Linux/RHEL 계열에서는 tuned가 THP 설정을 다시 적용할 수 있음. 따라서 systemd oneshot만으로 끝내지 말고 kernel boot parameter를 우선 적용함.

grubby를 사용할 수 있는 경우:

sudo grubby --update-kernel=ALL --args="transparent_hugepage=never"

grubby 적용 후에는 반드시 서버를 재부팅한 뒤 실제 kernel command line과 THP 상태를 확인함.

sudo reboot

재부팅 후 확인:

cat /proc/cmdline
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag

정상 기준:

  • /proc/cmdlinetransparent_hugepage=never가 포함되어 있어야 함
  • /sys/kernel/mm/transparent_hugepage/enabled 출력에서 [never]가 선택되어 있어야 함

UEFI, Secure Boot, BLS(Boot Loader Spec) entry 환경에서는 grubby --update-kernel=ALL 적용 결과가 기대와 다를 수 있음.
따라서 적용 여부는 명령 실행 직후가 아니라 재부팅 후 /proc/cmdline 확인 결과를 기준으로 판단함.

grubby를 사용할 수 없는 경우 /etc/default/grubGRUB_CMDLINE_LINUX에 다음 값을 추가함.

transparent_hugepage=never

BIOS 기반 시스템 예시:

sudo grub2-mkconfig -o /boot/grub2/grub.cfg

UEFI 기반 시스템에서는 배포판 및 부트로더 경로를 확인한 뒤 적용함.
UEFI 또는 BLS 환경에서 적용되지 않는 경우 /boot/loader/entries/*.conf, /etc/default/grub, grub2-mkconfig 적용 대상 경로를 서버 부트 방식에 맞게 재확인함.

tuned 상태를 확인함.

systemctl is-active tuned
tuned-adm active

보조 방어선으로 systemd unit을 생성할 수 있음.

sudo tee /etc/systemd/system/disable-thp.service > /dev/null <<'EOF'
[Unit]
Description=Disable Transparent Huge Pages for Redis
DefaultDependencies=no
After=sysinit.target local-fs.target
Before=redis.service

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled; test -f /sys/kernel/mm/transparent_hugepage/defrag && echo never > /sys/kernel/mm/transparent_hugepage/defrag || true'

[Install]
WantedBy=basic.target
EOF

활성화함.

sudo systemctl daemon-reload
sudo systemctl enable --now disable-thp.service

확인함.

systemctl status disable-thp.service --no-pager
cat /sys/kernel/mm/transparent_hugepage/enabled

운영 기준 THP는 GRUB/kernel parameter로 비활성화하는 것을 원칙으로 함. systemd oneshot은 보조 방어선으로 사용함. tuned가 활성화된 환경에서는 reboot 후 THP 상태를 반드시 재확인함.

3.3 somaxconn 설정

동시 연결이 많은 환경에서는 TCP backlog 기준을 조정함.

echo 'net.core.somaxconn = 1024' | sudo tee /etc/sysctl.d/98-redis-network.conf
sudo sysctl --system

확인함.

sysctl net.core.somaxconn

3.4 systemd file descriptor limit 확인

Redis가 많은 client connection을 처리해야 하는 경우 file descriptor limit을 확인함.

systemctl show redis -p LimitNOFILE

필요 시 override를 추가함.

sudo systemctl edit redis

다음 내용을 입력함.

[Service]
LimitNOFILE=100000

적용함.

sudo systemctl daemon-reload
sudo systemctl restart redis
systemctl show redis -p LimitNOFILE

3.5 systemd hardening 예시

운영 환경에서는 systemd hardening을 검토함.

[Service]
LimitNOFILE=100000
PrivateTmp=yes
NoNewPrivileges=yes
ProtectSystem=full

주의 ProtectSystem=full을 적용하면 Redis가 설정 파일, data directory, log directory에 접근하지 못할 수 있음. 적용 전 Redis data directory, log 경로, pid 파일 경로, AOF/RDB rewrite 동작을 staging에서 검증함.