[Design pattern] Applicatie data synchronisatie

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 22-07-2024
Beste mensen, ik overpijns een probleem waarvan ik eigenlijk zelf niet helemaal weet of het een probleem is.

Ik heb een modulaire applicatie (taal maakt even niet uit) en die haalt gegevens uit een relationele database.
Nu maakt hij van de records uit de DB objecten. Elk object bevat de waarden die eigenlijk in 95% van de gevallen overeenkomen met de kolommen in de DB.

Nu zou het kunnen dat module 1 een record uit die DB haalt, en vervolgens module 2 hetzelfde record.

Omdat beide modules het record kunnen aanpassen zou het kunnen dat je twee schermpjes open hebt op je scherm, en je op schermpje 1 op 'save' drukt, en je veranderde waarden naar de DB schrijft.

Nu wil ik dan eigenlijk zorgen dat schermpje twee ook automagisch bijgewerkt wordt.

Ik had zelf het volgende bedacht:

elk 'object' dat gemaakt wordt uit een record (met PK) uit de DB wordt in een soort van collection gezet, en wanneer een ander schermpje hetzelfde object ophaalt uit de DB wordt er in de collectie gespit, wordt het record uit de collection wordt aangepast aan de laatste 'waarheid' en dan teruggegeven.

In dit geval is het dus zo dat beide schermpjes hetzelfde object weergeven. Ik kan dan dmv wat logica (events etc.) zorgen dat schermpje 2 wordt ververst als ik op het object een 'save' aanroep.

Echter heeft het een nadeel, namelijk dat ik een enorme collectie ga bijhouden waarin alle instanties staan die ik ooit uit de DB heb opgehaald.

Natuurlijk kan ik ook gaan zorgen dat ik wanneer ik geen referenties meer heb naar een record ik die uit die collectie haal, maar dit is allemaal veel werk.


Bijkomend is er een probleem dat andere processen records kunnen aanpassen. Dit heb ik opgelost door een timestamp toe te voegen, en het update statement een "where timestampCol = timestampFromObj" mee te geven.


Zijn er nog andere mogelijkheden om dit te realiseren? Ik kan me niet voorstellen dat ik de eerste ben die hiermee rondloopt.

This message was sent on 100% recyclable electrons.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Gewoon elke x seconden pollen (of websockets als je dat liever doet) en het record opnieuw opvragen en daarbij vergelijken met de originele waarde is geen optie? Waarom zou je instanties bij moeten houden? Dat is toch helemaal niet interessant?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 22-07-2024
NMe schreef op zondag 30 juni 2013 @ 13:27:
Gewoon elke x seconden pollen (of websockets als je dat liever doet) en het record opnieuw opvragen en daarbij vergelijken met de originele waarde is gewoon optie? Waarom zou je instanties bij moeten houden? Dat is toch helemaal niet interessant?
Als je gaat pollen ga je wel elke x seconden de DB in en dat wil ik eigenlijk niet zo vaak doen...

This message was sent on 100% recyclable electrons.


Acties:
  • 0 Henk 'm!

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Daarom zegt NMe ook websockets, zie bijvoorbeeld http://signalr.net/

Oops! Google Chrome could not find www.rijks%20museum.nl


Acties:
  • 0 Henk 'm!

  • leuk_he
  • Registratie: Augustus 2000
  • Laatst online: 15-07 15:35

leuk_he

1. Controleer de kabel!

pollen werkt alleen als load geen issue is. Anders levert het een hoge data-load op.

Ik ken hiervaan 2 implementaties. bij de ene was er een synchonisatie server gebouwd, die soort van abonnementen bijhield van degene die data opvroeg. Nee, dat was niet simpel, maar wel schaalbaar.

de andere oplossing die ik ken is dat zodra 1 client data modificeert er een broadcast gaat naar alle andere cleints om hun data te refreshen. Nadeel is dat dat alleen werkt als er niet teveel clients tegelijkertijd kunnen draaien. De load neemt anders wel heel snel toe.

Websockets impliceert dat je een soort van synchornisatie server bouwt die de sockets aanstuurt.

