Skip to content

Redis

Redis — это открытая база данных ключ-значение (Key-Value), написанная на языке ANSI C, соблюдающая лицензию BSD, поддерживающая сеть, работающая на основе памяти, распределённая, с опциональной персистентностью. Redis предоставляет API для множества языков программирования и может использоваться как 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, // Использование базы данных по умолчанию
   })

   // Установка пары ключ-значение, 0 означает без срока годности
   redisClient.Set("hello", "world", 0)

   // Чтение значения
   result, err := redisClient.Get("hello").Result()
   if err == redis.Nil {
      fmt.Println("ключ не существует")
   } 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

  // Минимальный интервал между повторными попытками.
  // По умолчанию 8мс; -1 отключает.
  MinRetryBackoff time.Duration

  // Максимальный интервал между повторными попытками
  // По умолчанию 512мс; -1 отключает.
  MaxRetryBackoff time.Duration

  // Таймаут создания нового подключения redis.
  // По умолчанию 5 секунд.
  DialTimeout time.Duration

  // Таймаут чтения сокета
  // По умолчанию 3 секунды.
  ReadTimeout time.Duration

  // Таймаут записи сокета
  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, // Использование базы данных по умолчанию
})

Закрытие подключения

Драйвер внутренне поддерживает пул подключений, поэтому не нужно закрывать подключение после каждой операции.

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