Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[JAVA] caching met meerdere nodes

Pagina: 1
Acties:

  • marty
  • Registratie: Augustus 2002
  • Laatst online: 27-03-2023
Ik heb op dit moment een applicatie op twee identieke tomcat servers draaien die achter een loadbalancer zitten. Er moet wat functionaliteit bijkomen waarin acties van een gebruiker bijgehouden moeten worden die sessie-overschrijdend moet zijn (dus als de sessie weg is, moet de actie nog steeds bewaard blijven voor een x-periode (denk aan enkele uren)). Wellicht dat er in de toekomst nog andere vergelijkbare dingen in opgeslagen moeten worden.
Er is op dit moment geen database en ik zou voor dit doeleinde een database ook overkill vinden (de users zitten in een extern (read-only) systeem wat ik bevraag tav user-gerelateerde dingen). Ik wil gewoon key-value pairs op kunnen slaan in een cache-achtig systeem. En liefst met extra's zoals een expiration time.

De eisen die ik heb:
  • Beide servers in het cluster moeten over dezelfde data beschikken
  • Als het cluster groeit - naar, pak 'm beet 6 nodes - dan moet dit geen probleem zijn
  • Hoef op dit moment geen grote hoeveelheden data op te slaan. Verwacht ook niet dat dit in de toekomst wel zo is, maar als het schaalbaar is in die zin is dat meegenomen.
  • Als er eens een keer data verloren gaat is dat jammer maar niet onoverkomelijk. De eis in die zin is dus dat ik geen oplossing hoef die dit garandeert terwijl dit ten koste gaat van bijvoorbeeld performance.
  • Ik stop deze functionaliteit ook het liefst een in een cluster oplossing zodat er altijd eentje uit kan vallen. Het meest voor de hand liggende is dan dat het op dezelfde machines wordt geinstalleerd als de tomcat instances.
Performance is uiteraard een belangrijk punt. Een caching mechanisme wat naar disk schrijft valt dus in principe af lijkt me.

Verder probeer ik bij mijn besluitvorming tot het kiezen van een oplossing ook te bepalen wat beter is: alle data repliceren over de verschillende nodes of een iets als een consistent hashing manier. Zoals ik al zei mag er incidenteel data verloren gaan, dus replicatie is niet persee nodig. Aan de andere kant: ik vermoed niet dat het om zulke hoeveelheden zal gaan dat het een voordeel gaat zijn als de data verspreid opgeslagen wordt. Adviezen hieromtrent worden ook gewaardeerd.

Ik ben wat gaan googelen wat momenteel goede oplossing zijn voor een Java applicatie op tomcat en heb de volgende dingen gevonden:

Memcached
Heb ik ervaring mee vanuit het verleden (maar binnen PHP) en werkt in principe prima. Maar misschien zijn er betere oplossingen?

Redis
Wordt vaak met memcached vergeleken en komt er dan vaak positiever uit. Is bijvoorbeeld flexibeler qua opslaan van verschillende typen data wat ik een leuke plus vind. Performance lijkt hetzelfde? Wat ik niet goed kon vinden is hoe ze verschillen met betrekking tot een cluster-architectuur.

JCS
Lijkt een optie, maar kon ik helaas weinig over vinden in relatie tot de bovengenoemde twee. Veel informatie leek bovendien erg oud. Las aardig wat geklaag, maar dat is misschien outdated?

Hazelcast
Lijkt ook een optie, maar kon wederom weinig vergelijkingen vinden en heb dus geen beeld hoe goed dit performt en in gebruik is, ivm de bovenstaande.

EHcache
Lijkt redelijk vergelijkbaar met redis en memcached, maar het feit dat ik er veel minder over vond vind ik een nadeel. Een actieve community achter een product vind ik wel een grote pre


Met dit topic hoop ik wat reacties met ervaringen en suggesties te krijgen om zo tot een goed besluit te kunnen komen.

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 21-11 15:31

TheNephilim

Wtfuzzle

Memcached was het eerste wat in mij op kwam, maar die garandeert volgens mij geen persistentie. Als ik jou was, zou ik eens naar MongoDB kijken. Dat is in principe een database, maar key=>value georiënteerd, als ik me niet vergis.

  • Dnomaid
  • Registratie: Augustus 2003
  • Laatst online: 21-11 10:55
MongoDB is een persistente documentstore, dat wou de TS toch net niet?