Need more data. We want your specs. Ik ben ook maar dom. anders: forum, ff reggen, ff topic maken
En als je een oplossing hebt gevonden laat het ook ujb ff in dit topic horen.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

leuk_he schreef op zondag 30 juni 2013 @ 13:44:
Websockets impliceert dat je een soort van synchornisatie server bouwt die de sockets aanstuurt.
Je doet nu alsof het heel ingewikkeld is maar met NodeJS is het een paar regels code. Daarbij moet je nog steeds om de zoveel tijd de DB queryen maar als dát al een probleem is heb je een groter issue, want dan kan wat de TS wil domweg niet. Als je niet kan detecteren of iets gewijzigd is dan kun je niet detecteren dát iets gewijzigd is. 8)7

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • phYzar
  • Registratie: November 2001
  • Laatst online: 11:29
Misschien is dit een idee:
- in je db een tabel waarin je bij elke save een record zet met objecttype (tabelnaam) + primary key + timestamp.
- in je client check je of er sinds je laatste check objecten in de lijst staan die jij open hebt.
- zo ja, dan zijn ze dirty en reload je ze.
- als je ook locking wilt kun je voor je save een extra unique threadid/clientid zette in je db en dan checken of jouw id daar staat voor je de save doet.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Dat verandert niets aan het feit dat je nog steeds in je database moet checken en per check een query moet doen. Of je dat met een timestamp controleert of door de waardes één voor één naast elkaar te leggen doet niet af aan het feit dat er regelmatig een query nodig is.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

NMe schreef op zondag 30 juni 2013 @ 15:34:
Dat verandert niets aan het feit dat je nog steeds in je database moet checken en per check een query moet doen. Of je dat met een timestamp controleert of door de waardes één voor één naast elkaar te leggen doet niet af aan het feit dat er regelmatig een query nodig is.
De states zouden tijdelijke data zijn, immers is zo een verandering bij een volgend request geen issue meer want dan wordt de data weer 'vers' op gehaald. Dan zou je die save states toch in bijv. memcached op kunnen slaan?

Acties:
  • 0 Henk 'm!

  • phYzar
  • Registratie: November 2001
  • Laatst online: 11:29
Als je met meerdere clients (/processen) draait en je wilt continu op de hoogte zijn van elkaars wijzigingen, dan zul je toch ergens een gedeelde context moeten hebben. De database is toch wel een handige plek hiervoor aangezien dat nu een al bestaande gemene deler is. Alleen wanneer je je case beperkt tot 1 machine met meerdere apps of zelfs 1 applicatie met meerdere threads kun je je context verplaatsen naar iets meer lokaals wat misschien wat goedkoper is qua performance.

Acties:
  • 0 Henk 'm!

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 22-07-2024
Het punt zit hem niet zozeer in het feit dat je meerdere clients heb die elk hun eigen connectie naar de DB hebben en geen weet hebben van elkaar.
Dit is een bijkomend ding (zie TS) en is opgelost met een timestamp. het neveneffect dat je dan niet altijd kan saven neem ik voor lief omdat iemand anders voor jou eerst gesaved heeft (Zeg maar, als subversion, je kan niet committen als je niet zelf de latest hebt)

Echter gaat het bij mij vooral om wanneer je binnen 1 applicatie (en nee beste mensen ik heb het woord 'web' nooit genoemd) meerdere keren dezelfde data uit de DB gaat halen door verschillende stukjes code.

Die beide stukjes code kan ik via dezelfde database handler laten lopen, en zodoende ik (in de meeste gevallen) gewoon het record dat je opgehaald hebt tegen een lijst aanhouden om te zorgen dat ik geen twee instanties van hetzelfde object hebt die verwijzen naar hetzelfde DB record.

Als ik in de DB 1 record heb, wil ik dus ook in mijn code 1 object hebben. Dat meerdere stukjes code in mijn applicatie dat object gebruiken vind ik prima. Ik kan dan dmv events een trigger geven naar alle schermen e.d. die dat object gebruiken.

