Gigamit ang mcrouter aron i-scale ang memcached nga pinahigda

Gigamit ang mcrouter aron i-scale ang memcached nga pinahigda

Ang pag-uswag sa mga proyekto nga adunay taas nga karga sa bisan unsang sinultian nanginahanglan usa ka espesyal nga pamaagi ug paggamit sa mga espesyal nga himan, apan kung bahin sa mga aplikasyon sa PHP, ang kahimtang mahimo’g modako pag-ayo nga kinahanglan nimo nga pauswagon, pananglitan, kaugalingon nga server sa aplikasyon. Niini nga nota, maghisgot kami bahin sa kasakit nga pamilyar sa tanan nga adunay giapod-apod nga pagtipig sa mga sesyon ug data caching sa memcached ug giunsa namo pagsulbad kini nga mga problema sa usa ka "ward" nga proyekto.

Ang bayani sa okasyon usa ka aplikasyon sa PHP nga gibase sa symfony 2.3 nga balangkas, nga wala gilakip sa mga plano sa negosyo nga i-update sa tanan. Dugang pa sa medyo standard nga pagtipig sa mga sesyon, kini nga proyekto hingpit nga gigamit "i-cache ang tanan" nga palisiya sa memcached: mga tubag sa mga hangyo sa database ug API server, lain-laing mga bandila, mga kandado alang sa pag-synchronize sa pagpatuman sa code, ug daghan pa. Sa ingon nga kahimtang, ang usa ka memcached break mahimong makamatay alang sa aplikasyon nga molihok. Dugang pa, ang pagkawala sa cache nagdala sa seryoso nga mga sangputanan: ang DBMS nagsugod sa pagbuto sa mga seams, ang mga serbisyo sa API nagsugod sa pagdili sa mga hangyo, ug uban pa. Mahimong mokabat ug napulo ka minuto aron ma-stabilize ang sitwasyon, diin ang serbisyo mohinay pag-ayo o mahimong dili magamit.

Kinahanglan namon nga maghatag ang posibilidad sa horizontal scaling sa aplikasyon nga adunay gamay nga pagpaagas sa dugo, i.e. nga adunay gamay nga pagbag-o sa source code ug bug-os nga gamit. Himoa nga ang cache dili lamang fault-tolerant, apan sulayi usab nga mamenosan ang pagkawala sa datos gikan niini.

Unsa ang sayup sa memcached mismo?

Sa kinatibuk-an, ang memcached extension alang sa PHP out of the box nagsuporta sa giapod-apod nga pagtipig sa datos ug mga sesyon. Ang mekanismo sa makanunayon nga pag-hash sa mga yawe nagtugot kanimo nga parehas nga ibutang ang datos sa daghang mga server, talagsaon nga pagtubag sa matag piho nga yawe sa usa ka piho nga server gikan sa grupo, ug ang mga built-in nga failover nga mga himan nagsiguro nga taas ang pagkaanaa sa serbisyo sa caching (apan, sa kasubo, walay data).

Uban sa pagtipig sa sesyon, ang mga butang mas maayo: mahimo nimong i-configure memcached.sess_number_of_replicas, ingon usa ka sangputanan diin ang datos ma-save sa daghang mga server sa usa ka higayon, ug kung mapakyas ang usa ka pananglitan sa memcached, ang datos ihatag gikan sa uban. Bisan pa, kung ang server mobalik online nga wala’y datos (sama sa kasagaran nga mahitabo pagkahuman sa pag-restart), pipila sa mga yawe ipanghatag pag-usab pabor niini. Sa pagkatinuod, kini magpasabot pagkawala sa datos sa sesyon, tungod kay wala'y paagi sa "pag-adto" sa lain nga replika kung adunay masipyat.