Vreemd dat er weinig te vinden is over EHCache, dat is toch een vrij populair product? Heb het echter nooit gebruikt in een clusteromgeving.

Nog een alternatief: InfiniSpan
http://infinispan.org/

[ Voor 62% gewijzigd door Dnomaid op 08-11-2013 15:22 ]


  • armageddon_2k1
  • Registratie: September 2001
  • Laatst online: 27-07 10:18
TheNephilim schreef op vrijdag 08 november 2013 @ 15:15:
Memcached was het eerste wat in mij op kwam, maar die garandeert volgens mij geen persistentie. Als ik jou was, zou ik eens naar MongoDB kijken. Dat is in principe een database, maar key=>value georiënteerd, als ik me niet vergis.
Bedoel je niet Redis?

Engineering is like Tetris. Succes disappears and errors accumulate.


  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33

HMS

Er zijn vrij veel Key-Value stores die kunnen wat TS wil. Wikipedia heeft een klein lijstje: Wikipedia: NoSQL

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 22-11 18:11
Oracle zelf biedt Coherence als in-memory data grid oplossing. Gezien de eisen zou dat prima moeten voldoen.

  • Domdo
  • Registratie: Juni 2009
  • Laatst online: 30-06 20:29
Nog een alternatief: Terracotta. Daarmee kan je de objecten van een JVM delen. Lijkt op Coherence en InfiniSpan

  • marty
  • Registratie: Augustus 2002
  • Laatst online: 27-03-2023
Bedankt allen voor de replies!

Hebben jullie toevallig ook een toelichting op de suggesties jullie gegeven hebben. Want in plaats van de keuze makkelijker te maken wordt het zo alleen maar moeilijker :-) Ik zoek juist naar wat onderbouwingen waarom je het ene product wel / niet zou kiezen.

en persistence is inderdaad niet wat ik zoek.

  • Pizzalucht
  • Registratie: Januari 2011
  • Laatst online: 14:05

Pizzalucht

Snotneus.

Op zich zoek je een tijdelijke persistance, met MongoDB kun je goed schalen en een TTL aan documents geven.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Pizzalucht schreef op zaterdag 09 november 2013 @ 01:03:
Op zich zoek je een tijdelijke persistance, met MongoDB kun je goed schalen en een TTL aan documents geven.
Ik betwijfel of het zo goed schaalt als een memcached-cluster... Die heeft namelijk uberhaupt geen onderlinge communicatie nodig.
En mijn ervaring met MongoDB is zeker positief, maar performance-wise is het nog wel af en toe erg inconsistent, zeker als je relatief veel writes doet. Wij gebruiken het hier bij Tweakers voor de opslag van gebruikerssessies en hebben uiteindelijk maar onze de mongodb-opslag van onze Master op tmpfs (=memory filesystem) gezet (met 2 slaves met storage op disk)... Want dat was de enige manier die wij konden vinden om sporadische pieken van 1+ seconde in wachttijden bij het schrijven (en dan ook lezen!) te voorkomen.

Overigens kan je niet een TTL aan documenten geven. Je kan een TTL aan een collection geven en alle documenten in die collection hebben dan dezelfde TTL, althans als je er aan gedacht had de documenten de bijbehorende value te geven en een index op die key te zetten ;)
Het is in ieder geval een stuk omslachtiger dan in Memcached en vziw ook dan Redis (hoewel ook die weer iets omslachtiger is dan Memcached).

Het klinkt alsof Redis hier een van de betere keuzes is, dat zorgt er in ieder geval voor dat er nog wel enige vorm van persistence is. Dus dat niet al je gebruikers er last van hebben als je de boel een keer moet herstarten.
Voor de schaalbaarheid van 2 naar 6 tomcat's zou ik me niet zo'n zorgen maken bij welke van de genoemde opties dan ook... Tenzij je heel inadequate hardware neerzet gaan ze het allemaal aankunnen, zeker van alle pure in-memory oplossingen (inclusief Redis) zou ik verwachten dat het je werk prima aankan.

  • Pizzalucht
  • Registratie: Januari 2011
  • Laatst online: 14:05

Pizzalucht

Snotneus.

ACM schreef op zaterdag 09 november 2013 @ 09:58:
[...]

