Avatar billede moddi100 Seniormester
28. september 2014 - 04:16 Der er 18 kommentarer og
1 løsning

Synkronisere aktivitet og sikre kun en udførsel på tværs af servere

Hej,

Jeg er interesseret i at vide, hvordan man bygger en service der kan kalde en given url på et fastsat tidspunkt e.g. kl. 04:00 hver dag. Præcis ligesom et cronjob.

Blot vil jeg gerne vide, hvordan man laver dette på tværs af en stak webservere. Går én webserver ned, skal en af de andre sørge for at udføre opgaven (kalde en url). Det er dog vigtigt at opgaven altid udføres præcis én gang i døgnet og ikke mere.

Hvordan ville man rent teoretisk strikke sådan en service sammen?

Med venlig hilsen
Morten
Avatar billede arne_v Ekspert
28. september 2014 - 04:24 #1
Det nemmeste er nok at bruge en database til at synkronisere web serverne.

En database som understoetter transaktioner, transaction isolation level >= repeateable read, SELECT inuse FROM synctbl og UPDATE synctbl SET inuse = TRUE.
Avatar billede arne_v Ekspert
28. september 2014 - 04:25 #2
Saa saetter du cron eller andet til at kalde PHP kode paa all noder, men kun af dem faar lov til at saette flaget og lave det som skal laves.
Avatar billede moddi100 Seniormester
28. september 2014 - 04:45 #3
Det må du lige uddybe arne_v, du vil bruge transaction til at sikre, at en af noderne ikke opdaterer, imens en anden allerede er i gang med processen. Så langt så godt, men hvad mener du med resten?

Og hvordan sikrer du dig, såfremt database-serveren går ned? Ideelt set, så jeg jo helst at der ikke var nogen hoved-server, som alle var afhængige af.
Avatar billede arne_v Ekspert
28. september 2014 - 04:55 #4
Der er et flag i databasen som bruges til at laase med.

Transaktion bruges til at sikre at SELECT af flag og UPDATE af flag kan laves atomisk.
Avatar billede arne_v Ekspert
28. september 2014 - 04:56 #5
Der er vel en standby database server som tager over hvis database server gaar ned??
Avatar billede moddi100 Seniormester
28. september 2014 - 15:48 #6
Hvad mente du med følgende:
transaction isolation level >= repeateable read


Men som udgangspunkt er der ikke nogen database-server til at overtage, princippet er, at jeg I vil sætte det op på php-webhoteller på tværs af forskellige udbydere.

Går én webserver/webhost helt ned, vil jeg gerne have at de andre kan klare opgaven. Uanset hvilke(n) webserver der går ned.
Det jeg sørger er dybest set at lave min egen lille decentraliserede cloud. Jeg er dog opmærksom på, at der vil være tale om forskellige IP-adresser/domæner, som man vil skulle afprøve i tilfælde af, at en eller flere af noderne er nede.

Giver det mening?
Avatar billede moddi100 Seniormester
28. september 2014 - 15:50 #7
Min egen tanke var noget i stil med, at server A skal fortælle/indhente accept fra over halvdelen af noderne, for at kan udføre opgaven. Lige så snart server A, har informeret de andre servere om dette, vil de jo så ikke udføre opgaven, og en eventuel server B vil ikke kunne få accept fra over halvdelen til også at udføre opgaven.

Denne fremgangsmåde betyder dog, at der potentielt kan gå ret lang tid førend en server har kontaktet minimum halvdelen af serverne. Så jeg tænkte, at der nok var en bedre måde. Men måske man skal ind og se på noget med én central (database-)server.
Avatar billede arne_v Ekspert
28. september 2014 - 16:42 #8
transaction isolation level >= repeateable read er noedvendigt for at metode med foerst en SELECT og saa en UPDATE virker.
Avatar billede arne_v Ekspert
28. september 2014 - 16:44 #9
Du kan godt lave en loesning med in-memory data og kun kommunikation over netvaerk. Det du har bruge for er ogsaa kendt som en DLM - distributed lock manager.
Avatar billede arne_v Ekspert
28. september 2014 - 16:49 #10
DLM er typisk noget man bruger i OS og database kode skrevet i C eller i nogen af de nyere big data thingie skrevet i Java.

