Interagir com o Cache do Azure para Redis usando o .NET
Normalmente, um aplicativo cliente usará uma biblioteca de clientes para formar solicitações e executar comandos em um Cache Redis. Você pode obter uma lista de bibliotecas de cliente diretamente na Página de clientes Redis.
Execução de comandos no cache Redis
Um cliente popular de Redis de alto desempenho para a linguagem .NET é StackExchange.Redis. O pacote está disponível por meio do NuGet e pode ser adicionado ao código .NET usando a linha de comando ou o IDE. Veja abaixo exemplos de como usar o cliente.
Conectar-se ao seu cache Redis com stackExchange.Redis
Lembre-se de que usamos o endereço do host, o número da porta e uma chave de acesso para se conectar a um servidor Redis. O Azure também oferece uma cadeia de conexão para alguns clientes do Redis que agrupa esses dados em uma única cadeia de caracteres. Ela é parecida com o seguinte (com os campos cache-name
e password-here
preenchidos com valores reais):
[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False
Você pode passar essa cadeia de caracteres para StackExchange.Redis a fim de criar uma conexão com o servidor.
Observe que há dois parâmetros adicionais no final:
- ssl - garante que a comunicação seja criptografada.
- abortConnection - permite a criação de uma conexão, mesmo se o servidor estiver indisponível no momento.
Há vários outros parâmetros opcionais que você pode acrescentar à cadeia de caracteres para configurar a biblioteca de clientes.
Criar uma nova conexão
O objeto de conexão principal no StackExchange.Redis é a classe StackExchange.Redis.ConnectionMultiplexer
. Esse objeto abstrai o processo de conexão com um servidor Redis (ou grupo de servidores). Ele foi otimizado para gerenciar conexões com eficiência e deve ser mantido por perto enquanto você precisa ter acesso ao cache.
Crie uma instância de ConnectionMultiplexer
usando o método estático ConnectionMultiplexer.Connect
ou ConnectionMultiplexer.ConnectAsync
, passando uma cadeia de conexão ou um objeto ConfigurationOptions
.
Confira um exemplo simples:
using StackExchange.Redis;
...
var connectionString = "[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False";
var redisConnection = ConnectionMultiplexer.Connect(connectionString);
Quando você tiver um ConnectionMultiplexer
, há três coisas principais que talvez você queira fazer:
- Acessar um banco de dados Redis.
- Usar os recursos publicador/assinante do Redis, que está fora do escopo deste módulo.
- Acessar um servidor individual para manutenção ou monitoramento.
Acessar um banco de dados Redis
O tipo IDatabase
representa o banco de dados Redis. Você pode recuperar um usando o método GetDatabase()
:
IDatabase db = redisConnection.GetDatabase();
Dica
O objeto retornado por GetDatabase
é um objeto leve, e não precisa ser armazenado. Somente o ConnectionMultiplexer
precisa ser mantido ativo.
Quando você tem um objeto IDatabase
, pode executar métodos para interagir com o cache. Todos os métodos têm versões síncronas e assíncronas que retornam objetos Task
para torná-los compatíveis com as palavras-chave async
e await
.
A seguir está um exemplo de como armazenar uma chave/valor no cache:
bool wasSet = db.StringSet("favorite:flavor", "i-love-rocky-road");
O método StringSet
retorna um bool
indicando se o valor foi definido (true
) ou não (false
). Em seguida, recuperamos o valor com o método StringGet
:
string value = db.StringGet("favorite:flavor");
Console.WriteLine(value); // displays: ""i-love-rocky-road""
Obter e definir valores binários
Lembre-se de que as chaves e valores de Redis são válidos para binários. Esses mesmos métodos podem ser usados para armazenar dados binários. Há operadores de conversão implícitos para trabalhar com tipos byte[]
, para que você possa trabalhar naturalmente com os dados:
byte[] key = ...;
byte[] value = ...;
db.StringSet(key, value);
byte[] key = ...;
byte[] value = db.StringGet(key);
StackExchange.Redis representa chaves usando o tipo RedisKey
. Essa classe tem conversões implícitas de string
e byte[]
, permitindo que as chaves de texto e binário sejam usadas sem qualquer complicação. Os valores são representados pelo tipo RedisValue
. Assim como acontece com RedisKey
, há conversões implícitas em vigor para permitir que você passe string
ou byte[]
.
Outras operações comuns
A interface IDatabase
inclui vários outros métodos para trabalhar com o cache Redis. Há métodos para trabalhar com hashes, listas, conjuntos e conjuntos ordenados.
Estes são alguns dos mais comuns que funcionam com chaves únicas. É possível ler o código-fonte da interface ver a lista completa.
Método | Descrição |
---|---|
CreateBatch |
Cria um grupo de operações a serem enviadas ao servidor como uma única unidade, mas não necessariamente processadas como uma unidade. |
CreateTransaction |
Cria um grupo de operações a serem enviadas ao servidor como uma única unidade e processadas no servidor como uma única unidade. |
KeyDelete |
Exclua a chave/valor. |
KeyExists |
Retorna se a chave especificada existe no cache. |
KeyExpire |
Define uma expiração de TTL (vida útil) em uma chave. |
KeyRename |
Renomeia uma chave. |
KeyTimeToLive |
Retorna a TTL de uma chave. |
KeyType |
Retorna a representação de cadeia de caracteres do tipo do valor armazenado na chave. Os diferentes tipos para retorno são: cadeia de caracteres, lista, conjunto, zset e hash. |
Executar outros comandos
O objeto IDatabase
tem um método Execute
e ExecuteAsync
que pode ser usado para passar comandos textuais para o servidor Redis. Por exemplo:
var result = db.Execute("ping");
Console.WriteLine(result.ToString()); // displays: "PONG"
Os métodos Execute
e ExecuteAsync
retornam um objeto RedisResult
que é um detentor de dados que inclui duas propriedades:
Resp2Type
que retorna umstring
indicando o tipo do resultado –STRING
,INTEGER
etc.IsNull
um valor true/false para detectar quando o resultado énull
.
Depois, você pode usar ToString()
no RedisResult
para obter o valor de retorno real.
Use Execute
para executar qualquer comando de suporte, por exemplo, todos os clientes podem ficar conectados ao cache ("LISTA DE CLIENTES"):
var result = await db.ExecuteAsync("client", "list");
Console.WriteLine($"Type = {result.Resp2Type}\r\nResult = {result}");
Isso gera todos os clientes conectados:
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
Armazenar valores mais complexos
Redis é orientado por cadeias de caracteres binárias seguras, mas você pode armazenar em cache grafos de objeto serializando-os para um formato textual, normalmente XML ou JSON. Por exemplo, talvez para as nossas estatísticas, temos um objeto GameStats
que se parece com:
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"))}";
}
}
Poderíamos usar a biblioteca Newtonsoft.Json para transformar uma instância desse objeto em uma cadeia de caracteres:
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);
Poderíamos recuperá-la e transformá-la de volta em um objeto usando o processo inverso:
var result = db.StringGet("event:2019-local-game");
var stat = Newtonsoft.Json.JsonConvert.DeserializeObject<GameStat>(result.ToString());
Console.WriteLine(stat.Sport); // displays "Soccer"
Limpar a conexão
Quando a conexão não for mais necessária, você poderá Dispose
o ConnectionMultiplexer
. Isso fechará todas as conexões e desligará a comunicação com o servidor.
redisConnection.Dispose();
redisConnection = null;