Skip to content

Redis

Redis 는 오픈소스로 ANSI C 언어로 작성되었으며 BSD 프로토콜을 준수하고, 네트워크를 지원하며, 메모리 기반, 분산, 선택적 영속성이 있는 키 - 값 (Key-Value) 저장 데이터베이스로, 여러 언어의 API 를 제공하며 Redis 는 NoSQL 데이터베이스로도 사용할 수 있고 고속 캐시 스토리지로도 사용할 수 있으며 간단한 메시지 큐도 지원합니다.

이 문서에서는 Go 언어 드라이버를 사용하여 Redis 데이터베이스를 조작하는 방법만 설명하며, Redis 자체에 대해서는 설명하지 않습니다.

공식 문서: Golang Redis client (uptrace.dev)

공식 저장소: go-redis/redis: Type-safe Redis client for Golang (github.com)

설치

Redis 드라이버는 여러 가지가 있으며, 이 문서에서는 github.com/go-redis/redis를 사용합니다.

Redis 버전이 6 인 경우

go get github.com/go-redis/redis/v8

Redis 버전이 7 인 경우

go get github.com/go-redis/redis/v9

빠른 시작

go
import (
   "fmt"
   "log"
   "testing"

   "github.com/go-redis/redis"
)

func TestQuickStart(t *testing.T) {
   // Redis 연결 클라이언트 생성
   redisClient := redis.NewClient(&redis.Options{
      Addr:     "192.168.48.134:6379",
      Password: "123456",
      DB:       0, // 기본 DB 사용
   })

   // 키 - 값 쌍 설정, 0 은 만료되지 않음
   redisClient.Set("hello", "world", 0)

   // 값 읽기
   result, err := redisClient.Get("hello").Result()
   if err == redis.Nil {
      fmt.Println("ket not exist")
   } else if err != nil {
      log.Panic(err)
   }
   fmt.Println(result)
}

연결 설정

go
type Options struct {
  // 네트워크 유형 tcp 또는 unix.
  // 기본값은 tcp.
  Network string
  // redis 주소, 형식 host:port
  Addr string

    // Dialer 는 새로운 네트워크 연결을 생성하며 Network 와 Addr 옵션보다 우선순위가 높음
  // Network and Addr options.
  Dialer func() (net.Conn, error)

  // 새로운 redis 연결을 생성할 때 호출되는 함수
  OnConnect func(*Conn) error

  // redis 비밀번호, redis server 에 설정되지 않은 경우 비워둘 수 있음
  Password string

  // redis 데이터베이스, 인덱스는 0 부터 시작하며 기본값은 0, 설정하지 않아도 됨
  DB int

  // redis 작업 실패 시 최대 재시도 횟수, 기본값 0.
  MaxRetries int

  // 최소 재시도 시간 간격.
  // 기본값은 8ms ; -1 은 비활성화.
  MinRetryBackoff time.Duration

  // 최대 재시도 시간 간격
  // 기본값은 512ms; -1 은 비활성화.
  MaxRetryBackoff time.Duration

  // redis 새 연결 타임아웃 시간.
  // 기본값은 5 초.
  DialTimeout time.Duration

  // socket 읽기 타임아웃 시간
  // 기본값 3 초.
  ReadTimeout time.Duration

  // socket 쓰기 타임아웃 시간
  WriteTimeout time.Duration

  // redis 연결 풀의 최대 연결 수.
  // 기본 연결 풀 크기는 cpu 개수 * 10
  PoolSize int

  // redis 연결 풀의 최소 유휴 연결 수.
  MinIdleConns int

  // redis 연결의 최대 수명 시간, 기본값은 만료된 연결을 닫지 않음.
  MaxConnAge time.Duration

  // redis 연결 풀에서 연결을 가져온 후, 연결 풀이 해당 연결을 얼마나 기다릴지.
  // 기본값은 ReadTimeout + 1 초.
  PoolTimeout time.Duration

  // redis 연결 풀이 유휴 연결을 닫는 시간.
  // 기본값은 5 분. -1 은 이 설정 항목 비활성화
  IdleTimeout time.Duration

  // 유휴 연결을 얼마나 자주 확인하는지
  // 기본값은 1 분. -1 은 유휴 연결 확인 비활성화
  IdleCheckFrequency time.Duration

  // 읽기 전용 설정, true 로 설정하면 현재 노드 인스턴스에서 redis 는 쿼리만 가능하고 업데이트 불가.
  readOnly bool

    // TLS 설정
  TLSConfig *tls.Config
}

