sql >> Database teknologi >  >> NoSQL >> Redis

Batchsæt data fra ordbog til Redis

"bare" er et meget relativt begreb, og det giver ikke rigtig mening uden mere kontekst, især:hvor store er disse nyttelaster?

dog for at præcisere et par punkter for at hjælpe dig med at undersøge:

  • der er ingen grund til at låse en IDatabase medmindre det udelukkende er til dine egne formål; SE.Redis beskæftiger sig med gevindsikkerhed internt og er beregnet til at blive brugt af konkurrerende gevind
  • i øjeblikket vil din timing af dette inkludere al serialiseringskoden (JsonConvert.SerializeObject ); dette vil tilføje op, især hvis dine genstande er store; For at få et anstændigt mål, foreslår jeg kraftigt, at du tider serialiserings- og genoptagelsestiderne separat
  • batch.Execute() metoden bruger en pipeline API og venter ikke på svar mellem opkald, så:tidspunktet du ser er ikke den kumulative effekt af latens; der kun efterlader lokal CPU (til serialisering), netværksbåndbredde og server-CPU; klientbiblioteksværktøjerne kan ikke påvirke nogen af ​​disse ting
  • der er et StringSet overbelastning, der accepterer et KeyValuePair<RedisKey, RedisValue>[]; du kunne vælge at bruge dette i stedet for en batch, men den eneste forskel her er, at det er varadic MSET i stedet for flere SET; uanset hvad, vil du blokere forbindelsen for andre opkaldere i varigheden (da formålet med batch er at gøre kommandoerne sammenhængende)
  • det gør du ikke faktisk skal bruge CreateBatch her, især da du låser databasen (men jeg foreslår stadig, at du ikke behøver at gøre dette); formålet med CreateBatch er at lave en sekvens af kommandoer sekventiel , men jeg kan ikke se, at du har brug for dette her; du kunne bare bruge _database.StringSetAsync for hver kommando efter tur, hvilket også ville har den fordel, at du vil køre serialisering parallelt med den forrige kommando, der sendes - den ville tillade dig at overlappe serialisering (CPU bundet) og redis ops (IO bundet) uden noget arbejde bortset fra at slette CreateBatch opkald; dette vil også betyde, at du ikke monopoliserer forbindelsen fra andre opkaldere

Så; den første ting, jeg ville gøre, ville være at fjerne noget kode:

private static StackExchange.Redis.IDatabase _database;
static JsonSerializerSettings _redisJsonSettings = new JsonSerializerSettings {
    ContractResolver = new SerializeAllContractResolver(),
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore };

public void SetAll<T>(Dictionary<string, T> data, int cacheTime)
{
    TimeSpan expiration = new TimeSpan(0, cacheTime, 0);
    var list = new List<Task<bool>>();
    foreach (var item in data)
    {
        string serializedObject = JsonConvert.SerializeObject(
            item.Value, Formatting.Indented, _redisJsonSettings);

        list.Add(_database.StringSetAsync(item.Key, serializedObject, expiration));
    }
    Task.WhenAll(list.ToArray());
}

Den anden ting, jeg ville gøre, ville være at time serialiseringen separat til redis-arbejdet.

Den tredje ting, jeg ville gøre, ville være at se, om jeg kan serialisere til en MemoryStream i stedet, ideelt set en, som jeg kan genbruge - for at undgå string alocation og UTF-8 encode:

using(var ms = new MemoryStream())
{
    foreach (var item in data)
    {
        ms.Position = 0;
        ms.SetLength(0); // erase existing data
        JsonConvert.SerializeObject(ms,
            item.Value, Formatting.Indented, _redisJsonSettings);

        list.Add(_database.StringSetAsync(item.Key, ms.ToArray(), expiration));
    }
}


  1. Kloning af en MongoDB-instans eller replikasæt

  2. Hvordan forespørger jeg efter forskellige værdier i Mongoose?

  3. grupper efter forespørgsler om meteorindsamling

  4. Hvad er Mongoose (Nodejs) pluraliseringsregler?