Jump to content
php.lv forumi

Memcache failover risinājumi


Lynx

Recommended Posts

Sveiki,

 

esam projektā saskārušies ar vienu problēmu un vēlējos pakonsultēties varbūt cilvēkiem ir idejas kā vislabāk šo jautājumu risināt.

 

Situācija ir tāda, ka ir mums ir 3 memcache serveri, kas visi tiek izmantoti clusterī. Un pa retam ļoti lielas noslodzes gadījumos var sanākt sastapties ar timeoutu konektējoties kādam no memcache serveriem. Tas ko dara memcache tajā brīdī ir pārveido serveru hašu un seto() ierakstu kādā citā serverī, kas tajā brīdī ir pieejams. Nākamajos requestos pastāv iespēja, ka pirmais serveris, kuram agrāk neizdevās piekonektēties atkal ir pieejams un klients paņem vecos datus, kas rada būtiskas sinhronizācijas problēmas.

 

Šeit ir aprakstīta situācija angliski: http://code.google.c...re,_or_Failover (mūsu gadījumā gan nav tīkla vada izraušana :D)

 

Ātri radās divi risinājumi:

 

1 risinājums:

  • Katram ierakstam ko mēs liekam memcachē datus vienmēr likt masīvā un masīvā obligāti pievienot jaunu lauku, piemēram: write_time
  • izveidot atsevišķu memcache ierakstu: memcache_[user_id], kur masīvā glabājas visi konkrētā lietotāja memcache ieraksti ar write_time vērtībām
  • Kad veicam get() salīdzinam vai memcache_[user_id] ieraksta write_time sakrīt ar izvilkto datu write_time, ja nesakrīt uzskatam, ka ieraksts ir nederīgs un velkam datus no DB
  • Ja nu gadījumā neeksistē ieraksts memcache_[user_id] - velkam pilnīgi visu no db

Lielākais mīnus ir ka nākas izmantot datu lauku un papildināt to ar papildus vērtību. Un ja orģināli bija plānots ielikt memcachē stringu vai tīri int, tad tagad būs nepieciešams array.

 

2 risinājums:

  • Modificēt pašas atslēgas, piemēram, veidot tās šādi: "nosaukums_[user_id]_[key]" un sastopoties ar Timeout kļūdu palielināt $key. Problēma ir ka pašlaik jāizdomā kur glabāt šo key vērtību - visticamāk datubāzē, bet tas prasīs veikt papildus selektu datubāzei no kā vēlamies izvairīties.

Mēs nevaram rakstīt šo vērtību sesijās, jo sesijas arī uztur memcache. Vēl ir ideja, ka tās varētu pieglabāt APC cachē, kuru mēs arī izmantojam, bet tad konkrētās vērtība ir piesaistīta noteiktam webserverim, kas nozimē pēc refresha, ja trāpīs uz cita webservera būs nepieciešama pilnīga memcache ielāde no db, jo $key neeksistē, kaut gan ar datiem viss ir ok.

 

Ir kādas idejas vai pieredze šajā jautājuma?

Link to comment
Share on other sites

Kā būtu, ja izslēgtu memcache.allow_failover PHP settingos? Tad vismaz izvairītos no tā, ka tiek sačakarētas atslēgas citos serveros un ja problēmas ir pietiekami retas, tad gan jau kaut kā varētu pārdzīvot.

Link to comment
Share on other sites

Tas arī risinājums, nedaudz bail ir par to, ka ja patiesi kāds no memcache serveriem nomirst, nevis vienkārši netiek galā ar slodzi, tad failovera neeksitēšana mūsu datubāzi kaut kādā brīdī arī nogalinātu. Kas ir vēl ļaunāk.

 

Tapēc šeit šķiet, ka tomēr jāizdomā kāds koda risinājums, kas būtu pietiekami ātrs un effektīvs.

 

Pašlaik, kamēr nav labākas idejas, esmu ķēries pie pirmā risinājuma realizēšanas, redzēs kādi zemūdens akmeņi vēl parādīsies.

Link to comment
Share on other sites

Tāpat jūsu gadījumā pie failover 1/3 pieprasījumu aiziet nākamo reizi uz datubāzi, lai tiktu pie vajadzīgajiem datiem. Jārūpējas par to, lai DB to varētu pavilkt - pareizi indeksi, optimāli vaicājumi, utt.

 

No otras puses - nezinot kas tas par projektu un cik svarīga ir nepārtraukta pieejamība, cik kritiskas ir kļūdas, ja tādas notiek ir visai pagrūti ieteikt vienu vai otru risinājumu.

Link to comment
Share on other sites

1) Uztaisi papildus servisu, kuram failoveru gadījumā tiek ziņoti visi failoveru dati, šis serviss savukārt atjauno datus mecahced serveros nedaudz vēlāk, kad serveris tikko pieejams. Bet papildus tam monitorē failoveru daudzumu, vai paša servera dzīvīgumu, ja tas jūt, ka serveris ir aizgājis pa pieskari, tad ziņo, ka serveris aizgājis pavisam un dati jāraksta citos serveros.

 

