Utforska klient-API:et för interaktion med Redis

Slutförd

Som tidigare nämnts är Redis en minnesintern NoSQL-databas som kan replikeras över flera servrar. Det används ofta som en cache, men kan användas som en formell databas eller till och med som meddelandekö.

Redis kan lagra olika datatyper och strukturer. Den stöder olika kommandon som du kan utfärda för att hämta cachelagrade data eller för att fråga efter information om själva cachen. De data du arbetar med lagras alltid som nyckel/värde-par.

Köra kommandon i Redis-cachen

Vanligtvis använder ett klientprogram ett klientbibliotek till att skapa begäranden och köra kommandon på en Redis-cache. Du kan hämta en lista med klientbibliotek direkt från Redis klientsida. StackExchange.Redis är en populär Redis-klient med höga prestanda för plattformen .NET. Paketet är tillgängligt via NuGet och du kan lägga till det i .NET-koden med hjälp av kommandoraden eller IDE.

Anslut till Redis-cachen med StackExchange.Redis

Kom ihåg att vi använder värdadressen, portnumret och en åtkomstnyckel för att ansluta till en Redis-server. Azure erbjuder också en anslutningssträng för vissa Redis-klienter, som paketera dessa data i en enda sträng.

Vad är en anslutningssträng?

En anslutningssträng är en enskild textrad som innehåller alla uppgifter som krävs för att ansluta och autentisera till en Redis-cache i Azure. Den ser ut ungefär så här (med fälten cache-name och password-here ifyllda med verkliga värden):

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

Dricks

Anslutningssträngen ska skyddas i ditt program. Om programmet finns på Azure kan du använda ett Azure Key Vault för att lagra värdet.

Du kan skicka strängen till StackExchange.Redis för att skapa en anslutning till servern.

Observera att det finns ytterligare två parametrar i slutet:

  • ssl: säkerställer att kommunikationen krypteras
  • abort Anslut ion: tillåter att en anslutning skapas även om servern inte är tillgänglig just då

Det finns flera andra valfria parametrar som du kan lägga till i strängen när du konfigurerar klientbiblioteket.

Skapa en anslutning

Det huvudsakliga anslutningsobjektet i StackExchange.Redis är klassen StackExchange.Redis.ConnectionMultiplexer. Det här objektet eliminerar processen för att ansluta till en Redis-server (eller en grupp med servrar). Det har optimerats för att effektivt hantera anslutningar och kan användas varje gång du behöver åtkomst till cachen.

Du skapar en ConnectionMultiplexer-instans med statisk ConnectionMultiplexer.Connect eller ConnectionMultiplexer.ConnectAsync-metoden och skickar antingen en anslutningssträng eller ett ConfigurationOptions-objekt.

Här är ett enkelt exempel:

using StackExchange.Redis;
...
var connectionString = "[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False";
var redisConnection = ConnectionMultiplexer.Connect(connectionString);
    // ^^^ store and re-use this!!!

När du har en ConnectionMultiplexerfinns det tre primära saker som du kanske vill göra:

  1. Få åtkomst till en Redis-databas (fokus för den här modulen).
  2. Använd utgivar-/nedsänkta funktioner i Redis (utanför omfånget för den här modulen).
  3. Få åtkomst till en enskild server för underhåll eller övervakning.

Få åtkomst till en Redis-databas

Redis-databasen representeras av IDatabase-typen. Du kan hämta en med GetDatabase()-metoden:

IDatabase db = redisConnection.GetDatabase();

Dricks

Objektet som returneras från GetDatabase är ett lättviktsobjekt och behöver inte lagras. Det är bara ConnectionMultiplexer som måste vara aktiv.

När du har ett IDatabase-objekt kan du köra metoder för att interagera med cacheminnet. Alla metoder har synkrona och asynkrona versioner, som returnerar Task objekt för att göra dem kompatibla med nyckelorden async och await .

Här är ett exempel på lagring av en nyckel/ett värde i cacheminnet:

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

StringSet-metoden returnerar en bool som visar ifall värdet har angetts (true) eller inte (false). Vi kan sedan hämta värdet med StringGet-metoden:

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

Hämta och ange binära värden

Kom ihåg att Redis-nycklar och värden är binärt säkra. Du kan använda samma metoder för att lagra binära data. Det finns implicita konverteringsoperatörer som använder byte[]-typer, så du kan arbeta med data naturligt:

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

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

Dricks

StackExchange.Redis representerar nycklar med RedisKey-typen. Den här klassen har implicita konverteringar till och från både string och byte[], vilket gör att både text och binära nycklar kan användas utan problem. Värden representeras av RedisValue-typen. Precis som med RedisKey, finns det implicita konverteringar på plats så att du kan skicka string eller byte[].

Andra vanliga åtgärder

IDatabase-gränssnittet innehåller flera andra metoder för att arbeta med Redis-cache. Det finns metoder för att arbeta med hashvärden, listor, uppsättningar och ordnade uppsättningar.

Här är några av de vanligaste åtgärderna som fungerar med enkla nycklar. du kan läsa källkoden för gränssnittet för att se den fullständiga listan.

Metod beskrivning
CreateBatch Skapar en åtgärdsgrupp som kommer att skickas till servern som en enda enhet, men inte nödvändigtvis behandlas som en enhet.
CreateTransaction Skapar en åtgärdsgrupp som kommer att skickas till servern som en enda enhet och behandlas på servern som en enda enhet.
KeyDelete Tar bort nyckeln/värdet.
KeyExists Returneras om den angivna nyckeln finns i cacheminnet.
KeyExpire Anger en tidsgräns för TTL-värdet (Time to live) för en nyckel.
KeyRename Byter namn på en nyckel.
KeyTimeToLive Returnerar TTL-värdet för en nyckel.
KeyType Returnerar en strängrepresentation av typen på det värde som lagras i nyckeln. De olika typer som kan returneras är: sträng, lista, uppsättning, zset och hash.

