0. 실습 목표 및 환경
목표
- Ubuntu에 Redis 설치 및 서비스 운영(systemd)
redis-cli로 핵심 명령 실습(STRING/LIST/SET/HASH/ZSET)- TTL/캐시 패턴(캐시 미스/갱신/무효화) 이해
- RDB/AOF 영속화 설정 및 복구 실습
- 외부 노출 시 필수 보안 설정(바인딩/비밀번호/방화벽)
- 운영 관점 점검(로그/메모리/Slowlog/지표)
준비물
- Ubuntu VM 1대 (권장: 2 vCPU / 2GB RAM 이상)
- sudo 권한
- 터미널 사용
1. Redis 설치 및 서비스 확인
1-1) 패키지 설치
sudo apt update
sudo apt install -y redis-server1-2) 서비스 상태 확인
sudo systemctl status redis-server --no-pager1-3) Redis 버전/접속 테스트
redis-server --version
redis-cli ping- 기대 출력:
PONG
1-4) 포트 리스닝 확인(기본 6379)
ss -lntp | grep 6379 || sudo lsof -i:63792. redis-cli 기본 사용법
2-1) 접속
redis-cli2-2) 도움말/명령 탐색
HELP
COMMAND COUNT
COMMAND INFO GET SET
2-3) 서버 정보/설정 확인
INFO
INFO server
INFO memory
CONFIG GET *
CONFIG GET dir
CONFIG GET appendonly => AOF기능 활성화 여부 확인
2-4) 키 탐색 주의
운영에서는 KEYS * 금지(블로킹). 실습에서는 데이터가 적으므로 비교 용도만.
KEYS *
SCAN 0 MATCH * COUNT 10 => 10개씩 조회
3. Redis 데이터 모델(자료구조) 실습
실습 전, 데이터 초기화
FLUSHDB : 현재 DB 삭제
FLUSHALL : 모든 DB 삭제
설명
- 현재 선택된 Redis DB(기본 0번)에 저장된 모든 키를 삭제. DB는 0~15까지 16개가 있음.
- 실습을 처음부터 깨끗한 상태로 시작하기 위함
FLUSHALL은 모든 DB를 삭제하므로 실습에서는FLUSHDB권장
3-1) STRING
SET user:1:name "kim"
user:1:name이라는 키에 문자열"kim"저장- 동일한 키가 있으면 덮어쓰기
GET user:1:name
- 해당 키에 저장된 값을 조회
- 결과:
"kim"
INCR page:view
-
page:view값을 1 증가 -
키가 없으면
0으로 간주한 뒤1로 생성 -
문자열 타입이지만 숫자 형태의 문자열이어야 함
-
한 번 더 증가 → 누적 증가 확인
INCR page:view
- 현재 조회수(카운터) 값 확인
GET page:view
- 여러 키를 한 번에 저장
- 내부적으로 원자적(atomic)으로 실행
MSET k1 v1 k2 v2
- 여러 키를 한 번에 조회
- 결과는 입력한 순서대로 반환
MGET k1 k2
실습
SET counter 0실행INCR counter를 5회 실행- 최종 값이
5인지 확인 👉 조회수, 접속 수 카운터에 사용되는 패턴
3-2) LIST (큐 / 스택)
- 기존 리스트 키 삭제 (실습 재실행 대비)
DEL queue:email
- 리스트 왼쪽(Head) 에 데이터 삽입
- 여러 값일 경우 왼쪽부터 순차 삽입
- 최종 순서:
mail3 → mail2 → mail1
LPUSH queue:email "mail1" "mail2" "mail3"
- 리스트 전체 조회
0= 첫 번째,1= 마지막
LRANGE queue:email 0 -1
- 리스트 오른쪽(Tail) 에서 데이터 하나 제거 후 반환
- 큐(FIFO) 구조에서 꺼내기 동작
RPOP queue:email
- pop 이후 남은 데이터 확인
LRANGE queue:email 0 -1
블로킹 POP (워크 큐 스타일)
터미널 A
redis-cliqueue:job리스트에 값이 들어올 때까지 대기0은 무한 대기 의미- 작업 큐(worker) 구현 시 사용
BLPOP queue:job 0
터미널 B
redis-cliLPUSH queue:job "job1"
- 값이 들어오는 순간, 터미널 A가 즉시 값을 받음
과제
RPUSH로 데이터 추가LPOP으로 데이터 제거- FIFO 큐 구조 직접 구성해보기
3-3) SET (중복 없는 집합)
- 집합에 값 추가
"kim"은 중복이므로 한 번만 저장
SADD class:students "kim" "lee" "park" "kim"
- 집합에 저장된 모든 값 조회
- 순서는 보장되지 않음
SMEMBERS class:students
"kim"이 집합에 있는지 확인- 결과:
1(있음),0(없음)
SISMEMBER class:students "kim"
- 집합에 포함된 원소 개수 반환
SCARD class:students
"park"를 집합에서 제거
SREM class:students "park"
- 제거 후 최종 상태 확인
SMEMBERS class:students
집합 연산
- 두 개의 집합 생성
SADD class:A "kim" "lee"
SADD class:B "lee" "choi"
- 교집합 (공통 요소) →
"lee"
SINTER class:A class:B
- 합집합 (전체 요소)
SUNION class:A class:B
- 차집합 (A에는 있고 B에는 없는 값)
SDIFF class:A class:B
3-4) HASH (객체 / 레코드)
- 하나의 키(
user:1)에 여러 필드-값 저장 - 객체(JSON)와 유사한 구조
HSET user:1 name "kim" age "29" role "student"
- 특정 필드 값만 조회
HGET user:1 name
- 해당 키의 모든 필드와 값 조회
HGETALL user:1
login_count필드를 1 증가- 필드가 없으면
0으로 간주 후 증가
HINCRBY user:1 login_count 1
- 누적 증가 확인
HINCRBY user:1 login_count 1
- 최종 로그인 횟수 조회
HGET user:1 login_count
과제
user:2생성- 필드 3개 이상 저장(job:sa, team:cloud, floor:3
HGETALL user:2결과 확인
3-5) ZSET (정렬된 집합: 랭킹 / 점수)
ranking이라는 ZSET에 데이터 추가- 숫자(score)를 기준으로 자동 정렬됨
ZADD ranking 100 "alice" 80 "bob" 120 "chris"
- 점수 오름차순 정렬 결과 조회
ZRANGE ranking 0 -1 WITHSCORES
- 점수 내림차순 정렬 결과 조회 (랭킹용)
ZREVRANGE ranking 0 -1 WITHSCORES
"bob"의 점수를+30증가
ZINCRBY ranking 30 "bob"
- 점수 변경 후 순위 자동 재정렬 확인
ZREVRANGE ranking 0 -1 WITHSCORES
Top-N 조회
- 점수가 높은 순으로 상위 3개 조회
- Top-N 랭킹 조회의 대표적인 패턴
ZREVRANGE ranking 0 2 WITHSCORES
4. TTL과 캐시 동작 이해
4-1) TTL 기본
- 세션 데이터 저장
SET session:abc "user1"
- 60초 뒤 자동 삭제 설정
EXPIRE session:abc 60
- 남은 TTL 시간(초 단위) 확인
TTL session:abc
- TTL 만료 전이면 값 반환
- 만료 후면
(nil)반환
GET session:abc
4-2) SETEX / PSETEX
- 값을 저장하면서 TTL(초) 동시에 설정
SETEX otp:001 30 "123456"
- 남은 시간 확인
TTL otp:001
- TTL을 밀리초(ms) 단위로 설정
PSETEX otp:ms 5000 "999999"
- 남은 시간을 ms 단위로 확인
PTTL otp:ms4-3) 캐시 패턴 실습 (수동 시뮬레이션)
상황: DB 조회 결과를 Redis에 10초 캐싱
- 기존 캐시 삭제
DEL cache:product:100
- 값 없음 → 캐시 미스(Cache Miss)
GET cache:product:100
- DB 조회 결과를 Redis에 저장
SET cache:product:100 "{'name':'mouse','price':12000}"
- 10초 뒤 자동 삭제
EXPIRE cache:product:100 10
- 캐시 만료까지 남은 시간 확인
TTL cache:product:100
- TTL 만료 전 → 캐시 히트(Cache Hit)
GET cache:product:100
과제
- TTL 만료 후 다시 GET 했을 때 값을 확인하고, 재캐싱을 수행하시오.
5. 영속화(Persistence): RDB / AOF
Redis 설정 파일 위치(우분투 패키지 기본):
/etc/redis/redis.conf- 데이터 디렉터리: 보통
/var/lib/redis
5-1) 현재 설정 확인
sudo grep -E "^(save|appendonly|appendfsync|dir|dbfilename)" /etc/redis/redis.conf
sudo egrep "^(save|appendonly|appendfsync|dir|dbfilename)" /etc/redis/redis.conf또는 redis-cli에서:
redis-cli CONFIG GET save
redis-cli CONFIG GET appendonly
redis-cli CONFIG GET dir5-2) RDB 스냅샷(기본)
수동 저장:
redis-cli SAVE백그라운드 저장:
redis-cli BGSAVERDB 파일 위치 확인:
redis-cli CONFIG GET dir
redis-cli CONFIG GET dbfilename
sudo ls -al /var/lib/redis복구 실습(안전하게 진행)
- 샘플 데이터 생성
redis-cli FLUSHDB
redis-cli SET rdb:test "hello"
redis-cli BGSAVE- Redis 중지 후 데이터 파일 확인
sudo systemctl stop redis-server
sudo ls -al /var/lib/redis- Redis 재시작 후 데이터 확인
sudo systemctl start redis-server
redis-cli GET rdb:test5-3) AOF 활성화(권장: 데이터 중요 시)
- 설정 변경
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
sudo sed -i 's/^appendonly no/appendonly yes/' /etc/redis/redis.conf
sudo sed -i 's/^# appendfsync everysec/appendfsync everysec/' /etc/redis/redis.conf- 서비스 재시작
sudo systemctl restart redis-server- AOF 파일 생성 확인
sudo ls -al /var/lib/redis
redis-cli CONFIG GET appendonlyAOF 재작성(압축)
redis-cli BGREWRITEAOF과제
- AOF 켠 상태에서 키 3개 저장 후 재시작해도 남아있는지 검증
6. 운영 관점 필수 점검(메모리/모니터링/슬로우로그)
6-1) 메모리 확인
INFO memory
MEMORY STATS
MEMORY USAGE user:1
6-2) 실시간 모니터링(주의: 운영에서 과다 사용 금지)
redis-cli MONITOR6-3) Slowlog
CONFIG SET slowlog-log-slower-than 10000
CONFIG SET slowlog-max-len 128
SLOWLOG LEN
SLOWLOG GET 10
6-4) 클라이언트/연결 확인
INFO clients
CLIENT LIST
7. 보안 기본(실습 환경 기준)
7-1) 기본 바인딩/접근 제한 확인
sudo grep -E "^(bind|protected-mode|requirepass)" /etc/redis/redis.conf- 실습 로컬에서만 쓸 거면:
bind 127.0.0.1 ::1유지 권장 - 외부 접속 허용은 매우 신중(비밀번호 + 방화벽 + 네트워크 분리 전제)
7-2) 비밀번호 설정(requirepass)
sudo sed -i 's/^# requirepass .*/requirepass StrongPassw0rd!/' /etc/redis/redis.conf
sudo systemctl restart redis-server접속 테스트:
redis-cli ping
# (NOAUTH 에러 기대)
redis-cli -a 'StrongPassw0rd!' ping7-3) UFW 방화벽(외부 차단)
sudo ufw status
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw deny 6379/tcp
sudo ufw status8. 복제(Replication) 실습: 2대 VM 또는 2개 인스턴스
아래는 노션에 그대로 붙여넣기 가능한 Redis Master–Replica 복제 실습 교안입니다.
(우분투 기준, 2대 VM 또는 1대에서 포트만 다르게 2인스턴스 모두 제공)
0. 실습 준비
권장 환경
- Ubuntu 22.04 서버 2대 (또는 1대에서 2인스턴스)
- IP 예시
- Master:
192.168.80.110 - Replica:
192.168.80.120
- Master:
포트
- 기본:
6379
1) Redis 설치 (두 서버 모두)
sudo apt update
sudo apt install -y redis-server
redis-server --version서비스 상태 확인:
sudo systemctl status redis-server --no-pager2) 방화벽/네트워크 확인 (두 서버 모두)
UFW를 쓰는 경우(예시):
sudo ufw allow 6379/tcp
sudo ufw status서로 통신 확인(Replica → Master):
nc -zv 192.168.80.110 63793) Master 설정 (192.168.80.110)
설정 파일:
sudo vi /etc/redis/redis.conf아래 항목을 찾아 수정/확인:
bind 0.0.0.0
port 6379
protected-mode yes
requirepass StrongPassw0rd!
# (선택) 실습 중 위험 명령 막기 - 운영용 권장
# rename-command FLUSHALL ""
# rename-command FLUSHDB ""재시작:
sudo systemctl restart redis-server외부 접속 확인(로컬에서):
redis-cli -a StrongPassw0rd! PING
# PONGMaster 역할 확인:
redis-cli -a StrongPassw0rd! INFO replication | egrep "role|connected_slaves"
# role:master
# connected_slaves:04) Replica 설정 (192.168.80.120)
설정 파일:
sudo vi /etc/redis/redis.conf아래 항목을 찾아 수정/확인:
bind 0.0.0.0
port 6379
protected-mode yes
requirepass StrongPassw0rd!
# Master 인증 (Master에 requirepass가 있을 때 필수)
masterauth StrongPassw0rd!
# 복제 대상 지정 (중요)
replicaof 192.168.80.110 6379재시작:
sudo systemctl restart redis-serverReplica 역할 확인:
redis-cli -a StrongPassw0rd! INFO replication | egrep "role|master_host|master_link_status"정상 출력 예:
role:slave
master_host:192.168.80.110
master_link_status:up
Master에서 Replica 연결 확인:
redis-cli -a StrongPassw0rd! INFO replication | egrep "connected_slaves|slave0"5) 복제 동작 확인
5-1) Master에 데이터 쓰기
Master에서:
redis-cli -a StrongPassw0rd! SET demo:key "hello"
redis-cli -a StrongPassw0rd! INCR demo:counter
redis-cli -a StrongPassw0rd! INCR demo:counter
redis-cli -a StrongPassw0rd! GET demo:key
redis-cli -a StrongPassw0rd! GET demo:counter5-2) Replica에서 동일 데이터 읽기
Replica에서:
redis-cli -a StrongPassw0rd! GET demo:key
redis-cli -a StrongPassw0rd! GET demo:counter기대 결과:
demo:key→"hello"demo:counter→"2"
6) Replica 쓰기 금지 확인
Replica에서:
redis-cli -a StrongPassw0rd! SET replica:write "no"기대 결과:
(error) READONLY You can't write against a read only replica.
7) 복제 해제 / 전환 실습
7-1) Replica 복제 해제(Standalone로 전환)
Replica에서:
redis-cli -a StrongPassw0rd! REPLICAOF NO ONE확인:
redis-cli -a StrongPassw0rd! INFO replication | egrep "role|master_host"
# role:master이제 Replica였던 서버에서 쓰기 가능:
redis-cli -a StrongPassw0rd! SET now:master "ok"7-2) 다시 Master(192.168.80.110) 따라가도록 재설정
Replica(전환된 서버)에서:
redis-cli -a StrongPassw0rd! REPLICAOF 192.168.80.110 63798) 장애/운영 관점 포인트
8-1) 복제는 자동 승격이 아님
- Master가 죽어도 Replica가 자동으로 Master가 되지 않음
- 자동 장애조치가 필요하면:
- Redis Sentinel 또는
- 클러스터/관리형(예: ElastiCache Multi-AZ) 고려
8-2) 보안 필수 요소
bind를 내부망 IP로 제한하거나 보안그룹/방화벽으로 제한requirepass설정- 복제에는
masterauth설정
연결이 안 될 때(Replica에서)
Replica에서:
redis-cli -a StrongPassw0rd! INFO replication | egrep "master_link_status|master_last_io_seconds_ago|master_host"Master에서:
redis-cli -a StrongPassw0rd! INFO replication | egrep "connected_slaves|slave0"로그 확인:
sudo journalctl -u redis-server -n 200 --no-pager자주 원인:
- Master 포트(6379) 방화벽 차단
- Master
bind 127.0.0.1로 외부 접속 불가 requirepass는 있는데 Replica에masterauth누락- 서로 다른 Redis 인스턴스/포트에 붙음