Взаимодействие с кэшем Azure для Redis с помощью .NET
Как правило, клиентское приложение использует клиентская библиотека для формирования запросов и выполнения команд в кэше Redis. Список доступных клиентских библиотек можно получить на странице клиентов Redis.
Выполнение команд в кэше Redis
Для языка .NET самым популярным является высокопроизводительный клиент Redis StackExchange.Redis. Этот пакет можно получить с помощью NuGet и добавить в код .NET, используя командную строку или интегрированную среду разработки. Ниже приведены примеры использования клиента.
Подключение к кэшу Redis с помощью StackExchange.Redis
Как вы помните, для подключения к серверу Redis нужны адрес узла, номер порта и ключ доступа. Azure также предлагает строка подключения для некоторых клиентов Redis, которые объединяют эти данные в одну строку. Это выглядит примерно так (с cache-name
полями, password-here
заполненными реальными значениями):
[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False
Для создания подключения к серверу строку следует передать в StackExchange.Redis.
Обратите внимание, что в конце есть еще два параметра:
- ssl — требует шифровать создаваемое подключение;
- abortConnection — позволяет создать подключение, даже если сервер в данный момент недоступен.
Существует несколько других необязательных параметров, которые можно включить в строку подключения для настройки клиентской библиотеки.
Создание подключения
Основным объектом подключения в библиотеке StackExchange.Redis является класс StackExchange.Redis.ConnectionMultiplexer
. Этот объект абстрагирует процесс подключения к серверу (или группе серверов) Redis. Он оптимизирован для эффективного управления подключениями и всегда должен быть доступным при любых действиях с кэшем.
Создать экземпляр ConnectionMultiplexer
можно с помощью статического метода ConnectionMultiplexer.Connect
или ConnectionMultiplexer.ConnectAsync
, передав строку подключения или объект ConfigurationOptions
.
Вот простой пример.
using StackExchange.Redis;
...
var connectionString = "[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False";
var redisConnection = ConnectionMultiplexer.Connect(connectionString);
Получив ConnectionMultiplexer
, вы можете выполнить три основные действия:
- Получить доступ к базе данных Redis.
- Используйте функции издателя или подписчика Redis, которые находятся вне области этого модуля.
- Обратиться к отдельному серверу для обслуживания или мониторинга.
Получение доступа к базе данных Redis
Тип IDatabase
представляет базу данных Redis. Его можно получить с помощью метода GetDatabase()
:
IDatabase db = redisConnection.GetDatabase();
Совет
Возвращенный из метода GetDatabase
объект не требует много места или постоянного сохранения. Достаточно лишь сохранять активное состояние ConnectionMultiplexer
.
Получив объект IDatabase
, вы можете выполнять его методы для взаимодействия с кэшем. Все методы имеют синхронные и асинхронные версии, возвращающие Task
объекты для их совместимости с async
ключевыми словами.await
Ниже приведен пример хранения ключа или значения в кэше:
bool wasSet = db.StringSet("favorite:flavor", "i-love-rocky-road");
Метод StringSet
возвращает bool
, значение которого сообщает, что значение сохранено успешно (true
) или нет (false
). Затем это значение можно получить с помощью метода StringGet
:
string value = db.StringGet("favorite:flavor");
Console.WriteLine(value); // displays: ""i-love-rocky-road""
Получение и сохранение двоичных значений
Как вы помните, ключи и значения Redis предоставляются в виде двоичных безопасных строк. Это означает, что для хранения двоичных данных можно использовать те же методы. Для работы с типами byte[]
существуют операторы неявного преобразования, а значит, с данными можно работать естественным образом:
byte[] key = ...;
byte[] value = ...;
db.StringSet(key, value);
byte[] key = ...;
byte[] value = db.StringGet(key);
StackExchange.Redis представляет ключи через тип RedisKey
. Этот класс использует неявные преобразования в string
или byte[]
и обратно, позволяя использовать текстовые и двоичные значения ключей без сложностей. Значения представлены типом RedisValue
. Как и для RedisKey
, используются неявные преобразования, позволяющие передавать значение string
или byte[]
.
Другие распространенные операции
Интерфейс IDatabase
включает несколько других методов для работы с кэшем Redis. В их число входят методы для работы с хэшами, списками, наборами и упорядоченными наборами.
Вот некоторые наиболее распространенные методы, которые работают с индивидуальными ключами. Полный список методов можно получить, изучив исходный код интерфейса.
Метод | Description |
---|---|
CreateBatch |
Создает группу операций для отправки на сервер в виде одной единицы, но не обязательно обрабатывается как единица. |
CreateTransaction |
Создает группу операций для отправки на сервер в виде одной единицы и обрабатывается на сервере в виде одной единицы. |
KeyDelete |
Удаляет пару "ключ-значение". |
KeyExists |
Возвращает информацию о том, существует ли указанный ключ в кэше. |
KeyExpire |
Задает для ключа срок жизни (TTL). |
KeyRename |
Переименовывает ключ. |
KeyTimeToLive |
Возвращает значение TTL для ключа. |
KeyType |
Возвращает строковое представление типа, который используется для значения ключа. Могут быть возвращены различные типы: строка, список, набор, zset и хэш. |
Выполнение других команд
Объект IDatabase
имеет Execute
метод и ExecuteAsync
метод, который можно использовать для передачи текстовых команд серверу Redis. Например:
var result = db.Execute("ping");
Console.WriteLine(result.ToString()); // displays: "PONG"
ExecuteAsync
Методы Execute
возвращают RedisResult
объект, который является владельцем данных, который включает два свойства:
Resp2Type
возвращаетstring
тип результата —STRING
,INTEGER
и т. д.IsNull
содержит значение true или false, которое обозначает, является ли результатnull
.
Для получения фактического возвращаемого значения можно использовать ToString()
для RedisResult
.
Метод Execute
позволяет выполнить любые поддерживаемые команды — например, получить полный список клиентов, подключенных к кэшу (CLIENT LIST):
var result = await db.ExecuteAsync("client", "list");
Console.WriteLine($"Type = {result.Resp2Type}\r\nResult = {result}");
Это выводит все подключенные клиенты:
Type = BulkString
Result = id=9469 addr=16.183.122.154:54961 fd=18 name=DESKTOP-AAAAAA age=0 idle=0 flags=N db=0 sub=1 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 ow=0 owmem=0 events=r cmd=subscribe numops=5
id=9470 addr=16.183.122.155:54967 fd=13 name=DESKTOP-BBBBBB age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 ow=0 owmem=0 events=r cmd=client numops=17
Хранение более сложных значений
Redis ориентирован на двоичные безопасные строки, но вы можете кэшировать и графы объектов, сериализуя их в текстовый формат (чаще всего применяются XML или JSON). Например, возможно, для нашей статистики у нас есть GameStats
объект, который выглядит следующим образом:
public class GameStat
{
public string Id { get; set; }
public string Sport { get; set; }
public DateTimeOffset DatePlayed { get; set; }
public string Game { get; set; }
public IReadOnlyList<string> Teams { get; set; }
public IReadOnlyList<(string team, int score)> Results { get; set; }
public GameStat(string sport, DateTimeOffset datePlayed, string game, string[] teams, IEnumerable<(string team, int score)> results)
{
Id = Guid.NewGuid().ToString();
Sport = sport;
DatePlayed = datePlayed;
Game = game;
Teams = teams.ToList();
Results = results.ToList();
}
public override string ToString()
{
return $"{Sport} {Game} played on {DatePlayed.Date.ToShortDateString()} - " +
$"{String.Join(',', Teams)}\r\n\t" +
$"{String.Join('\t', Results.Select(r => $"{r.team } - {r.score}\r\n"))}";
}
}
С помощью библиотеки Newtonsoft.Json мы может преобразовать экземпляр этого объекта в строку:
var stat = new GameStat("Soccer", new DateTime(2019, 7, 16), "Local Game",
new[] { "Team 1", "Team 2" },
new[] { ("Team 1", 2), ("Team 2", 1) });
string serializedValue = Newtonsoft.Json.JsonConvert.SerializeObject(stat);
bool added = db.StringSet("event:1950-world-cup", serializedValue);
Получив эту строку из кэша, мы преобразуем ее в объект с помощью обратного процесса:
var result = db.StringGet("event:2019-local-game");
var stat = Newtonsoft.Json.JsonConvert.DeserializeObject<GameStat>(result.ToString());
Console.WriteLine(stat.Sport); // displays "Soccer"
Очистка подключения
Если подключение больше не требуется, можно Dispose
ConnectionMultiplexer
использовать . Это закрывает все подключения и завершает связь с сервером.
redisConnection.Dispose();
redisConnection = null;