Skip to main content Link Menu Expand (external link) Document Search Copy Copied

쓰기 확장성을 고려한 redis cluster 구축을 위해서 docker 로 초기 설정을 진행했었습니다. 결론적으로 redis cluster 에서 announce-ip 옵션에 내 ip 및 port 를 넣어줘야지만 정상동작함에 실망해서 결국 쉘 스크립트로 로컬에 직접 노드를 띄워고 클러스터 설정을 해주었습니다. 대부분의 로컬 환경에선 고정 ip 를 가지고 있지 않을 것이고 dhcp 할당 ip 를 넣어줘야하는데 계속 바뀌기때문에 번거로워서 그냥 로컬에 직접 띄우고 관리하였습니다.

redis 8.4 cnf 파일 참고해서 아래처럼 생성했습니다.

#!/usr/bin/env bash
BASE="$(pwd)"
PORTS=(9001 9002 9003 9004 9005 9006)
PASSWORD="패스워드 입력"

mkdir -p $BASE/data/redis/conf $BASE/data/redis/data


for p in "${PORTS[@]}"; do
cat > $BASE/conf/redis-$p.conf <<EOF
port $p
bind 127.0.0.1 # 로컬호스트 바인딩
protected-mode no # 외부접속 허용
cluster-enabled yes
cluster-config-file nodes-$p.conf
cluster-node-timeout 5000
# aof 설정으로 이렇게 해놓으면 redis 재시작 시점에 rdb 로 스냅샷 빠르게 가져오고 aof 조합으로 최신화합니다.
appendonly yes
appendfsync everysec # AOF 를 디스크에 매 초마다 기록
aof-use-rdb-preamble yes # 재시작 시 RDB 스냅샷을 먼저 로드한 후 AOF 로그를 재생하도록 설정
save 3600 1 300 100 60 10000
stream-node-max-bytes 4096
stream-node-max-entries 100

user default on >$PASSWORD ~* +@all

dir $BASE/data
EOF
redis-server $BASE/conf/redis-$p.conf &
done

sleep 3
redis-cli -a "$PASSWORD" --cluster create \
127.0.0.1:9001 127.0.0.1:9002 127.0.0.1:9003 \
127.0.0.1:9004 127.0.0.1:9005 127.0.0.1:9006 \
--cluster-replicas 1 --cluster-yes

설정한 값들

  • AOF/RDB
    • 1/3600s, 100/300s, 10000/60s 마다 스냅샷 저장 해서 복구시간 단축하였습니다.
    • AOF 는 매 초마다 디스크에 기록해서 1초 이내로만 데이터 유실 보장하도록 설정했습니다. appendfsync always 로 풀싱크 가능하긴한데 io 때문에 성능 떨어져서 이러면 굳이 redis stream 을 쓸 이유가 없습니다. 완벽한 정합성을 바란다면 그냥 안전하게 디스크 기반 mq kafka 쓰면 되요.
  • stream-node-max-bytes, stream-node-max-entries

    Streams macro node max size / items. The stream data structure is a radix tree of big nodes that encode multiple items inside. Using this configuration it is possible to configure how big a single node can be in bytes, and the maximum number of items it may contain before switching to a new node when appending new stream entries. If any of the following settings are set to zero, the limit is ignored, so for instance it is possible to set just a max entries limit by setting max-bytes to 0 and max-entries to the desired value.

    redis 는 stream 에 radix tree 쓰고 listpack 으로 여러 엔트리를 인코딩해서 저장하는데 listpack 크기 및 엔트리 개수를 제한하는 옵션입니다. 이거 크기가 커졌을 때 listpack 내부에서 O(1) 탐색해서 잘 고려해서 설정해줘야합니다. 저는 기본 값인 4096 바이트 및 100개로 설정했습니다.

    이 값을 작게 잡으면 XADD 할 때 노드 분할이 잦아져 메모리 할당, 포인터 오버헤드가 증가합니다. 서로 떨어져있으니까요. 대신 XREAD 선형탐색시간이 감소합니다. 반대로 이 값을 크게 잡으면 XADD 빠르고 XREAD/XRANGE listpack 내부 선형 스캔 비용이 커집니다. 난 자주 읽는다 하면 작게, 자주 쓰기만 한다 하면 크게 잡으면 됩니다. 전 그냥 기본값으로 했습니다.

SUMMARY

  1. redis cluster 을 docker 로 띄우려다 announce-ip 옵션 때문에 도커로 말고 로컬에 직접 띄웠습니다.
  2. redis 의 설정값들을 자세히 관찰하였습니다.
    1. AOF + RDB 조합으로 빠른 복구시간과 데이터 유실 최소화를 동시에 잡았습니다.
    2. stream-node-max-bytes, stream-node-max-entries 옵션으로 stream radix-tree 내부 listpack 크기 및 엔트리 개수 제한 설정했습니다.