Ik betwijfel of het zo goed schaalt als een memcached-cluster... Die heeft namelijk uberhaupt geen onderlinge communicatie nodig.
En mijn ervaring met MongoDB is zeker positief, maar performance-wise is het nog wel af en toe erg inconsistent, zeker als je relatief veel writes doet. Wij gebruiken het hier bij Tweakers voor de opslag van gebruikerssessies en hebben uiteindelijk maar onze de mongodb-opslag van onze Master op tmpfs (=memory filesystem) gezet (met 2 slaves met storage op disk)... Want dat was de enige manier die wij konden vinden om sporadische pieken van 1+ seconde in wachttijden bij het schrijven (en dan ook lezen!) te voorkomen.

Overigens kan je niet een TTL aan documenten geven. Je kan een TTL aan een collection geven en alle documenten in die collection hebben dan dezelfde TTL, althans als je er aan gedacht had de documenten de bijbehorende value te geven en een index op die key te zetten ;)
Het is in ieder geval een stuk omslachtiger dan in Memcached en vziw ook dan Redis (hoewel ook die weer iets omslachtiger is dan Memcached).

Het klinkt alsof Redis hier een van de betere keuzes is, dat zorgt er in ieder geval voor dat er nog wel enige vorm van persistence is. Dus dat niet al je gebruikers er last van hebben als je de boel een keer moet herstarten.
Voor de schaalbaarheid van 2 naar 6 tomcat's zou ik me niet zo'n zorgen maken bij welke van de genoemde opties dan ook... Tenzij je heel inadequate hardware neerzet gaan ze het allemaal aankunnen, zeker van alle pure in-memory oplossingen (inclusief Redis) zou ik verwachten dat het je werk prima aankan.
Qua prestaties is mongo helaas inderdaad echt heel erg afhankelijk van de disk IO. Dat zou nog wel eens een probleem kunnen zijn.

Als je wilt dat je users makkelijk tussen servers kunt balancen, dan is het toch juist handig als je de data kan sharden/replicaten?

Je geeft inderdaad geen TTL aan documenten, je maakt een index op een date property met een expire date. Je kan dus met de waarde in het date field bepalen wanneer een document expired. Dus een beetje handig kloten met Date.now pakken en die aanpassen om een TTL per document te maken :+

  • sub0kelvin
  • Registratie: September 2002
  • Laatst online: 10-08-2023
Wij gebruiken bij Shopify zowel Memchached als Redis erg intensief.
[list]
• Memcached voor alles wat per direct verloren mag gaan, eigenlijk alles wat Rails wil cachen, maar ook het tijdelijk opslaan van data voor background jobs e.d.
• In-memory Redis voor dingen die wat complexer zijn maar toch verloren mogen gaan. Doordat je met LUA atomic acties kunt uitvoeren die veel meer omvatten dan 'getset', kun je uitgebreide data opslaan en bewerken zonder (of iig minder) bang te zijn voor race condities.
• Persisted Redis voor zaken die klein zijn en frequent gelezen/geschreven worden, maar toch een crash moeten overleven.


Bij mijn vorige (Java) werkgever met tevredenheid ehcache gebruikt als cache voor Hibernate objects & queries en Wicket sessies, en dat schaalde ook prima over meerdere nodes. Duplicatie tussen nodes was mogelijk, maar ik weet even niet meer hoe dat zat.

Redis clustert momenteel volgens mij alleen door de data te splitsen, niet door data synchroon te houden. Redis Cluster komt per versie 2.8, maar daar kun je waarschijnlijk niet op wachten. Wij hebben meerdere dedicated Redis en Memcached servers draaien, maar ik weet niet hoe onderling de data verspreid is. Memcached heeft duidelijk een lagere CPU-load dan Redis, maar met een beetje uitkijken dat je niet te complexe LUA-scripts schrijft, hoeft dat geen probleem te zijn.

Als ik alles zo bekijk denk ik dat Redis goed past bij jouw wensen: TTL, key-value, inmem (met mogelijk tot persisten van snapshots), schaalbaar in hoeveelheid data, clusterbaar (maar op een andere manier dan jij eist).

  • marty
  • Registratie: Augustus 2002
  • Laatst online: 27-03-2023