Ang sukaranan nga mga himan sa librarya gitumong sa panguna pinahigda pag-scale: gitugotan ka nila nga madugangan ang cache sa daghang mga gidak-on ug hatagan kini pag-access gikan sa code nga gi-host sa lainlaing mga server. Bisan pa, sa among kahimtang, ang kantidad sa gitipig nga datos dili molapas sa daghang mga gigabytes, ug ang paghimo sa usa o duha nga mga node igo na. Tungod niini, gikan sa usa ka mapuslanon nga regular nga paagi, mahimo ra nila masiguro ang pagkaanaa sa memcached samtang gipadayon ang labing menos usa ka higayon sa cache sa kahimtang sa pagtrabaho. Bisan pa, bisan kini nga oportunidad wala gipahimuslan ... Dinhi kinahanglan naton hinumdoman ang karaan nga balangkas nga gigamit sa proyekto, mao nga dili posible nga himuon ang aplikasyon nga magamit sa usa ka pool sa mga server. Dili usab nato kalimtan ang bahin sa pagkawala sa datos sa sesyon: ang mata sa kustomer mikibot gikan sa daghang pag-logout sa mga tiggamit.

Sa tinuud, gikinahanglan kini memcached entry replication ug bypassing replicas kung adunay sayup o sayup. Nakatabang kanamo sa pagpatuman niini nga estratehiya microuter.

microuter

Kini usa ka memcached router nga gihimo sa Facebook aron masulbad ang ilang mga problema. Gisuportahan niini ang memcached text protocol, nga nagtugot scale memcached nga mga instalasyon sa buang nga proporsyon. Ang usa ka detalyado nga paghulagway sa mcrouter makita sa kini nga pahibalo. Dugang pa sa uban lapad nga pagpaandar mahimo niya ang atong gikinahanglan:

  • kopyaha ang rekord;
  • paghimo usa ka fallback sa ubang mga server sa grupo kung adunay sayup.

Para sa negosyo!

configuration sa mcrouter

Deretso ta sa config:

{
 "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"
       ]
     }
   }
 }
}

Nganong tulo ka pool? Ngano nga ang mga server gisubli? Atong tan-awon kon sa unsang paagi kini molihok.

  • Niini nga pag-configure, gipili sa mcrouter ang agianan diin ipadala ang hangyo base sa mando sa hangyo. Ang tipo nagsulti kaniya bahin niini OperationSelectorRoute.
  • GET hangyo moadto sa handler RandomRoute, nga random nga nagpili sa usa ka pool o ruta taliwala sa mga butang nga laray children. Ang matag elemento niini nga array kay usa ka handler MissFailoverRoute, nga nagbalikbalik sa matag server sa pool hangtod nga makadawat kini usa ka tubag nga adunay datos, nga gibalik sa kliyente.
  • Kung gigamit lang nato MissFailoverRoute nga adunay usa ka pool sa tulo ka mga server, unya ang tanan nga mga hangyo moabut una sa una nga higayon sa memcached, ug ang uban makadawat mga hangyo sa usa ka nahabilin nga basehan kung wala’y datos. Ang ingon nga pamaagi motultol sa sobra nga load sa unang server sa listahan, mao nga nakahukom nga makamugna og tulo ka pool nga adunay mga adres sa lain-laing han-ay ug pilion kini nga random.
  • Ang tanan nga ubang mga hangyo (ug kini usa ka rekord) giproseso gamit AllMajorityRoute. Kini nga handler nagpadala sa mga hangyo sa tanan nga mga server sa pool ug naghulat alang sa mga tubag gikan sa labing menos N/2 + 1 niini. Gikan sa paggamit AllSyncRoute alang sa pagsulat nga mga operasyon kinahanglan nga biyaan, tungod kay kini nga pamaagi nanginahanglan usa ka positibo nga tubag gikan sa sa tanan mga server sa grupo - kung dili kini mobalik SERVER_ERROR. Bisan kung idugang sa mcrouter ang datos sa magamit nga mga cache, ang function sa pagtawag sa PHP mubalik ug sayop ug paghimo og pahibalo. AllMajorityRoute dili kaayo estrikto ug nagtugot sa decommissioning hangtod sa katunga sa mga yunit nga wala ang mga problema nga gihulagway sa ibabaw.

