Onestamente non riesco a decidere se questa è una domanda SO o una domanda MSO, ma:
Passare a un altro sistema è mai più veloce dell'interrogazione della memoria locale (purché sia digitata); risposta semplice:usiamo entrambi! Quindi usiamo:
- memoria locale
- else controlla redis e aggiorna la memoria locale
- altrimenti recupera dal sorgente e aggiorna redis e memoria locale
Questo quindi, come dici tu, causa un problema di invalidamento della cache, anche se in realtà non è critico nella maggior parte dei posti. Ma per questo - gli eventi redis (pub/sub) consentono un modo semplice di trasmettere le chiavi che stanno cambiando a tutti i nodi, in modo che possano eliminare la loro copia locale - il che significa:la prossima volta che sarà necessario prenderemo la nuova copia da redis . Quindi trasmettiamo i nomi delle chiavi che stanno cambiando rispetto a un singolo nome di canale di eventi.
Strumenti:redis sul server Ubuntu; BookSleeve come involucro redis; protobuf-net e GZipStream (abilitati/disabilitati automaticamente a seconda delle dimensioni) per il confezionamento dei dati.
Quindi:gli eventi redis pub/sub vengono utilizzati per invalidare la cache per una determinata chiave da uno nodo (quello che sa che lo stato è cambiato) immediatamente (praticamente) a tutti nodi.
Per quanto riguarda i processi distinti (dai commenti, "usate un qualsiasi tipo di modello di memoria condivisa per più processi distinti che alimentano gli stessi dati?"):no, non lo facciamo. Ciascuna casella di livello Web ospita in realtà solo un processo (di un determinato livello), con multi-tenancy all'interno quello, quindi all'interno dello stesso processo potremmo avere 70 siti. Per motivi legacy (ad es. "funziona e non ha bisogno di essere riparato") utilizziamo principalmente la cache http con l'identità del sito come parte della chiave.
Per le poche parti del sistema ad alta intensità di dati, abbiamo meccanismi per persistere su disco in modo che il modello in memoria possa essere passato tra domini app successivi mentre il Web si ricicla naturalmente (o viene ridistribuito), ma questo è non correlato a redis.
Ecco un esempio correlato che mostra il solo gusto ampio di come potrebbe funzionare:avvia un certo numero di istanze di quanto segue, quindi digita alcuni nomi di chiavi 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));
}
}
}
Quello che dovresti vedere è che quando digiti un nome-chiave, viene mostrato immediatamente in tutte le istanze in esecuzione, che quindi scaricherebbero la loro copia locale di quella chiave. Ovviamente nell'uso reale le due connessioni dovrebbero essere messe da qualche parte e mantenute aperte, quindi non essere in using
dichiarazioni. Usiamo quasi un singleton per questo.