2)Otrs variants, griezties vienmēr pie servera, kuram failovera gadījumā būtu nodoti dati un pārbaudīt, vai tur nav tādi dati arī. Bet tas principā dubulto pieprasījumu skaitu un nav nekāds spožais risinājums.

Link to comment
Share on other sites

nevar pie juzera cepumā glabāt kaut kādu identifikatoru, kas norāda kurā memcache serveri viņs tusējas?

un tad jau ir taimauts, tad pārceļam tusiņu uz citu serveri un pie jūzera pieglabājam, ka tusējam citā serverī jau.

respektiivi kastei A ir timeout, juzris parcelas uz B un atpakal uz A vairs netiek celts ja A atgriežas. var taisīt kaut kādu load balansing, lai visi nesalien B kastē ...

patlaban visi dati glabājas tajā pašā memcache kurā sesija ja ? tad sanaak ka juzeris arii "izlogojas" ?

 

veel arī vienk sesijas var glabāt konstanti vienā kastē un citās kastees glabājas dati. tad var pie sesijas glabāt id, kurā kastē ir juuzera dati.

ja projekts nopietns, tad var vienk nopirkt vairākas kastes kurām ir ram (lai būtu failover) (te drosi vien ka der parastas desktop kastes.)

Link to comment
Share on other sites

  • 4 weeks later...

Jāpadarbojas nedaudz ar nekromanciju un jāatgriežas atkal pie problēmas risinājuma - vakar vienam memcache serverim sanāca pussprāgt.

 

@klez, mēs nevaram glabāt cookija info par to kurā memcachē atrodas vērtība, jo mēs paši nezinam - ir vienkārši klusters un consistent hashing algoritms, kas pats izvēlas kurā serverī rakstīt un meklēt info. par to web serverim nedodot nekādu info. Teorētiski varētu norādīt, lai katrs webserveris slēdzas klāt tikai vienam memcache serverim, bet tad zustu memcache clusterošanas jēga.

 

Tas ko mēs realizējām bija Kaklz ieteiktais risinājums - atslēgt failover un pārgājām uz consistent hashing algoritmu. Tas atrisināja problēmas, ka uz citiem serveriem saglabājas vecas vērtības, kuras varēja iegūt, ja primārais serveris nosprāga. Ar performanci, ja kaut viens no memcache serveriem darbojās lielas problēmas nav - īslaicīgi var pārdzīvot un salabot problēmu.

 

Bet vakar sastapāmies ar problēmu, ka viens un tas pats serveris nogļukoja īslaicīgi. Situācija šāda skatoties no viena lietotāja skatupunkta:

 

Sāka neatbildēt memcache B (vērtības netika iztīrītas no cache)

Pieprasījums 1 - nevarēja pieslēgties memcache serverim B un tapēc izvilka dažus datus no sql un updeitoja sql. Memcache A, C tika updeitota. Memcache B netika updeitota.

pēc vairākiem pieprasījumiem memcache B atgriezās

Pieprasījums 6 - pieslēdzās visiem memcache serveriem, no B saņēma vecas vērtības un viss aizgāja pa pieskari, jo ir noticis datu zudums. Ar A un C serveriem pēdējās vērtības, kas rada vēl sliktāku effektu, ka cilvēki ir iztērējuši kādas lietas un nav ieguvuši rezultātu vai otrādāk.

 

Pašlaik sākam skatīties uz Codez pieminēto 1o risinājumu par kādu monitoringa daemonu. Itkā ir Moxy, kas darbojas kā Proxy http://code.google.com/p/moxi/ un izskatās, ka var arī monitorēt cache stāvokli. Bet tad viņš izvērstos par single point of failure. Varbūt ir vēl kādas idejas?

Edited by Lynx
Link to comment
Share on other sites

Pēc labi daudz literatūras izlasīšanas un ārzemju forumu studēšanas, tika nospriests par šādu variantu, kas varbūt nav drošakais (rakstīt atsevišķu daemonu, kas to kontrolē), bet toties pilnībā kontrolējams PHP galā.

 

Memcache serveru konfigurāciju rakstīt atsevišķā konfigurācijas failā un, ja sastopamies ar kādu kļūdu piekonektējoties memcachei - tad pārakstam konfigurācijas failu ar php, norādot, ka šis serveris ir neaktīvs un lai nākamie pieprasījumi nemaz nemēģina uzreiz konektēties šim serverim. Tapēc, ka serveris ir flagots kā neaktīvs hash struktūra netiek izjaukta un citu serveru darbība netiek ietekmēta, jo failover ir atslēgts.

 

Paralēli tiek padota mums info, ka bija problēma - mēs atrisinam problēmu, iztīram visas vērtības un manuāli nomainam memcache konfigurāciju uz webserveriem. Lielāks čakars toties nekad nevajadzētu atgriezties novecojušām vērtībām.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...