Come dovrei interrogare il DB per una chiave specifica senza interrogare ogni volta che viene chiamata la funzione?

3

Abbiamo un grande progetto legacy basato su Java, la disponibilità di alcune funzionalità in tutta l'applicazione è determinata dal valore corrispondente in una tabella "feature_enabled" in un database SQL. Molto simile a Windows abilita le funzionalità basate sui valori del Registro di sistema.

Ultimamente, abbiamo lavorato per ridurre in modo significativo il numero di query SQL eseguite in una parte specifica dell'app. Quindi abbiamo scritto una classe di memorizzazione nella cache che chiama la query una volta e memorizza i risultati nella cache. Sfortunatamente, non possiamo riscrivere tutte le funzioni in quanto altre parti dell'app dipendono da esso. Quindi, quando il nostro team chiama la funzione (che esegue la query SQL), forniamo l'intera classe con la proprietà della tabella in cache. La funzione quindi controlla semplicemente se la proprietà è stata impostata. In tal caso, utilizza i dati da lì, altrimenti esegue una nuova query.

Il problema è che vorremmo aggiungere questa tecnica di caching come una funzionalità che può essere abilitata come gli altri. Interrogare il DB ogni volta che il db memorizzato nella cache viene chiamato per verificare se la funzionalità è abilitata, annulla qualsiasi query che stiamo salvando. Quindi la mia domanda è che cosa è un buon modello di design per realizzare questo?

    
posta DemCodeLines 08.08.2016 - 05:06
fonte

3 risposte

2

Devi essere in grado di attivare o disattivare arbitrariamente la funzionalità "Memorizzazione nella cache abilitata" mentre l'app è in esecuzione?

Se hai bisogno di cambiarlo durante il runtime:

Ecco alcune possibilità:

  • Crea una tabella a riga singola separata che contiene solo questo valore. Ciò ridurrà al minimo il costo della query. Nel mondo reale, il vantaggio che ottieni da questo potrebbe non essere nemmeno misurabile, specialmente se la tabella di configurazione contiene solo poche (dozzine) righe.
  • Metti questo flag in un file di configurazione sul file system. Molti problemi qui. Dovrai continuamente guardare il file per le modifiche, quali richiede tempo e aggiunge complessità Inoltre, c'è il problema di fare sicuro che il file di configurazione sia distribuito correttamente ovunque.
  • Costruire un modo per l'editor di configurazione per dire all'app in esecuzione che il flag di caching è cambiato. Questo probabilmente ha senso solo se l'editor e l'app principale fanno parte dello stesso processo. Se lo sono, basta aggiungere un metodo NotifyCachingSettingChanged alla tua classe di caching.

Se non lo fai:

Fai in modo che la funzione controlli la sua cache memorizzata per vedere se la funzione è abilitata. In caso affermativo, restituire la tabella memorizzata. In caso contrario, andare a interrogare il DB per la tabella. Quando devi cambiare il flag di caching, cambialo nel DB e riavvia il processo dell'app per svuotare la cache e forzare una ricarica.

    
risposta data 08.08.2016 - 05:43
fonte
1

Quando ti trovi in una situazione di sondaggio (come se avessi voglia di sapere quando qualcosa cambia) è il momento di rivolgersi agli eventi. Quali sono gli eventi? Beh, nel cuore sta sondando, fatto meglio.

Diciamo che hai dieci cose che entrano nel database che vorresti sapere nel momento in cui sono cambiate. Puoi colpire il database dieci volte al minuto. Oppure puoi semplicemente eseguire una query al minuto.

Ecco come funzionano gli interrupt nell'architettura del tuo computer. Un registro con molti bit viene controllato in un ciclo stretto ogni ciclo di clock. Se qualche bit è diverso da zero, qualcosa sta interrompendo il normale flusso del programma e attende di essere risolto. Quale bit ti dice cosa stai aspettando.

Fatto a livello di database questo schema potrebbe essere fatto con una stringa. Considerando il sovraccarico della query, una stringa di dimensioni ragionevoli dovrebbe avere prestazioni pari a quelle di un int. Quindi mantieni una tabella con timestamp di eventi con nome. Funziona così:

  • Interrogare la tabella per eventi più recenti rispetto all'ultimo controllo.
  • Elimina eventi più vecchi dell'ultimo controllo.
  • Gestire gli eventi (interrogare qualsiasi cosa debba essere richiesta)

L'ordine in cui desideri inserirla ha più a che fare con il debug che con le prestazioni.

Avrai bisogno di un modo per creare eventi nella tabella degli eventi. Questo potrebbe essere fatto nel db stesso o può essere fatto in qualsiasi aggiornamento del db. Quando aggiorni la tabella Foo puoi anche rilasciare una stringa Foo data / ora nella tabella degli eventi. Quando elimini la voce Barra dalla tabella Baz, puoi rilasciare una stringa Baz-Bar con data e ora nella tabella degli eventi. È gloriosamente asincrono e scala molto bene. 10, 100, 10000 tipi di eventi caricano il db nello stesso modo.

Ora sai quando un valore memorizzato nella cache non è aggiornato, quindi puoi aggiornarlo tempestivamente.

Se non sei l'unico a guardare questi eventi, la cancellazione diventa un po 'complicata. È possibile elaborare uno schema per registrare gli osservatori degli eventi e cancellarli solo quando tutti li hanno consumati, ma questo è fragile. Un osservatore va giù e il DB si sta riempiendo. Meglio definire una finestra temporale in cui gli eventi vivranno e cancellare quelli che hanno lasciato la finestra.

Ovviamente tutto ciò potrebbe essere evitato se si riuscisse a trovare un modo per utilizzare un'alternativa al DB come un sistema di messaggistica. Non fare errori, questo è un hack . È un attacco molto più efficace del polling di tutto individualmente, ma è ancora un hack .

    
risposta data 08.08.2016 - 06:05
fonte
1

Un modo completamente diverso per risolvere il problema del polling è quello di avvolgere il DB. Il wrapper espone la stessa interfaccia del DB. Fai parlare tutto con il wrapper DB. Il wrapper parla al DB dicendo qualsiasi cosa sia stata detta.

Potresti persino usare uno sniffer per il traffico per questo. In questo modo nulla deve essere riconfigurato. Trova solo un modo per inviarlo come streaming.

Il vantaggio qui è ora che il DB o i processi di aggiornamento devono sapere quali valori sono legati agli eventi. Fa solo il wrapper.

Ora il wrapper può inviare eventi agli ascoltatori registrati. Falla riposare e l'ascoltatore può trovarsi su qualsiasi scatola.

Potresti avere il filtro del wrapper verso il basso proprio a ciò che gli utenti si preoccupano di mantenere basso il traffico, ma per assicurarsi che questo non rallenti il DB se ci sono molti osservatori potresti voler dedicare una casella per un feed non filtrato.

Questo è più vicino al modo in cui le persone con grandi quantità di dati risolvono questo problema. A seconda delle tue reali esigenze, considera questo approccio.

    
risposta data 08.08.2016 - 19:54
fonte

Leggi altre domande sui tag