Kutumia mcrouter kupima memcached mlalo

Kutumia mcrouter kupima memcached mlalo

Kuendeleza miradi yenye mzigo mkubwa katika lugha yoyote inahitaji mbinu maalum na matumizi ya zana maalum, lakini linapokuja suala la matumizi katika PHP, hali inaweza kuwa mbaya sana kwamba unapaswa kuendeleza, kwa mfano. seva ya programu yako mwenyewe. Katika dokezo hili tutazungumza juu ya maumivu yanayojulikana na uhifadhi wa kikao kilichosambazwa na uhifadhi wa data kwenye memcached na jinsi tulivyotatua matatizo haya katika mradi mmoja wa "kata".

Shujaa wa hafla hiyo ni programu ya PHP kulingana na mfumo wa symfony 2.3, ambayo haijajumuishwa kabisa katika mipango ya biashara ya kusasisha. Mbali na uhifadhi wa kawaida wa kipindi, mradi huu ulitumia kikamilifu sera ya "caching kila kitu". katika memcached: majibu kwa maombi kwa hifadhidata na seva za API, bendera mbalimbali, kufuli kwa ulandanishi wa utekelezaji wa msimbo na mengi zaidi. Katika hali kama hiyo, kuvunjika kwa memcached inakuwa mbaya kwa uendeshaji wa programu. Kwa kuongeza, kupoteza cache husababisha madhara makubwa: DBMS huanza kupasuka kwenye seams, huduma za API zinaanza kupiga marufuku maombi, nk. Kuimarisha hali kunaweza kuchukua makumi ya dakika, na wakati huu huduma itakuwa polepole sana au haipatikani kabisa.

Tulihitaji kutoa uwezo wa kusawazisha programu kwa usawa kwa bidii kidogo, i.e. na mabadiliko madogo kwa msimbo wa chanzo na utendakazi kamili umehifadhiwa. Fanya cache sio tu sugu kwa kushindwa, lakini pia jaribu kupunguza upotezaji wa data kutoka kwayo.

Ni nini kibaya na memcached yenyewe?

Kwa ujumla, kiendelezi cha memcached cha PHP kinaauni data iliyosambazwa na uhifadhi wa kikao nje ya boksi. Utaratibu wa hashing ya ufunguo thabiti hukuruhusu kuweka data kwa usawa kwenye seva nyingi, kushughulikia kwa kipekee kila ufunguo maalum kwa seva maalum kutoka kwa kikundi, na zana zilizojumuishwa ndani huhakikisha upatikanaji wa juu wa huduma ya kache (lakini, kwa bahati mbaya, hakuna data).

Mambo ni bora kidogo na uhifadhi wa kipindi: unaweza kusanidi memcached.sess_number_of_replicas, kama matokeo ambayo data itahifadhiwa kwenye seva kadhaa mara moja, na katika tukio la kushindwa kwa mfano mmoja wa memcached, data itahamishwa kutoka kwa wengine. Hata hivyo, ikiwa seva itarudi mtandaoni bila data (kama kawaida hutokea baada ya kuwasha upya), baadhi ya funguo zitasambazwa upya kwa niaba yake. Kwa kweli hii itamaanisha upotezaji wa data ya kikao, kwa kuwa hakuna njia ya "kwenda" kwa nakala nyingine ikiwa utakosa.

Zana za maktaba za kawaida zinalenga hasa mlalo kuongeza: hukuruhusu kuongeza kashe hadi saizi kubwa na kutoa ufikiaji wake kutoka kwa nambari iliyopangishwa kwenye seva tofauti. Hata hivyo, katika hali yetu, kiasi cha data iliyohifadhiwa haizidi gigabytes kadhaa, na utendaji wa nodes moja au mbili ni ya kutosha kabisa. Ipasavyo, zana muhimu pekee za kawaida zinaweza kuwa kuhakikisha upatikanaji wa memcached huku ukidumisha angalau tukio moja la akiba katika hali ya kufanya kazi. Hata hivyo, haikuwezekana kuchukua fursa ya fursa hii ... Hapa inafaa kukumbuka zamani za mfumo uliotumiwa katika mradi huo, ndiyo sababu haikuwezekana kupata maombi ya kufanya kazi na bwawa la seva. Pia tusisahau kuhusu upotevu wa data ya kipindi: jicho la mteja lililegea kutokana na utokaji mwingi wa watumiaji.