@NMe, het is ook niet dat ik nooit in de database wil kijken, maar door te pollen ga ik elke xx seconden kijken. Dat lijkt me wat overkill. Zeker als het om wat grote aantallen gaat (een lijstje dat ik laat zien) of om een tabel waar gewoon lomp veel records in zitten.
Ik wil dus een systeem waarbij de client niet actief bezig is om te kijken of er updates zijn, maar waarbij, wanneer de applicatie om wat voor reden dan ook gaat kijken in de DB en er is iets veranderd, dat alle stukjes code die dat record gebruiken ook automatisch geupdate worden.

This message was sent on 100% recyclable electrons.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

BasieP schreef op zondag 30 juni 2013 @ 16:24:
@NMe, het is ook niet dat ik nooit in de database wil kijken, maar door te pollen ga ik elke xx seconden kijken. Dat lijkt me wat overkill. Zeker als het om wat grote aantallen gaat (een lijstje dat ik laat zien) of om een tabel waar gewoon lomp veel records in zitten.
Als jij gewoon via je PK een record ophaalt heb je alle voordelen van een index. Verder hoef je alleen maar records op te halen die je daadwerkelijk aan het bewerken bent. De enige andere alternatieven die je hebt zijn row (of table) level locking of een of ander omslachtig merge-systeem als de wijzigingen niet mutually exclusive zijn...

Je kan niet zien of iets gewijzigd is zonder te kijken of iets gewijzigd is.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • phYzar
  • Registratie: November 2001
  • Laatst online: 11:29
Je kunt het in het geheugen bijhouden, maar dan ben je weer terug bij de in de TS voorgestelde lijst van objecten. Dit zou ook eventueel een lijst per class kunnen zijn, en je checkt bij instantiëren of je een db-select moet doen of de bestaande instantie kan doorgeven. Dan kom je ook weer terecht bij de in de TS genoemde issues, inclusief inderdaad leuke issues met 'pending changes' wanneer 1 iemand in het geheugen een ongesavede change heeft staan en iemand anders een refresh doet vanuit de db.

Is zo'n collectie echt zo enorm dat het niet wenselijk is? Hoeveel geheugengebruik zou dit geven? En over een jaar? Als de boel niet al te hard groeit en je kunt verwachten in een bepaalde tijdsperiode altijd ongeveer evenveel objecten aan te raken gooi je gewoon alles uit je lijst wat ouder is dan x minuten, en wanneer iemand er toch gebruik van wil maken mag hij een reload doen als reactie op het wegtieft-event :P

Acties:
  • 0 Henk 'm!

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 22-07-2024
phYzar, dat vind ik wel een goed plan. Dat ik voordat ik het afserveer wegens geheugenproblemen ik het eerst eens ga uitrekenen. Wellicht valt het wel mee. Zeker als ik ook goed dingen er weer uit ga halen.

Ik had al een opschoon actie bedacht (soort garbage collection, waarbij de oudste objecten opgeruimd worden) maar daarmee maak ik het een halfbakken oplossing. Hij doet het dan 'meestal' :P

Maar wellicht valt het geheugengebruik wel reuze mee.

This message was sent on 100% recyclable electrons.


Acties:
  • 0 Henk 'm!

  • Hoppie
  • Registratie: Februari 2001
  • Niet online
Het topic begint met [design pattern], maar ik hoor niemand het observer pattern noemen?
Als je het opgehaalde record een observable maakt, dan kunnen alle geregistreerde observers eenvoudig worden geïnformeerd van wijzigingen.

Aangezien de topic starter aangeeft dat meerdere modules hetzelfde record kunnen oproepen, lijkt het me een goed idee om tussen de modules en het database object een soort cache object toe te voegen dat opgevraagde records cached als observable objecten. Iedere module vraagt dan hetzelfde object op bij het cache object. Dat object geeft dan het gevraagde object terug en registreert het vragende object als observer.
Bij wijzigingen op het gecachede object, kan het cache object de andere observers de wijziging melden. Als dan het database object ook als observer geregistreerd is, kan dat na een wijziging het record in de database bijwerken....

Oh ja, als alle observers zich hebben afgemeld, kan het gecachede object verwijderd worden.