Panguna nga disbentaha Kini nga laraw mao nga kung wala’y datos sa cache, nan alang sa matag hangyo gikan sa kliyente, ang N nga hangyo sa memcached ipatuman gyud - nga sa tanan mga server sa pool. Mahimo nimong pakunhuran ang gidaghanon sa mga server sa mga pool, pananglitan, sa duha: pagsakripisyo sa kasaligan sa pagtipig, makuha namon ang bоMas kusog ug gamay nga load gikan sa mga hangyo alang sa nawala nga mga yawe.

NB: Mapuslanon nga mga link alang sa pagkat-on sa mcrouter mahimo usab dokumentasyon sa wiki и mga isyu sa proyekto (lakip ang mga sirado), nga nagrepresentar sa usa ka tibuuk nga balay tipiganan sa lainlaing mga pag-configure.

Pagtukod ug pagpadagan sa mcrouter

Ang aplikasyon (ug memcached mismo) nagtrabaho alang kanamo sa Kubernetes - sumala niana, naa usab ang mcrouter. Alang sa asembliya sa sudlanan gigamit namon werf, ang config nga tan-awon sama niini:

NB: Ang mga listahan nga gihatag sa artikulo gimantala sa repositoryo 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)

... ug ilabay Helm nga tsart. Sa makaiikag - ania ra ang usa ka config generator gikan sa gidaghanon sa mga replika (kung adunay usa nga adunay usa ka labi ka mubo ug elegante nga bersyon - ipaambit sa mga komento):

{{- $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)

Naglihok kami sa palibot sa pagsulay ug gisusi:

# 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 >

Ang pagpangita alang sa teksto sa sayup wala maghatag bisan unsang resulta, bisan pa, ang pangutana "microuter php» sa unahan mao ang labing karaan nga wala masulbad nga problema sa proyekto - kakulang sa suporta binary memcached protocol.

NB: Ang ASCII protocol sa memcached mas hinay kay sa binary, ug ang standard nga paagi sa makanunayon nga key hashing nagtrabaho lamang sa binary protocol. Apan wala kini maghimo mga problema alang sa usa ka partikular nga kaso.

Anaa kini sa bag: kini nagpabilin lamang sa pagbalhin sa ASCII protocol ug ang tanan molihok .... Bisan pa, sa kini nga kaso, ang batasan sa pagpangita sa mga tubag sa dokumentasyon sa php.net nagdula og mapintas nga komedya. Dili nimo makit-an ang husto nga tubag didto ... gawas kung, siyempre, mag-scroll ka hangtod sa katapusan, kung diin sa seksyon "Mga Tala nga Gitampo sa Gumagamit" mahimong tinuod ug dili patas nga downvoted nga tubag.

Oo, ang husto nga ngalan sa kapilian mao memcached.sess_binary_protocol. Kinahanglan nga kini dili ma-disable, pagkahuman ang mga sesyon magsugod sa pagtrabaho. Nagpabilin lamang nga ibutang ang sudlanan nga adunay mcrouter sa pod nga adunay PHP!

konklusyon

Busa, sa mga pagbag-o lamang sa imprastraktura, nakahimo kami sa pagsulbad sa buluhaton: ang isyu sa memcached fault tolerance nasulbad na, ang kasaligan sa pagtipig sa cache nadugangan. Dugang pa sa dayag nga mga bentaha alang sa aplikasyon, naghatag kini og luna alang sa pagmaniobra sa pagtrabaho sa plataporma: kung ang tanan nga mga sangkap adunay reserba, ang kinabuhi sa tagdumala gipasimple kaayo. Oo, kini nga pamaagi adunay mga kakulian, kini mahimong tan-awon sama sa usa ka "saklay", apan kung kini makatipig salapi, gilubong ang problema ug dili hinungdan sa mga bag-o - nganong dili?

PS

Basaha usab sa among blog:

Source: www.habr.com

Idugang sa usa ka comment