Kwa kweli ilihitajika urudufishaji wa rekodi katika nakala zilizohifadhiwa na kupitisha katika kesi ya kosa au kosa. Ilitusaidia kutekeleza mkakati huu mcrouter.

mcrouter

Hii ni kipanga njia cha memcached kilichotengenezwa na Facebook ili kutatua matatizo yake. Inasaidia itifaki ya maandishi ya memcached, ambayo inaruhusu punguza usakinishaji wa memcached kwa uwiano wa kichaa. Maelezo ya kina ya mcrouter yanaweza kupatikana ndani tangazo hili. Miongoni mwa mambo mengine utendakazi mpana inaweza kufanya kile tunachohitaji:

  • kuiga rekodi;
  • rudi nyuma kwa seva zingine kwenye kikundi ikiwa kosa litatokea.

Anza kazi!

usanidi wa mcrouter

Nitaenda moja kwa moja kwenye usanidi:

{
 "pools": {
   "pool00": {
     "servers": [
       "mc-0.mc:11211",
       "mc-1.mc:11211",
       "mc-2.mc:11211"
   },
   "pool01": {
     "servers": [
       "mc-1.mc:11211",
       "mc-2.mc:11211",
       "mc-0.mc:11211"
   },
   "pool02": {
     "servers": [
       "mc-2.mc:11211",
       "mc-0.mc:11211",
       "mc-1.mc:11211"
 },
 "route": {
   "type": "OperationSelectorRoute",
   "default_policy": "AllMajorityRoute|Pool|pool00",
   "operation_policies": {
     "get": {
       "type": "RandomRoute",
       "children": [
         "MissFailoverRoute|Pool|pool02",
         "MissFailoverRoute|Pool|pool00",
         "MissFailoverRoute|Pool|pool01"
       ]
     }
   }
 }
}

Kwa nini mabwawa matatu? Kwa nini seva zinarudiwa? Hebu tujue jinsi inavyofanya kazi.

  • Katika usanidi huu, mcrouter huchagua njia ambayo ombi litatumwa kulingana na amri ya ombi. Mwanaume anamwambia hivi OperationSelectorRoute.
  • PATA maombi nenda kwa kidhibiti RandomRouteambayo kwa nasibu huchagua dimbwi au njia kati ya vitu vya safu children. Kila kipengele cha safu hii kwa upande wake ni kidhibiti MissFailoverRoute, ambayo itapitia kila seva kwenye bwawa hadi itakapopokea jibu na data, ambayo itarejeshwa kwa mteja.
  • Ikiwa tulitumia pekee MissFailoverRoute na kundi la seva tatu, basi maombi yote yatakuja kwanza kwa mfano wa kwanza wa kumbukumbu, na wengine wangepokea maombi kwa msingi wa mabaki wakati hakuna data. Mbinu kama hiyo itasababisha mzigo mwingi kwenye seva ya kwanza kwenye orodha, kwa hivyo iliamuliwa kutoa mabwawa matatu na anwani katika mlolongo tofauti na kuwachagua kwa nasibu.
  • Maombi mengine yote (na hii ni rekodi) yanachakatwa kwa kutumia AllMajorityRoute. Kidhibiti hiki hutuma maombi kwa seva zote kwenye bwawa na husubiri majibu kutoka kwa angalau N/2 + 1 kati yao. Kutoka kwa matumizi AllSyncRoute kwa shughuli za kuandika zilipaswa kuachwa, kwa kuwa njia hii inahitaji majibu mazuri kutoka Kila seva kwenye kikundi - vinginevyo itarudi SERVER_ERROR. Ingawa mcrouter itaongeza data kwenye kache zinazopatikana, kazi ya kupiga simu ya PHP itarudisha kosa na itatoa taarifa. AllMajorityRoute sio kali sana na inaruhusu hadi nusu ya vitengo kuchukuliwa nje ya huduma bila matatizo yaliyoelezwa hapo juu.

Hasara kuu Mpango huu ni kwamba ikiwa hakuna data kwenye kashe, basi kwa kila ombi kutoka kwa mteja N maombi ya memcached yatatekelezwa - kwa kwa wote seva kwenye bwawa. Tunaweza kupunguza idadi ya seva kwenye mabwawa, kwa mfano, hadi mbili: kutoa dhabihu kuegemea kwa uhifadhi, tunapataΠΎkasi ya juu na mzigo mdogo kutoka kwa maombi hadi funguo zinazokosekana.

NB: Unaweza pia kupata viungo muhimu kwa ajili ya kujifunza mcrouter nyaraka kwenye wiki ΠΈ masuala ya mradi (ikiwa ni pamoja na zile zilizofungwa), zinazowakilisha ghala zima la usanidi mbalimbali.

Kujenga na kukimbia mcrouter

Maombi yetu (na memcached yenyewe) huendesha Kubernetes - ipasavyo, mcrouter pia iko hapo. Kwa mkusanyiko wa chombo tunatumia werf, usanidi ambao utaonekana kama hii:

NB: Orodha zilizotolewa katika makala zimechapishwa kwenye hifadhi flant/mcrouter.

configVersion: 1
project: mcrouter
deploy:
 namespace: '[[ env ]]'
 helmRelease: '[[ project ]]-[[ env ]]'
---
image: mcrouter
from: ubuntu:16.04
mount:
- from: tmp_dir
 to: /var/lib/apt/lists
- from: build_dir
 to: /var/cache/apt
ansible:
 beforeInstall:
 - name: Install prerequisites
   apt:
     name: [ 'apt-transport-https', 'tzdata', 'locales' ]
     update_cache: yes
 - name: Add mcrouter APT key
   apt_key:
     url: https://facebook.github.io/mcrouter/debrepo/xenial/PUBLIC.KEY
 - name: Add mcrouter Repo
   apt_repository:
     repo: deb https://facebook.github.io/mcrouter/debrepo/xenial xenial contrib
     filename: mcrouter
     update_cache: yes
 - name: Set timezone
   timezone:
     name: "Europe/Moscow"
 - name: Ensure a locale exists
   locale_gen:
     name: en_US.UTF-8
     state: present
 install:
 - name: Install mcrouter
   apt:
     name: [ 'mcrouter' ]

(werf.yaml)

... na kuchora nje Chati ya usukani. Jambo la kufurahisha ni kwamba kuna jenereta tu ya usanidi kulingana na idadi ya nakala (ikiwa kuna mtu ana chaguo zaidi laconic na kifahari, shiriki kwenye maoni):

{{- $count := (pluck .Values.global.env .Values.memcached.replicas | first | default .Values.memcached.replicas._default | int) -}}
{{- $pools := dict -}}
{{- $servers := list -}}
{{- /* ЗаполняСм  массив двумя копиями сСрвСров: "0 1 2 0 1 2" */ -}}
{{- range until 2 -}}
 {{- range $i, $_ := until $count -}}
   {{- $servers = append $servers (printf "mc-%d.mc:11211" $i) -}}
 {{- end -}}
{{- end -}}
{{- /* Π‘ΠΌΠ΅Ρ‰Π°ΡΡΡŒ ΠΏΠΎ массиву, ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ N срСзов: "[0 1 2] [1 2 0] [2 0 1]" */ -}}
{{- range $i, $_ := until $count -}}
 {{- $pool := dict "servers" (slice $servers $i (add $i $count)) -}}
 {{- $_ := set $pools (printf "MissFailoverRoute|Pool|pool%02d" $i) $pool -}}
{{- end -}}
---
apiVersion: v1
kind: ConfigMap
metadata:
 name: mcrouter
data:
 config.json: |
   {
     "pools": {{- $pools | toJson | replace "MissFailoverRoute|Pool|" "" -}},
     "route": {
       "type": "OperationSelectorRoute",
       "default_policy": "AllMajorityRoute|Pool|pool00",
       "operation_policies": {
         "get": {
           "type": "RandomRoute",
           "children": {{- keys $pools | toJson }}
         }
       }
     }
   }

(10-mcrouter.yaml)

Tunaiweka kwenye mazingira ya jaribio na angalia:

# php -a
Interactive mode enabled

php > # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ запись ΠΈ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅
php > $m = new Memcached();
php > $m->addServer('mcrouter', 11211);
php > var_dump($m->set('test', 'value'));
bool(true)
php > var_dump($m->get('test'));
string(5) "value"
php > # Π Π°Π±ΠΎΡ‚Π°Π΅Ρ‚! ВСстируСм Ρ€Π°Π±ΠΎΡ‚Ρƒ сСссий:
php > ini_set('session.save_handler', 'memcached');
php > ini_set('session.save_path', 'mcrouter:11211');
php > var_dump(session_start());
PHP Warning:  Uncaught Error: Failed to create session ID: memcached (path: mcrouter:11211) in php shell code:1
Stack trace:
#0 php shell code(1): session_start()
#1 {main}
  thrown in php shell code on line 1
php > # НС заводится… ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π·Π°Π΄Π°Ρ‚ΡŒ session_id:
php > session_id("zzz");
php > var_dump(session_start());
PHP Warning:  session_start(): Cannot send session cookie - headers already sent by (output started at php shell code:1) in php shell code on line 1
PHP Warning:  session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning:  session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning:  session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning:  session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning:  session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning:  session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning:  session_start(): Unable to clear session lock record in php shell code on line 1
PHP Warning:  session_start(): Failed to read session data: memcached (path: mcrouter:11211) in php shell code on line 1
bool(false)
php >

Kutafuta maandishi ya kosa hakutoa matokeo yoyote, lakini kwa swali "mcrouter php"Mbele ya mbele kulikuwa na shida ya zamani zaidi ambayo haijatatuliwa ya mradi - ukosefu wa msaada itifaki ya binary iliyofungwa.

NB: Itifaki ya ASCII katika memcached ni ya polepole zaidi kuliko ile ya binary, na njia za kawaida za hashing ya ufunguo thabiti hufanya kazi tu na itifaki ya binary. Lakini hii haileti shida kwa kesi maalum.

Ujanja uko kwenye begi: unachotakiwa kufanya ni kubadili itifaki ya ASCII na kila kitu kitafanya kazi.... Walakini, katika kesi hii, tabia ya kutafuta majibu ndani nyaraka kwenye php.net alicheza mzaha wa kikatili. Huwezi kupata jibu sahihi huko ... isipokuwa, bila shaka, unasonga hadi mwisho, ambapo katika sehemu "Maelezo yaliyochangiwa na mtumiaji" atakuwa mwaminifu na jibu lililopunguzwa kwa haki.

Ndiyo, jina la chaguo sahihi ni memcached.sess_binary_protocol. Ni lazima kuzimwa, baada ya hapo vikao vitaanza kufanya kazi. Kinachobaki ni kuweka chombo na mcrouter kwenye ganda na PHP!

Hitimisho

Kwa hivyo, kwa mabadiliko tu ya miundombinu tuliweza kutatua tatizo: suala la uvumilivu wa makosa ya memcached limetatuliwa, na uaminifu wa hifadhi ya cache imeongezeka. Mbali na faida dhahiri za programu, hii ilitoa nafasi ya ujanja wakati wa kufanya kazi kwenye jukwaa: wakati vifaa vyote vina hifadhi, maisha ya msimamizi hurahisishwa sana. Ndio, njia hii pia ina shida zake, inaweza kuonekana kama "crutch", lakini ikiwa inaokoa pesa, inazika shida na haisababishi mpya - kwa nini sivyo?

PS

Soma pia kwenye blogi yetu:

Chanzo: mapenzi.com

Kuongeza maoni