Köra andra kommandon

Objektet IDatabase har en Execute och-metod ExecuteAsync som kan användas för att skicka textkommandon till Redis-servern. Till exempel:

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

Metoderna Execute och ExecuteAsync returnerar ett RedisResult objekt, som är en datahållare som innehåller två egenskaper:

  • Type, som returnerar en string som anger typen av resultat – "STRING", "INTEGER" osv.
  • IsNull, ett sant/falskt värde för att identifiera när resultatet är null.

Du kan sedan använda ToString()RedisResult för att hämta det faktiska returvärdet.

Du kan använda Execute för att utföra alla kommandon som stöds. Vi kan till exempel hämta alla klienter som är anslutna till cachen ("KLIENTLISTA"):

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

Föregående kommandon matar ut alla anslutna klienter:

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

Lagra mer komplexa värden

Redis är inriktad på binära säkra strängar, men du kan cachelagra objektdiagram genom att serialisera dem till ett textformat. vanligtvis XML eller JSON. För vår statistik har vi till exempel ett GameStat objekt som ser ut så här:

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

Vi kan använda biblioteket Newtonsoft.Json till att omvandla en instans av det här objektet till en sträng:

var stat = new GameStat("Soccer", new DateTime(1950, 7, 16), "FIFA World Cup", 
                new[] { "Uruguay", "Brazil" },
                new[] { ("Uruguay", 2), ("Brazil", 1) });

string serializedValue = Newtonsoft.Json.JsonConvert.SerializeObject(stat);
bool added = db.StringSet("event:1950-world-cup", serializedValue);

Vi kan hämta den och omvandla den tillbaka till ett objekt genom en omvänd process:

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

Rensa anslutningen

När du är klar med Redis-anslutningen kan du ta bortConnectionMultiplexer. Det här kommandot stänger alla anslutningar och stänger av kommunikationen till servern:

redisConnection.Dispose();
redisConnection = null;

Nu ska vi skapa ett program och göra lite arbete med vår Redis-cache.

Som tidigare nämnts är Redis en minnesintern NoSQL-databas som kan replikeras över flera servrar. Det används ofta som en cache, men kan användas som en formell databas eller till och med meddelandekö.

Redis kan lagra olika datatyper och strukturer. Den stöder olika kommandon som du kan utfärda för att hämta cachelagrade data eller fråga efter information om själva cachen. De data du arbetar med lagras alltid som nyckel/värde-par.

Köra kommandon i Redis-cachen

Vanligtvis använder ett klientprogram ett klientbibliotek till att skapa begäranden och köra kommandon på en Redis-cache. Du kan hämta en lista med klientbibliotek direkt från Redis klientsida. En populär Redis-klient för Java Script är redis-paketet, som du kan lägga till i ett projekt med npm install redis.

Anslut till Redis-cachen med Redis-paketet

Du uppnår en interaktion med Redis-cache med klassen RedisClient. I de flesta fall är följande exempelkod det bästa sättet att skapa en RedisClient som ansluter till en Redis-cache i Azure:

const client = redis.createClient(
  port,  // the port number, 6380 by default
  hostname,  // <resourceName>.redis.cache.windows.net
  {
    password: accessKey,  // the primary or secondary access key
    tls: { servername: hostname }
  }
);

I de flesta fall bör du undvika att skapa flera RedisClient. En enda instans av RedisClient kan skickas runt och användas överallt i koden där Redis krävs.

Arbeta med en Redis-databas

Redis-kommandon representeras som metoder på RedisClient med namnen som själva kommandona. Här är ett exempel på att lagra ett nytt värde i cacheminnet:

client.set("myKey", "myValue"); // executes "set myKey myValue" on the cache

Alla kommandometoder i RedisClient är asynkrona och har stöd för ett valfritt återanropsargument som ger resultatet. Paketet redis stöder inte Promises (och därmedawaitasync/eller länkning med .then()) direkt. Det enklaste sättet att använda async/await eller .then() med RedisClient är att lägga till stöd för Promise (löfte) för hela klienten på en gång med bluebird-paketets promisifyAll-funktion:

var redis = require("redis");
var Promise = require("bluebird");

Promise.promsifyAll(redis);

Funktionen promisifyAll lägger till XXXAsync versioner av alla kommandometoder i RedisClient instanser, så att du kan använda asynkrona metoder som i följande exempel:

var result = await client.setAsync("myKey", "myValue");

Köra kommandon dynamiskt

Du kan skicka kommandon dynamiskt med hjälp sendCommand() av (eller sendCommandAsync() med bluebird) för att skicka valfri sträng som ett kommando till cachen. Din app kan till exempel visa en uppmaning om att skicka kommandon direkt till cachen, eller så kan Redis introducera nya kommandon som redis paketet inte stöder. Kommandoargument måste skickas som en matris.

// Add a key/value pair
var result = await client.sendCommandAsync("set", ["myKey", "myValue"]);

Rensa anslutningen

När du är klar med Redis-anslutningen bör du stänga den med quit() (eller quitAsync() när du använder bluebird):

await client.quitAsync();

Nu ska vi skapa ett program och göra lite arbete med vår Redis-cache.