[ Voor 5% gewijzigd door Hoppie op 30-06-2013 22:34 . Reden: typo en extra opmerking ]


Acties:
  • 0 Henk 'm!

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 22-07-2024
tnx hoppie, zoiets heb ik nu dus eigenlijk al gebouwd, alleen dit is wel een nette uitleg. Bovendien kan ik nog wel iets verbeteren zie ik :)

This message was sent on 100% recyclable electrons.


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
BasieP schreef op zondag 30 juni 2013 @ 13:24:
Echter heeft het een nadeel, namelijk dat ik een enorme collectie ga bijhouden waarin alle instanties staan die ik ooit uit de DB heb opgehaald.
Je houdt natuurlijk gewoon bij welke er open zijn, en slaat ze op in een hashmap/cache. Een technologie zoals JPA doet dit al. Als je hetzelfde id opvraagt, krijg je gegarandeerd weer hetzelfde in-memory object terug (mits oude niet gedetached en nog bestaat). In een garbage collected taal kan de garbage collector het bijhouden voor je doen, in een taal als c++ kan dit met weak_ptr.
BasieP schreef op zondag 30 juni 2013 @ 16:24:
Het punt zit hem niet zozeer in het feit dat je meerdere clients heb die elk hun eigen connectie naar de DB hebben en geen weet hebben van elkaar.
Dit is een bijkomend ding (zie TS) en is opgelost met een timestamp. het neveneffect dat je dan niet altijd kan saven neem ik voor lief omdat iemand anders voor jou eerst gesaved heeft (Zeg maar, als subversion, je kan niet committen als je niet zelf de latest hebt)
Sommige databases hebben zelfs altijd al een timestamp hiervoor, en doen ook aan notificaties. Zie bijvoorbeeld http://guide.couchdb.org/draft/notifications.html
NMe schreef op zondag 30 juni 2013 @ 16:40:
Je kan niet zien of iets gewijzigd is zonder te kijken of iets gewijzigd is.
Met push kun je wel weten dat iets gewijzigd is zonder zelf steeds te moeten gaan kijken. Ik zie liever push dan poll. Socket.IO (normaal draaiend op Node.js) is al voor veel talen beschikbaar, net als soortgelijke zaken zoals SignalR (.NET) of Atmosphere (Java). Ik trek het expres even door naar webapplicaties, want wie maakt er voor database-achtige zaken nu nog een desktopapplicatie? ;)
phYzar schreef op zondag 30 juni 2013 @ 16:05:
Als je met meerdere clients (/processen) draait en je wilt continu op de hoogte zijn van elkaars wijzigingen, dan zul je toch ergens een gedeelde context moeten hebben. De database is toch wel een handige plek hiervoor aangezien dat nu een al bestaande gemene deler is.
Hangt er een beetje vanaf of je database aan notificaties doet natuurlijk, en/of polling een optie is. Notificaties kunnen ook via een aparte server lopen, of zelfs via meerdere aparte servers. Atmosphere (Java) bijvoorbeeld gebruikt Redis voor synchronisatie als je meer dan 1 server nodig hebt. (Afgevallen techniek voor ons omdat Socket.IO als voordeel had dat er meerdere clients zijn dan alleen javascript.)

Ik ben nu toevallig met een extreme situatie van notificaties bezig, waarbij we een gedistribueerde en gerepliceerde queue (Kafka) gebruiken om straks meerdere servers te notificeren die weer web clients gaan notificeren. Pollen met de database geeft gewoon veels te veel verkeer en ongewenste delays.
BasieP schreef op zondag 30 juni 2013 @ 13:24:
Beste mensen, ik overpijns een probleem waarvan ik eigenlijk zelf niet helemaal weet of het een probleem is.
In de meeste gevallen is dit geen daadwerkelijk probleem en wordt de data simpelweg overschreven, soms raken updates dus kwijt. Ok, misschien is dit soms voor gebruikers wel een probleem, maar de meeste applicaties houden hier gewoon geen rekening mee. Probeer maar uit op dit forum bijvoorbeeld. 8)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1