연결 설정

go
// Redis 연결 클라이언트 생성
redisClient := redis.NewClient(&redis.Options{
    Addr:     "192.168.48.134:6379",
    Password: "123456",
    DB:       0, // 기본 DB 사용
})

연결 닫기

드라이버 내부에서 연결 풀을 관리하므로 작업할 때마다 연결을 닫을 필요가 없습니다.

go
defer redisClient.Close()

이 Redis 드라이버는 거의 모든 작업을 캡슐화했으며, Redis 명령과 메서드 이름이 일대일로 대응되므로 기본적으로 Redis 명령 사용법을 알면 드라이버의 해당 메서드도 거의 사용할 수 있습니다.

Redis 명령: redis 명령 매뉴얼

기본 작업

키 삭제

go
redisClient.Set("name", "jack", 0)
fmt.Println(redisClient.Del("name").Result())

만료 시간

go
redisClient.Set("name", "jack", 0)
// 만료 시간 설정
redisClient.Expire("name", time.Second*2)
fmt.Println(redisClient.Get("name").Val())
time.Sleep(time.Second * 3)
fmt.Println(redisClient.Get("name").Val())

만료 시간 취소

go
redisClient.Set("name", "jack", 2)
// 만료 시간 취소
redisClient.Persist("name")
time.Sleep(time.Second * 2)
fmt.Println(redisClient.Get("name"))

만료 시간 조회

go
fmt.Println(redisClient.TTL("name"))
fmt.Println(redisClient.PTTL("name"))

이름 변경

go
redisClient.Rename("name", "newName")

유형 조회

go
redisClient.Type("name")

스캔

go
fmt.Println(redisClient.Scan(0, "", 4))

문자열

단순 저장 및 읽기

go
redisClient.Set("token", "abcefghijklmn", 0)
fmt.Println(redisClient.Get("token").Val())

일괄 저장 및 읽기

go
redisClient.MSet("cookie", "12345", "token", "abcefg")
fmt.Println(redisClient.MGet("cookie", "token").Val())

숫자 증감

go
redisClient.Set("age", "1", 0)
// 증가
redisClient.Incr("age")
fmt.Println(redisClient.Get("age").Val())
// 감소
redisClient.Decr("age")
fmt.Println(redisClient.Get("age").Val())

해시 테이블

읽기 및 쓰기 작업

go
// 단일 설정
redisClient.HSet("map", "name", "jack")
// 일괄 설정
redisClient.HMSet("map", map[string]interface{}{"a": "b", "c": "d", "e": "f"})
// 단일 액세스
fmt.Println(redisClient.HGet("map", "a").Val())
// 일괄 액세스
fmt.Println(redisClient.HMGet("map", "a", "b").Val())
// 전체 map 가져오기
fmt.Println(redisClient.HGetAll("map").Val())

출력

b
[b <nil>]
map[a:b c:d e:f name:jack]

키 삭제

go
// map 의 필드 삭제
redisClient.HDel("map", "a")

키 존재 여부 확인

go
// 필드 존재 여부 확인
redisClient.HExists("map", "a")

모든 키 가져오기

go
// map 의 모든 키 가져오기
redisClient.HKeys("map")

해시 테이블 키 길이 가져오기

go
// map 길이 가져오기
redisClient.HLen("map")

해시 테이블 키 - 값 쌍 순회

go
// map 의 키 - 값 쌍 순회
redisClient.HScan("map", 0, "", 1)

리스트

요소 수정

go
// 왼쪽에 추가
redisClient.LPush("list", "a", "b", "c", "d", "e")
// 오른쪽에 추가
redisClient.RPush("list", "g", "i", "a")
// 참조 값 앞에 값 삽입
redisClient.LInsertBefore("list", "a", "aa")
// 참조 값 뒤에 값 삽입
redisClient.LInsertAfter("list", "a", "gg")
// 지정된 인덱스의 요소 값 설정
redisClient.LSet("list", 0, "head")

길이 액세스

go
// 리스트 길이 액세스
redisClient.LLen("list")

요소 액세스

go
// 왼쪽에서 요소 팝
redisClient.LPop("list")
// 오른쪽에서 요소 팝
redisClient.RPop("list")
// 지정된 인덱스의 요소 액세스
redisClient.LIndex("list", 1)
// 지정된 범위의 요소 액세스
redisClient.LRange("list", 0, 1)

요소 삭제