sub0kelvin schreef op zondag 10 november 2013 @ 02:41:
Wij gebruiken bij Shopify zowel Memchached als Redis erg intensief.
Puur interesse: waarom ook memcached als jullie ook Redis gebruiken? Ik snap dat je naar Redis grijpt voor de wat complexere dingen, maar welke voordelen biedt memcached dat je redis niet ook gewoon voor de simpele get/set operaties gebruikt? Is dat puur de lagere CPU load waar je het hieronder over hebt of zijn er nog andere zaken? Of verschilt die CPU load dan echt zo significant dat dit de extra complexiteit rechtvaardigt?
Redis clustert momenteel volgens mij alleen door de data te splitsen, niet door data synchroon te houden. Redis Cluster komt per versie 2.8, maar daar kun je waarschijnlijk niet op wachten. Wij hebben meerdere dedicated Redis en Memcached servers draaien, maar ik weet niet hoe onderling de data verspreid is. Memcached heeft duidelijk een lagere CPU-load dan Redis, maar met een beetje uitkijken dat je niet te complexe LUA-scripts schrijft, hoeft dat geen probleem te zijn.
Wat ik er van begrijp is de cluster-versie nu nog niet stabiel verklaart en zou ik dus met Redis partitioning aan de gang moeten gaan en dat voldoet volgens mij ook prima.

Ik heb even naar wat libraries gezocht en Jedis lijkt een van de meest actieve (qua ontwikkeling) en tevens degene die wordt aangeraden door Redis zelf.

Ik ga overigens niet voor Master-Slave replication kiezen denk ik. Hoewel het nu op zich prima zal voldoen is het minder schaalbaar. En hoewel schaalbaarheid nu nog geen issue lijkt is het natuurlijk wel handig als het ooit wel een issue wordt en daarnaast vind ik het een minpunt dat de afhankelijkheid van je master relatief groot is.

Voor dit doeleinde lijkt ShardedJedis met een connectionpool perfect.

Dit ter informatie voor anderen die dit lezen en mogelijk om nog wat andere suggesties uit te lokken :)

  • Gehakt
  • Registratie: Juli 2002
  • Laatst online: 24-10 20:19
Is iets als opensplice niets voor je? Dat bied shared memory emet een history indien je dat wilt.

  • sub0kelvin
  • Registratie: September 2002
  • Laatst online: 10-08-2023
marty schreef op zondag 10 november 2013 @ 12:42:
Puur interesse: waarom ook memcached als jullie ook Redis gebruiken? Ik snap dat je naar Redis grijpt voor de wat complexere dingen, maar welke voordelen biedt memcached dat je redis niet ook gewoon voor de simpele get/set operaties gebruikt? Is dat puur de lagere CPU load waar je het hieronder over hebt of zijn er nog andere zaken? Of verschilt die CPU load dan echt zo significant dat dit de extra complexiteit rechtvaardigt?
Ik ben niet betrokken geweest bij de introductie van Redis, ik werk er namelijk nog niet zo lang. Dus ik weet er niet alles van, maar ik zal proberen je te beantwoorden.

CPU load is zeker een van de redenen waarom niet alles in Redis wordt gedaan. Zeker wanneer je andere dingen doet dan simpele 'get', 'set' en 'increments' doet en je een paar K aan rounds per seconde moet verwerken ga je dat merken. Memchaced was er eerst en deed alles wat tijdelijk mocht zijn, de rest werd in de databases gedaan. DB is niet echt goed voor de load als je veel kleine schrijfacties moet doen, dus sommige kleine dingen die persisted moeten zijn van de database naar Redis verhuisd. En met name de cache zaken die in de code race condities konden veroorzaken, zijn van memcached verhuist naar LUA scripts die uitgevoerd worden door Redis. Memcached werkt gewoon prima, en dat aanvullen met Redis waar Memcached niet voldoende is lijkt me een prima oplossing.

Er zullen nog andere overwegingen zijn geweest, maar dit is wat ik zoal weet.

Meer (out-dated: half jaar geleden = ancient history) informatie hier: http://www.slideshare.net...ify-scales-rails-20443485 met bijbehorden presentatie: YouTube: Big Ruby 2013 How Shopify Scales Rails by John Duff

[ Voor 8% gewijzigd door sub0kelvin op 10-11-2013 15:46 ]


  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Pizzalucht schreef op zaterdag 09 november 2013 @ 01:03:
Op zich zoek je een tijdelijke persistance, met MongoDB kun je goed schalen en een TTL aan documents geven.
MongoDB schaalt helemaal niet zo goed als ze zelf beweren. Schijnt nogal een enorme dip te zijn na 100M items in een collection ofzo. Genoeg over te vinden op teh interwebz.

