Ik kan eerlijk gezegd niet beslissen of dit een SO-vraag of een MSO-vraag is, maar:
Naar een ander systeem gaan is nooit sneller dan het opvragen van lokaal geheugen (zolang het is ingetoetst); simpel antwoord:we gebruiken beide! Dus we gebruiken:
- lokaal geheugen
- zie anders redis en update lokaal geheugen
- anders ophalen van bron, en redis en lokaal geheugen updaten
Dit veroorzaakt dan, zoals je zegt, een probleem met het ongeldig maken van de cache - hoewel dat eigenlijk niet kritiek is op de meeste plaatsen. Maar hiervoor - redis-gebeurtenissen (pub/sub) bieden een gemakkelijke manier om sleutels die veranderen naar alle knooppunten uit te zenden, zodat ze hun lokale kopie kunnen laten vallen - wat betekent:de volgende keer dat het nodig is, halen we de nieuwe kopie op van redis . Daarom zenden we de sleutelnamen uit die veranderen tegen de naam van een enkele gebeurteniskanaal.
Tools:redis op ubuntu-server; BookSleeve als redis-wikkel; protobuf-net en GZipStream (automatisch ingeschakeld / uitgeschakeld afhankelijk van de grootte) voor verpakkingsgegevens.
Dus:de redis pub/sub-gebeurtenissen worden gebruikt om de cache voor een bepaalde sleutel van één ongeldig te maken node (degene die weet dat de status is veranderd) onmiddellijk (vrijwel) naar alle knooppunten.
Met betrekking tot afzonderlijke processen (uit opmerkingen, "gebruikt u een soort gedeeld geheugenmodel voor meerdere afzonderlijke processen die gebruikmaken van dezelfde gegevens?"):nee, dat doen we niet. Elke web-tier box host slechts één proces (van een bepaalde tier), met multi-tenancy binnen dat, dus binnen hetzelfde proces kunnen we 70 sites hebben. Om legacy-redenen (d.w.z. "het werkt en hoeft niet gerepareerd te worden") gebruiken we voornamelijk de http-cache met de site-identiteit als onderdeel van de sleutel.
Voor de weinige massaal data-intensieve delen van het systeem hebben we mechanismen om op schijf te blijven, zodat het in-memory-model kan worden doorgegeven tussen opeenvolgende app-domeinen terwijl het web op natuurlijke wijze recycleert (of opnieuw wordt geïmplementeerd), maar dat is niet gerelateerd aan redis.
Hier is een gerelateerd voorbeeld dat de alleen brede smaak . toont hoe dit zou kunnen werken - start een aantal instanties van het volgende en typ vervolgens enkele sleutelnamen in:
static class Program
{
static void Main()
{
const string channelInvalidate = "cache/invalidate";
using(var pub = new RedisConnection("127.0.0.1"))
using(var sub = new RedisSubscriberConnection("127.0.0.1"))
{
pub.Open();
sub.Open();
sub.Subscribe(channelInvalidate, (channel, data) =>
{
string key = Encoding.UTF8.GetString(data);
Console.WriteLine("Invalidated {0}", key);
});
Console.WriteLine(
"Enter a key to invalidate, or an empty line to exit");
string line;
do
{
line = Console.ReadLine();
if(!string.IsNullOrEmpty(line))
{
pub.Publish(channelInvalidate, line);
}
} while (!string.IsNullOrEmpty(line));
}
}
}
Wat u zou moeten zien, is dat wanneer u een sleutelnaam typt, deze onmiddellijk wordt weergegeven in alle actieve instanties, die vervolgens hun lokale kopie van die sleutel zouden dumpen. Het is duidelijk dat bij echt gebruik de twee verbindingen ergens moeten worden geplaatst en open moeten worden gehouden, dus niet wees in using
verklaringen. We gebruiken hiervoor een bijna-een-singleton.