sql >> Databasteknik >  >> NoSQL >> Redis

Batchuppsättningsdata från Dictionary till Redis

"bara" är ett mycket relativt begrepp och är inte riktigt meningsfullt utan mer sammanhang, i synnerhet:hur stora är dessa nyttolaster?

Men för att klargöra några punkter som hjälper dig att undersöka:

  • det finns inget behov av att låsa en IDatabase såvida det inte är enbart för dina egna syften; SE.Redis sysslar med trådsäkerhet internt och är tänkt att användas av konkurrerande trådar
  • för närvarande kommer din tidpunkt för detta att inkludera all serialiseringskod (JsonConvert.SerializeObject ); detta kommer att läggas ihop, särskilt om dina föremål är stora; För att få ett anständigt mått rekommenderar jag starkt att du tar tid för serialisering och redis tider separat
  • batch.Execute() Metoden använder ett pipeline-API och väntar inte på svar mellan samtal, så:tiden du ser är inte den kumulativa effekten av latens; som bara lämnar lokal CPU (för serialisering), nätverksbandbredd och server-CPU; klientbiblioteksverktygen kan inte påverka någon av dessa saker
  • det finns ett StringSet överbelastning som accepterar ett KeyValuePair<RedisKey, RedisValue>[]; du kunde välj att använda detta istället för en batch, men den enda skillnaden här är att det är varadic MSET snarare än flera SET; hur som helst, du kommer att blockera anslutningen för andra uppringare så länge (eftersom syftet med batch är att göra kommandona sammanhängande)
  • det gör du inte faktiskt måste använda CreateBatch här, särskilt eftersom du låser databasen (men jag föreslår fortfarande att du inte behöver göra detta); syftet med CreateBatch är att göra en sekvens av kommandon sekventiell , men jag ser inte att du behöver detta här; du kan bara använda _database.StringSetAsync för varje kommando i tur och ordning, vilket också skulle göra har fördelen att du skulle köra serialisering parallellt med det föregående kommandot som skickas - det skulle tillåta dig att överlappa serialisering (CPU bunden) och redis ops (IO bunden) utan något arbete förutom att ta bort CreateBatch ringa upp; detta innebär också att du inte monopoliserar uppkopplingen från andra uppringare

Så; den första det jag skulle göra skulle vara att ta bort lite kod:

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

Det andra jag skulle göra skulle vara att tajma serialiseringen separat till redis-arbetet.

Det tredje jag skulle göra är att se om jag kan serialisera till en MemoryStream istället, helst en som jag kan återanvända - för att undvika string alocation och UTF-8-kodning:

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. Frågar med mangust och dadlar

  2. Hur man hanterar databaser och samlingar i MongoDB

  3. Azure Cache/DataCache-stil regioner i Redis

  4. Finns det något sätt att flushall på ett kluster så att alla nycklar från master och slavar raderas från db