Ben zelf bezig geweest met Redis. De implementatie is erg simpel, veel handigheidjes (atomic increments op waardes, handig voor counters e.d.) en volgens mij erg geschikt voor de use-case van de TS. Sharding en replication zijn standaard aanwezig.

https://niels.nu


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

marty schreef op zondag 10 november 2013 @ 12:42:
Ik ga overigens niet voor Master-Slave replication kiezen denk ik. Hoewel het nu op zich prima zal voldoen is het minder schaalbaar. En hoewel schaalbaarheid nu nog geen issue lijkt is het natuurlijk wel handig als het ooit wel een issue wordt en daarnaast vind ik het een minpunt dat de afhankelijkheid van je master relatief groot is.
Pas op met dit soort uitspraken :)

Je hebt het over nu 2 en mogelijk straks 6 tomcat-servers. Mijn verwachting zou zijn dat 1 fysieke server voor je je hier besproken database (memcached, redis, watdanook) makkelijk de belasting aankan die jij met die 6 tomcat's erop kunt maken. Tenzij je natuurlijk veel meer werk naar je database stuurt dan ik nu verwacht dat er uiteindelijk gaat gebeuren :P

Als inderdaad blijkt dat 1 databaseserver het werk makkelijk aan kan, dan is het nogal zonde om allerlei moeite te steken in een nog meer schaalbare opstelling dan je nu al hebt.

Sterker nog, je geeft zelf al aan dat de data in het ergste geval best mag verdwijnen dus je hoeft zelfs geen rekening te houden met een transparante overgang van deze naar een andere opstelling.
Mocht de "nood" dus aan de man komen, dan kan je tegen die tijd een compleet nieuw databasecluster opbouwen en de overstap maken. Met als voordeel dat je je dan actuele situatie kunt gebruiken en ook met de dan actuele software kunt werken (wie weet is Redis' clustersysteem dan superhandig en -stabiel of kan Mongo tegen die tijd wel schalen naar grote IO-loads). Maar je bespaart dan nu in ieder geval allerlei premature werkzaamheden voor iets wat toch vreselijk moeilijk is te voorspelen.


Zorg voor nette abstracties in je code tussen de verwerking en dataopslag en het zou een relatief kleine inspanning moeten zijn om over te gaan naar sharding en/of een compleet andere opslagtechniek.

Afhankelijkheid van een master hou je in veel situaties toch wel. Met 2 tomcat-nodes is het sowieso wel erg overkill om een cluster van 3 storageservers te bouwen. En met een databaseoplossing met 2 nodes wordt het vaak een active/passive-opstelling, soms master/slave, soms master/master. Je kan tenslotte alleen een meerderheid hebben als je beide nodes 'up' zijn en dan is automatische failover van de meeste clusteroplossingen niet mogelijk :P
En laten we eerlijk zijn... fatsoenlijke serverhardware kan over het algemeen prima een uptime van een jaar of meer halen :)

Dus als je huidige databasewerk goed zou passen bij een eenvoudige master/slave-opstelling van Redis en je ook nog wel verwacht dat 3x zoveel werk er ook goed op werkt... waarom dan niet domweg met master/slave aan de slag? :)

  • marty
  • Registratie: Augustus 2002
  • Laatst online: 27-03-2023
Je hebt een goed punt. Bedankt voor de input.

Nu ik er nog eens over nadenk valt de afhankelijkheid met de master ook wel mee, want ik zie dat het eigenlijk een peulenschil is om een slave om te zetten naar master.

Aan de andere kant: ik lees in de documentatie dat er binnen een master-slave configuratie bepaalde functionaliteit beschikbaar is die je niet heb als je de boel partitioneert. Daar mee-/omheen werken vind ik ook weer zoiets .. dan is het misschien netter (en uiteindelijk minder effort) gewoon van af het begin met partitioning te werken als ik besluit dat het een mogeljkheid moet zijn in de toekomst redelijk eenvoudig over te stappen.

  • AnonymousCoward
  • Registratie: Juli 2011
  • Laatst online: 08-04-2023
Disclaimer: ik werk voor Terracotta, en ben dus enigszins bevooroordeeld.
Ik kan in ieder geval bevestigen dat Ehcache (wat van Terracotta is) alle gewenste functionaliteiten biedt. Key-value pairs, persistentie, expiration, eviction policies en clustering (dus voor failover en high availability). Kijk meer eens op Ehcache.org of terracotta.org...
Pagina: 1