Jeg kan ikke umiddelbart finde noget om en saadan i PHP.
Avatar billede moddi100 Seniormester
28. september 2014 - 19:06 #11
Ud fra dit indlæg om DLM, har jeg kigget lidt nærmere på ZooKeeper. Med denne viden og dine svar, er jeg kommet frem til, at der nok skal udpeges én hovedserver. Ved fejl, må de andre servere, så sørge for automatisk at udpege en ny.

ZooKeeper fungerer ved at alle write operationer sendes til hovedserveren, som så iværksætter synkronisering med alle de andre servere. Dette princip kunne man sådan set sagtens kopiere. Og så selvfølgelig anvende transactions på hovedserveren.

Mit bud på en løsning:
Hovedserver:
Antag at vi har n=10 servere. Så snart en server (S1) ikke kan kontakte hovedserveren spørg den de andre servere, om de har forbindelse. Er der ikke forbindelse til hovedserveren udpeges S1 som ny hovedserver. Såfremt S1 ikke får nogle svar, anses den som værende afskåret. Når der igen er forbindelse til de andre, skal S1 derfor synkronisere på ny.

Synkronisering:
En klient kontakter S2 med en write-forespørgsel. S2 kontakter hovedserveren, som også gemmer en log om forespørgselen. Hovedserveren accepterer og sender en opdatering rundt til alle servere med ændringen. S2 svarer klienten.

Ved simpel read-forespørgsel til S2, svarer S2 klienten ud fra egen data. En log sendes til hovedserveren.

Planlagte opgaver m.m.
Alle serverne sørger på det planlagte tidspunkt at kontakte hovedserveren, som kun tillader første mand at udføre opgaven. Såfremt hovedserveren er utilgængelig, vælges først en ny, hvorefter opgaven udføres.
Avatar billede moddi100 Seniormester
28. september 2014 - 19:12 #12
Bør man overveje deadlock problemer, såfremt S2 har fået tilladelse til at udføre en opgave, men aldrig vender tilbage, når den er løst? Nogen gode forslag hertil?
Avatar billede arne_v Ekspert
28. september 2014 - 19:58 #13
Det er vel muligt at teste paa om opgaven er fjordt faerdig eller ej.

Det er almindeligt med keep-alive messages saaledes at en node der er nede hurtigt opdages.

Husk at der altid skal vaere >50% af noderne tilstede (quorum) for at undgaa split brain problemer.
Avatar billede arne_v Ekspert
28. september 2014 - 20:00 #14
Jeg vil fraraade dig at forsoege at implementere saadan noget fra bunden af. Det er meget tricky at faa korrekt.

Og PHP's fleksible ekskverings-model goer det endnu vanskeligere.

Enten brug en database.

Eller koer noget eksternt ved siden af PHP som PHP kan kommunikere med.
Avatar billede moddi100 Seniormester
28. september 2014 - 20:04 #15
Jeg synes jo fordelen ved at lave det selv, var at man undgik afhængigheden af én (database-)server. Men det kan da godt ske du har ret i, at det ikke bliver for komplekst til at man kan opnå et ordentligt resultat.
Avatar billede arne_v Ekspert
28. september 2014 - 20:18 #16
At saette 2 database servere op saa den anden tager over hvis den foerste gaar ned er helt standard.
Avatar billede arne_v Ekspert
28. september 2014 - 20:19 #17
Den ande mulighed var at koere noget andet (formentligt skrevet i Java) ved siden af Apache+PHP paa web serverene og lade PHP snakke med det via noget IPC/netvaerk kommunikation.
Avatar billede moddi100 Seniormester
29. september 2014 - 16:54 #18
Jeg prøver mig frem med at lave min egen PHP-løsning, og vil så prøve at stress-teste den lidt. Så må vi se hvordan det hele performer.

Det kan meget vel være jeg ender med at bruge database-løsningen, men i første omgang, synes jeg, det kunne være interessant at lære lidt mere om DLM og de dertilhørende problemstillinger.

Læg et svar for din gode hjælp og kvalificerede råd!
Avatar billede arne_v Ekspert
29. september 2014 - 17:08 #19
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester