Jag nämnde i kommentarerna till min introduktionsartikel om Terracotta att Terracotta kan användas för flera olika ändamål. Jag tänkte utveckla det lite grand här.

Ett sätt att beskriva vad Terracotta gör är att det pekar ut specifika objekt, och ser till att deras tillstånd är samma på flera parallella (klustrade) Java-VMar. Det finns en central Terracotta-server som hanterar detta tillstånd och skyddar det med läs- och skrivlåsningar runt åtkomst till de utpekade objekten. Eftersom Terracotta håller koll på hur varje Java-VM använder de klustrade objekten kan vissa optimeringar göras. Den mest uppenbara är kanske att en VM som aldrig behöver vare sig läsa eller skriva till ett objekt inte heller behöver läsa in det i minnet. Objektet läses alltså in vid behov av Terracotta.

Det finns flera sätt att dra nytta av den arkitekturen…

  1. Klustring för prestanda
  2. Klustring för redundans och fail-over
  3. Interprocess-kommunikation
  4. Tillgång till en virtuell Java-VM med ”oändligt” mycket tillgängligt minne

Klustring för prestanda och redundans

Kanske den första anledningen att klustra man kommer att tänka på — med en klustrad applikation finns det flera servrar som delar på lasten och alltså klarar av en större total last, med möjlighet att bygga ut genom att köpa mer hårdvara. Det ger också en säkerhet mot fel i hårdvaran eftersom flera servrar har samma uppfattning om applikationens tillstånd och en ny server kan ta vid där en annan fallerat.

Interprocess-kommunikation

Ett lite annorlunda sätt att se på delat tillstånd mellan servrar är att de också kan dela på interna kommunikationsstrukturer som t.ex. meddelandeköer. Om applikationen kan beskrivas som ett flöde av indata-meddelanden som ska bearbetas separat så kan du enkelt fylla på en trådsäker kö från en eller flera indata-trådar och sedan ha mellan en och väldigt många jobbtrådar som tar meddelanden från kön och utför arbetet (för att sedan kanske lägga in dem i ytterligare en kö för nästa steg i processen). Om meddelande-kön är klustrad kan alla dessa trådar kan ligga på godtyckligt uppdelade fysiska maskiner.

Ett konkret exempel på en sådan applikation skulle kunna vara ett blanketthanteringssystem som har ett inflöde av inscannade blanketter (i något bildformat) som ska OCR-tolkas för att sedan sparas undan i något informationssystem. OCR-behandlingen kan vara ett rätt tungt jobb och om flödet är stort kan det vara knöligt att designa ett skalbart system. Med vår lösning får vi skalbarhet från en maskin som har en indatatråd och en OCR-tråd i samma Java-VM, till en klustrad Terracotta-lösning där det räcker att lägga till hårdvara för att fortsätta skala uppåt. Inte en enda kodrad är ändrad.

Java-VM med ”oändligt” mycket tillgängligt minne

Ytterligare ett användningsområde är lite av en bieffekt till vad jag nämnde inledningsvis — att Terracotta genom sin roll som övervakare av klustrade objekt också får tillfälle att lägga in lite smarta optimeringar. Det är nämligen så att eftersom de klustrade objektens tillstånd sparas (på disk) på den centrala Terracotta-servern och eftersom Terracotta ser till att de bara läses in i minnet på den servern och vid det tillfället som det faktiskt behövs, så kan den totala mängden klustrade objekt vara mycket större än vad som skulle rymmas i ens den fetaste server-VMens internminne. Den totala mängden tillgängligt minne som kan användas begränsas av hur mycket disk det finns på Terracotta-servern så att kalla det för ”oändligt” mycket är väl en rätt grov approximation (läs ”lögn”), men det är lätt att se att det går att hantera minst en magnitud mer minne i denna virtuella VM än i en oklustrad dito.

Det här är naturligtvis egentligen inget annat än en implementation av disk-baserat virtuellt minne, precis som operativsystemen gör det, men det kommer också runt enskilda Java VMars begränsningar i hur mycket minne de klarar av att hantera (virtuellt eller ej).

Nyttan av att kunna ha ett väldigt stort minne tillgängligt för en Java-VM är kanske inte uppenbar för alla, men det finns tillämpningar och algoritmer som hanterar väldigt stora mängder rådata och att slippa ha själva minneshanteringen med i koden förenklar dessa implementationer avsevärt!

Kommer ni på några fler användningsområden?