go
// 지정된 요소 삭제
redisClient.LRem("list", 0, "a")
// 지정된 범위의 요소 삭제
redisClient.LTrim("list", 0, 1)
// 지정된 범위의 요소 유지
redisClient.LTrim("list", 0, 1)

집합

요소 추가

go
// 집합에 요소 추가
redisClient.SAdd("set", "a", "b", "c")
redisClient.SAdd("set2", "c", "d", "e")

집합 요소 액세스

go
// 집합의 모든 멤버 가져오기
redisClient.SMembers("set")
// 요소가 집합에 속하는지 확인
redisClient.SIsMember("set", "a")
// count 개의 요소 무작위 반환
redisClient.SRandMemberN("set", 1)
// 집합의 요소 개수 가져오기
redisClient.SCard("set")

집합 작업

go
// 주어진 집합의 차집합 반환
redisClient.SDiff("set", "set2")
// 주어진 집합의 차집합을 결과 집합에 저장하고 결과 집합의 길이 반환
redisClient.SDiffStore("store", "set", "se2")
// 주어진 집합의 교집합 반환
redisClient.SInter("set", "set2")
// 주어진 집합의 교집합을 결과 집합에 저장하고 결과 집합의 길이 반환
redisClient.SInterStore("store", "set", "set2")
// 주어진 집합의 합집합 반환
redisClient.SUnion("set", "set2")
// 주어진 집합의 합집합을 결과 집합에 저장하고 결과 집합의 길이 반환
redisClient.SUnionStore("store", "set", "store")

요소 삭제

go
// 요소 팝 및 삭제
redisClient.SPop("set")
// N 개 요소 팝 및 삭제
redisClient.SPopN("set", 2)

요소 이동

go
// 소스 집합에서 지정된 요소를 대상 집합으로 이동
redisClient.SMove("set", "set2", "a")

요소 삭제

go
// 지정된 요소 삭제
redisClient.SRem("set", "a", "b")

순회

go
// 집합 순회
redisClient.SScan("set", 0, "", 2)

정렬된 집합

요소 추가

go
// 정렬된 집합에 요소 추가
redisClient.ZAdd("ss", redis.Z{
   Score:  1,
   Member: "a",
}, redis.Z{
   Score:  2,
   Member: "b",
})

요소 순위

go
// 정렬된 집합에서 요소의 순위 반환, 낮은 것에서 높은 것으로 정렬
redisClient.ZRank("ss", "1")
// 정렬된 집합에서 요소의 순위 반환, 높은 것에서 낮은 것으로 정렬
redisClient.ZRevRank("ss", "1")

요소 액세스

go
// min 과 max 사이의 멤버 수 반환
redisClient.ZCount("ss", "1", "2")

// 요소의 가중치 반환
redisClient.ZScore("ss", "a")

// 지정된 구간의 요소 반환
redisClient.ZRange("ss", 1, 2)
// min 과 max 사이의 모든 멤버 목록 반환
redisClient.ZRangeByScore("ss", redis.ZRangeBy{
   Min:    "1",
   Max:    "2",
   Offset: 0,
   Count:  1,
})

가중치 수정

go
// 해당 요소에 가중치 증가
redisClient.ZIncr("ss", redis.Z{
   Score:  2,
   Member: "b",
})

요소 삭제

go
// 지정된 요소 삭제
redisClient.ZRem("ss", "a")
// 지정된 순위 구간의 요소 삭제
redisClient.ZRemRangeByRank("ss", 1, 2)
// min 과 max 구간의 가중치를 가진 요소 삭제
redisClient.ZRemRangeByScore("ss", "1", "2")

스크립트

go
// 스크립트 로드, sha 값 반환
redisClient.ScriptLoad("return 0")
// sha 값으로 스크립트 실행
redisClient.EvalSha("sha", []string{}, "")
// 스크립트 직접 실행
redisClient.Eval("return 0", []string{}, "")
// 스크립트 캐시 지우기
redisClient.ScriptFlush()
// 현재 실행 중인 스크립트 중지
redisClient.ScriptKill()
// 해당 해시 값의 스크립트 존재 여부 확인
redisClient.ScriptExists("")

게시 및 구독

go
// 지정된 채널로 메시지 전송
redisClient.Publish("channel", "message")
// 지정된 채널 구독
redisClient.Subscribe("channel")
// 구독 상태 확인
redisClient.PubSubNumSub("channel")

Golang by www.golangdev.cn edit