sql >> Database >  >> NoSQL >> Redis

Batch set data van Dictionary naar Redis

"gewoon" is een zeer relatieve term en is niet echt logisch zonder meer context, met name:hoe groot zijn deze payloads?

echter, om een ​​paar punten te verduidelijken om u te helpen onderzoeken:

  • het is niet nodig om een ​​IDatabase te vergrendelen tenzij dat puur voor uw eigen doeleinden is; SE.Redis houdt zich intern bezig met threadveiligheid en is bedoeld om te worden gebruikt door concurrerende threads
  • op dit moment omvat uw timing hiervan alle serialisatiecode (JsonConvert.SerializeObject ); dit zal oplopen, vooral als je objecten groot zijn; om een ​​fatsoenlijke maat te krijgen, raad ik je ten zeerste aan om de serialisatie- en redis-tijden afzonderlijk te timen
  • de batch.Execute() methode gebruikt een pijplijn-API en wacht niet op reacties tussen aanroepen, dus:de tijd die u ziet is niet het cumulatieve effect van latentie; dat laat alleen de lokale CPU (voor serialisatie), netwerkbandbreedte en server-CPU over; de tools van de clientbibliotheek kunnen geen van deze dingen beïnvloeden
  • er is een StringSet overbelasting die een KeyValuePair<RedisKey, RedisValue>[] accepteert; je zou kies ervoor om dit te gebruiken in plaats van een batch, maar het enige verschil hier is dat het de varadic MSET is in plaats van meerdere SET; hoe dan ook, je blokkeert de verbinding voor andere bellers voor de duur (aangezien het doel van batch is om de opdrachten aaneengesloten te maken)
  • je eigenlijk niet moet CreateBatch . gebruiken hier, vooral omdat je de database vergrendelt (maar ik stel toch voor dat je dit niet hoeft te doen); het doel van CreateBatch is om een ​​reeks opdrachten opeenvolgend . te maken , maar ik zie niet dat je dit hier nodig hebt; je zou gewoon _database.StringSetAsync . kunnen gebruiken voor elk commando om de beurt, wat ook hebben het voordeel dat u serialisatie parallel aan . zou uitvoeren de vorige opdracht wordt verzonden - het zou u toestaan ​​om serialisatie (CPU-gebonden) en redis ops (IO-gebonden) te overlappen zonder enig werk, behalve om de CreateBatch te verwijderen telefoongesprek; dit betekent ook dat u de verbinding van andere bellers niet monopoliseert

Dus; de eerste wat ik zou doen is verwijderen wat code:

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

Het tweede wat ik zou doen zou zijn om de serialisatie apart van het redis-werk te timen.

Het derde wat ik zou doen is kijken of ik kan serialiseren naar een MemoryStream in plaats daarvan idealiter een die ik kan hergebruiken - om de string . te vermijden alocatie en UTF-8-codering:

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. nodejs mongodb object-ID naar string

  2. SCUMM:de op agenten gebaseerde databasebewakingsinfrastructuur in ClusterControl

  3. Een subdocument bijwerken dat is opgenomen in een array in een MongoDB-document

  4. Hoe de featureCompatibilityVersion in MongoDB in te stellen