Interakcja z usługą Azure Cache for Redis przy użyciu platformy .NET

Ukończone

Zazwyczaj aplikacja kliencka używa biblioteki klienta do tworzenia żądań i wykonywania poleceń w pamięci podręcznej Redis Cache. Listę bibliotek klienckich możesz uzyskać bezpośrednio ze strony klientów usługi Redis.

Wykonywanie poleceń w pamięci podręcznej Redis

Popularnym klientem usługi Redis o wysokiej wydajności dla języka .NET jest StackExchange.Redis. Ten pakiet jest dostępny za pośrednictwem pakietu NuGet i może zostać dodany do Twojego kodu platformy .NET przy użyciu wiersza polecenia lub środowiska IDE. Poniżej przedstawiono przykłady korzystania z klienta.

Nawiązywanie połączenia z pamięcią podręczną Redis przy użyciu klienta StackExchange.Redis

Przypomnij sobie, że do połączenia z serwerem usługi Redis używaliśmy adresu hosta, numeru portu i klucza dostępu. Platforma Azure oferuje również parametry połączenia dla niektórych klientów usługi Redis, którzy łączą te dane w jeden ciąg. Wygląda to podobnie do poniższego (z cache-name polami i password-here wypełnionymi rzeczywistymi wartościami):

[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False

Możesz przekazać ten ciąg do klienta StackExchange.Redis w celu utworzenia połączenia z serwerem.

Zwróć uwagę, że na końcu znajdują się jeszcze dwa parametry:

  • ssl — zapewnia, że komunikacja jest szyfrowana.
  • abortConnection — umożliwia utworzenie połączenia, nawet jeśli serwer jest niedostępny w danej chwili.

Jest kilka innych parametrów opcjonalnych, które możesz dołączyć do ciągu w celu skonfigurowania biblioteki klienta.

Tworzenie połączenia

Obiektem głównym połączenia w kliencie StackExchange.Redis jest klasa StackExchange.Redis.ConnectionMultiplexer. Ten obiekt tworzy abstrakcję procesu nawiązywania połączenia z serwerem Redis (lub grupą serwerów). Jest on zoptymalizowany pod kątem wydajnego zarządzania połączeniami i przeznaczony do uruchamiania, gdy będziesz potrzebować dostępu do pamięci podręcznej.

Tworzysz wystąpienie obiektu ConnectionMultiplexer przy użyciu statycznej metody ConnectionMultiplexer.Connect lub metody ConnectionMultiplexer.ConnectAsync, przekazując w każdym przypadku parametry połączenia lub obiekt ConfigurationOptions.

Oto prosty przykład:

using StackExchange.Redis;
...
var connectionString = "[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False";
var redisConnection = ConnectionMultiplexer.Connect(connectionString);

Gdy masz element ConnectionMultiplexer, istnieją trzy podstawowe elementy, które warto wykonać:

  • Uzyskać dostęp do bazy danych usługi Redis.
  • Korzystaj z funkcji wydawcy/subskrybenta usługi Redis, która znajduje się poza zakresem tego modułu.
  • Uzyskać dostęp do indywidualnego serwera na potrzeby konserwacji lub monitorowania.

Uzyskiwanie dostępu do bazy danych usługi Redis

Typ IDatabase reprezentuje bazę danych Redis. Możesz ją pobrać przy użyciu metody GetDatabase():

IDatabase db = redisConnection.GetDatabase();

Napiwek

Obiekt zwrócony z metody GetDatabase jest uproszczonym obiektem i nie musi być przechowywany. Tylko obiekt ConnectionMultiplexer musi mieć stale podtrzymywane połączenie.

Po utworzeniu obiektu IDatabase możesz wykonać metody służące do interakcji z pamięcią podręczną. Wszystkie metody mają wersje synchroniczne i asynchroniczne, które zwracają Task obiekty, aby były zgodne ze słowami async kluczowymi i .await

Poniżej przedstawiono przykład przechowywania klucza/wartości w pamięci podręcznej:

bool wasSet = db.StringSet("favorite:flavor", "i-love-rocky-road");

Metoda StringSet zwraca bool, co wskazuje, czy wartość została ustawiona (true), czy też nie (false). Można następnie pobrać wartość za pomocą metody StringGet:

string value = db.StringGet("favorite:flavor");
Console.WriteLine(value); // displays: ""i-love-rocky-road""

Pobieranie i ustawianie wartości binarnych

Przypomnij sobie, że klucze i wartości usługi Redis są bezpieczne binarnie. Te same metody mogą służyć do przechowywania danych binarnych. Istnieją operatory niejawnej konwersji do pracy z typami byte[], aby można było pracować z danymi w naturalny sposób:

byte[] key = ...;
byte[] value = ...;

db.StringSet(key, value);
byte[] key = ...;
byte[] value = db.StringGet(key);

StackExchange.Redis reprezentuje klucze przy użyciu typu RedisKey. Ta klasa ma niejawne konwersje do i z typów string i byte[], pozwalając, aby zarówno klucze tekstowe, jak i binarne mogły być bezproblemowo używane. Wartości są reprezentowane przez typ RedisValue . Podobnie jak w przypadku RedisKey, istnieją dostępne niejawne konwersje pozwalające na przekazanie string lub byte[].

Inne typowe operacje

Interfejs IDatabase zawiera kilka innych metod do pracy z pamięcią podręczną Redis Cache. Istnieją metody do pracy ze skrótami, listami, zestawami i uporządkowanymi zestawami.

Poniżej przedstawiono niektóre częściej spotykane metody, które działają z pojedynczymi kluczami. Aby zobaczyć pełną listę, możesz odczytać kod źródłowy interfejsu.

Metoda opis
CreateBatch Tworzy grupę operacji do wysłania na serwer jako pojedynczą jednostkę, ale niekoniecznie przetworzoną jako jednostkę.
CreateTransaction Tworzy grupę operacji, które mają być wysyłane do serwera jako pojedyncza jednostka i przetwarzane na serwerze jako pojedyncza jednostka.
KeyDelete Usuń parę klucz/wartość.
KeyExists Zwraca informacje, czy dany klucz istnieje w pamięci podręcznej.
KeyExpire Ustawia czas wygaśnięcia (TTL) klucza.
KeyRename Zmienia nazwę klucza.
KeyTimeToLive Zwraca czas wygaśnięcia klucza.
KeyType Zwraca ciąg reprezentujący typ wartości przechowywanej w kluczu. Różne typy, które można zwrócić, to: ciąg, lista, zestaw, zset i skrót.

Wykonywanie innych poleceń

Obiekt IDatabase ma metodę Execute i ExecuteAsync , która może służyć do przekazywania poleceń tekstowych do serwera Redis. Na przykład:

var result = db.Execute("ping");
Console.WriteLine(result.ToString()); // displays: "PONG"

Metody Execute i ExecuteAsync zwracają RedisResult obiekt, który jest posiadaczem danych zawierającym dwie właściwości:

  • Resp2Type zwraca wartość wskazującą string typ wyniku — STRING, INTEGERitp.
  • IsNull to wartość prawda/fałsz, aby wykryć, kiedy jest wynik null.

Następnie możesz użyć ToString() w RedisResult, aby pobrać rzeczywistą zwracaną wartość.

Możesz użyć Execute, aby wykonać dowolne obsługiwane polecenia — na przykład możemy pobrać wszystkich klientów połączonych z pamięcią podręczną („CLIENT LIST”):

var result = await db.ExecuteAsync("client", "list");
Console.WriteLine($"Type = {result.Resp2Type}\r\nResult = {result}");

Spowoduje to wyjście wszystkich połączonych klientów:

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

Przechowywanie bardziej złożonych wartości

Usługa Redis jest zorientowana na bezpieczne ciągi binarne, ale możesz buforować wykresy obiektów, serializując je do postaci tekstowej — zwykle XML lub JSON. Na przykład dla naszych statystyk mamy GameStats obiekt, który wygląda następująco:

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"))}";
    }
}

Moglibyśmy użyć biblioteki Newtonsoft.Json, aby przekształcić wystąpienie tego obiektu w ciąg:

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);

Moglibyśmy pobrać go i przekształcić z powrotem w obiekt przy użyciu odwrotnego procesu:

var result = db.StringGet("event:2019-local-game");
var stat = Newtonsoft.Json.JsonConvert.DeserializeObject<GameStat>(result.ToString());
Console.WriteLine(stat.Sport); // displays "Soccer"

Czyszczenie połączenia

Gdy połączenie nie jest już potrzebne, możesz elementy Dispose ConnectionMultiplexer. Spowoduje to zamknięcie wszystkich połączeń i zamknięcie komunikacji z serwerem.

redisConnection.Dispose();
redisConnection = null;