Sharding con IoC

2

Mi sono imbattuto in una situazione in cui ho bisogno di dividere un database (Oracle, ma ciò non è particolarmente importante).

L'essenza del problema è che ho scritto un sistema su larga scala in uno stile TDD abbastanza standard, con repository e servizi nascosti dietro le interfacce. L'iniezione delle dipendenze viene utilizzata per implementare versioni particolari dei servizi e degli archivi in fase di runtime, con questa funzionalità che consente di soddisfare i requisiti dei client (ad esempio, abbiamo migrato da MSSQL a Oracle in meno di una settimana, cosa che non sarebbe stata possibile se l'architettura non fosse stata correttamente disaccoppiato!).

Ora sorge il problema che ho bisogno di ritagliare una gran parte dei dati in un sistema di archiviazione separato, per motivi di prestazioni. La struttura del tavolo deve rimanere la stessa a causa dei limiti di tempo, e vorrei che la purezza dell'architettura rimanga la stessa, senza una sezione del sistema che abbia conoscenza del funzionamento interno di un altro. Il sistema dovrà essere commutato da un frammento all'altro in modo dinamico tramite un input dell'utente (l'input non è ancora stato finalizzato).

Quindi, i due modi in cui posso pensare di affrontare questo problema sono:

1 - Passa la stringa di connessione richiesta alla creazione di un repository. Questo non è l'ideale in quanto significa che il livello di servizio, o peggio, l'interfaccia utente, ha bisogno di sapere del sottotitolo sottostante. Ciò renderà il design molto inflessibile in futuro e richiederà che cose come il sit-in-front caching layer (un'implementazione della cache write-through sopra l'IService) siano aggiornamenti, quindi i loro metodi accettano una stringa di connessione come parametro, che sembra sbagliato .

2 - Creare una nuova sottosezione IConnectionProvider del sistema che estrae le informazioni di connessione per il repository. Questo sarebbe più ideale, poiché i repository rimarrebbero autonomi, ma non riesco a pensare a un buon modo per cambiare questa implementazione senza dover specificare l'interfaccia rilevante come parametro per ogni chiamata al metodo, che ritorna al livello di servizio che specifica quale connessione usare.

Qualcuno ha qualche esperienza con questo problema, o qualche opinione su un'implementazione preferibilmente a basso impiego ma ancora abbastanza pura in questa situazione?

    
posta Ed James 12.02.2012 - 19:23
fonte

1 risposta

1

Penso che dipenda dal modo in cui le entità che stai persistendo sono separate. Se sono accoppiati e ti stai affidando a join incrociati per portare in alto lo stato di lettura dell'array (+ proiezione) e poi deserializzarlo, probabilmente avrai un problema.

D'altra parte, se è possibile caricare un'entità o aggregare oggetti root + value dal proprio repository senza dover visualizzare un grafico completo di oggetti con contorni incrociati e avere coerenza in una transazione, allora c'è sicuramente il possibilità di frammentare nel repository.

Nel mio mondo, il repository è la cosa reale che implementa il sharding: è un "sacchetto di entità coerente per ID".

Detto questo; su cosa ti stai attaccando? Tipo di entità? Quindi, ad es. con Windsor, utilizza una implementazione di IHandlerSelector che analizza il tipo di repository (che significa tipo di entità richiesta) e sceglie l'istanza corretta a seconda che si tratti di un'entità "calda" o di una "fredda".

Allo stesso modo, per intervalli di chiavi o basati su dati / attributi di entità, potresti fare un selettore di gestori che guarda qualche cosa sull'entità.

Un'alternativa è iniziare a pubblicare un flusso di eventi dalle operazioni sulle entità e fare in modo che quegli eventi creino un modello di lettura che è già denormalizzato; evitando i problemi di join che potrebbero essere la causa principale dei problemi di scalabilità (questo è speculativo da parte mia in base all'esperienza).

    
risposta data 12.02.2012 - 20:39
fonte

Leggi altre domande sui tag