Nggunakake mcrouter kanggo skala memcached horisontal

Nggunakake mcrouter kanggo skala memcached horisontal

Ngembangake proyek kanthi beban dhuwur ing basa apa wae mbutuhake pendekatan khusus lan nggunakake alat khusus, nanging nalika nerangake aplikasi ing PHP, kahanan bisa saya tambah akeh, mula sampeyan kudu ngembangake, contone, server aplikasi dhewe. Ing cathetan iki kita bakal pirembagan bab pain menowo karo panyimpenan sesi mbagekke lan data caching ing memcached lan carane kita ditanggulangi masalah iki ing siji project "bangsal".

Pahlawan acara kasebut yaiku aplikasi PHP adhedhasar kerangka kerja symfony 2.3, sing ora kalebu ing rencana bisnis kanggo nganyari. Saliyane panyimpenan sesi sing cukup standar, proyek iki digunakake kanthi lengkap kebijakan "caching kabeh". ing memcached: nanggepi panjalukan kanggo database lan server API, macem-macem panji, kunci kanggo nyinkronake eksekusi kode lan akeh liyane. Ing kahanan kaya mengkono, risak saka memcached dadi fatal kanggo operasi aplikasi. Kajaba iku, mundhut cache ndadékaké kanggo jalaran serius: DBMS wiwit bledosan ing lapisan, layanan API wiwit ban panjalukan, etc. Stabilisasi kahanan bisa njupuk puluhan menit, lan sajrone wektu iki layanan bakal alon banget utawa ora kasedhiya.

We needed kanggo nyedhiyani kemampuan kanggo horisontal ukuran aplikasi karo sethitik gaweyan, i.e. karo owah-owahan minimal kanggo kode sumber lan fungsi lengkap wadi. Nggawe cache ora mung tahan kanggo gagal, nanging uga nyoba kanggo nyilikake mundhut data saka iku.

Apa salah karo memcached dhewe?

Umumé, ekstensi memcached kanggo PHP ndhukung data sing disebarake lan panyimpenan sesi metu saka kothak. Mekanisme kanggo hashing tombol konsisten ngijini sampeyan kanggo nyebarake data roto-roto ing akeh server, unik ngarahake saben tombol tartamtu menyang server tartamtu saka grup, lan dibangun ing piranti failover njamin kasedhiyan dhuwur saka layanan caching (nanging, sayangé, ora ana data).

Iku luwih apik karo panyimpenan sesi: sampeyan bisa ngatur memcached.sess_number_of_replicas, minangka asil saka data bakal disimpen ing sawetara server bebarengan, lan ing acara saka Gagal siji Kayata memcached, data bakal ditransfer saka liyane. Nanging, yen server bali online tanpa data (kaya biasane kedadeyan sawise miwiti maneh), sawetara tombol bakal disebarake maneh. Ing kasunyatan iki bakal tegese mundhut data sesi, amarga ora ana cara kanggo "pindhah" menyang tiron liyane ing cilik saka miss.

piranti perpustakaan standar ngarahke utamané ing horisontal njongko: padha ngijini sampeyan kanggo nambah cache kanggo ukuran gigantic lan nyedhiyani akses menyang saka kode tuan rumah ing server beda. Nanging, ing kahanan kita, volume data sing disimpen ora ngluwihi sawetara gigabyte, lan kinerja siji utawa loro simpul cukup cukup. Dadi, mung alat standar sing migunani kanggo mesthekake kasedhiyan memcached nalika njaga paling ora siji conto cache ing kondisi kerja. Nanging, iku ora bisa kanggo njupuk kauntungan saka malah kesempatan iki. Ayo uga ora lali babagan kelangan data sesi: mripat pelanggan kedutan saka logout pangguna sing akeh.

Saenipun dibutuhake replikasi cathetan ing replika memcached lan bypassing menawi wonten kalepatan utawi kalepatan. Mbantu kita ngetrapake strategi iki mcrouter.

mcrouter

Iki minangka router memcached sing dikembangake dening Facebook kanggo ngatasi masalah kasebut. Ndhukung protokol teks memcached, sing ngidini panginstalan memcached skala kanggo proporsi edan. Katrangan rinci babagan mcrouter bisa ditemokake ing pengumuman iki. Antarane liyane fungsi sudhut bisa nindakake apa sing kita butuhake:

  • replikasi rekaman;
  • apa fallback menyang server liyane ing grup yen ana kesalahan.

Kanggo bisnis!

konfigurasi mcrouter

Aku bakal langsung menyang konfigurasi:

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

Napa telung blumbang? Kenapa server diulang? Ayo dipikirake cara kerjane.

  • Ing konfigurasi iki, mcrouter milih path sing bakal dikirim panjalukan adhedhasar printah request. Wong lanang iki ngomong marang dheweke OperationSelectorRoute.
  • Panjaluk GET menyang pawang RandomRoutekang acak milih blumbang utawa rute antarane obyek Uploaded children. Saben unsur saka array iki minangka pawang MissFailoverRoute, sing bakal ngliwati saben server ing blumbang nganti nampa respon karo data, sing bakal bali menyang klien.
  • Yen kita digunakake istimewa MissFailoverRoute karo blumbang telung server, banjur kabeh panjalukan bakal teka pisanan kanggo Kayata memcached pisanan, lan liyane bakal nampa panjalukan ing basis ampas nalika ora ana data. Pendekatan kuwi bakal mimpin kanggo mbukak gedhe banget ing server pisanan ing dhaftar, mula diputusake ngasilake telung pool kanthi alamat ing urutan sing beda-beda lan pilih kanthi acak.
  • Kabeh panjalukan liyane (lan iki rekaman) diproses nggunakake AllMajorityRoute. Handler iki ngirim panjalukan kanggo kabeh server ing blumbang lan ngenteni respon saka paling N / 2 + 1 mau. Saka nggunakake AllSyncRoute kanggo operasi nulis kudu nilar, wiwit cara iki mbutuhake respon positif saka всех server ing grup - digunakake bakal bali SERVER_ERROR. Sanajan mcrouter bakal nambah data menyang cache sing kasedhiya, fungsi PHP nelpon bakal ngasilake kesalahan lan bakal ngasilake kabar. AllMajorityRoute ora ketat lan ngidini nganti setengah saka unit bisa dicopot saka layanan tanpa masalah sing diterangake ing ndhuwur.

Kerugian utama Skema iki yaiku yen ora ana data ing cache, mula saben panjaluk saka klien N njaluk memcached bakal ditindakake - kanggo kanggo kabeh server ing blumbang. Kita bisa nyuda jumlah server ing blumbang, contone, dadi loro: ngorbanake linuwih panyimpenan, kita entukоkacepetan luwih lan kurang mbukak saka panjalukan kanggo tombol ilang.

NB: Sampeyan uga bisa nemokake pranala migunani kanggo sinau mcrouter dokumentasi ing wiki и masalah proyek (kalebu sing ditutup), makili kabeh gudang saka macem-macem konfigurasi.

Bangunan lan mlaku mcrouter

Aplikasi kita (lan memcached dhewe) mlaku ing Kubernetes - kanthi mangkono, mcrouter uga ana ing kana. Kanggo ngrakit wadhah kita nggunakake werf, konfigurasi sing bakal katon kaya iki:

NB: Daftar sing diwenehake ing artikel kasebut diterbitake ing gudang flant / microuter.

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)

... lan gawe sketsa Bagan helm. Sing menarik yaiku mung ana generator konfigurasi adhedhasar jumlah replika (Yen ana sing duwe pilihan sing luwih laconic lan elegan, nuduhake ing komentar):

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

Kita muter metu menyang lingkungan test lan mriksa:

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

Nggoleki teks kesalahan ora menehi asil, nanging pitakon "mcrouter php"Ing ngarep ana masalah paling tuwa sing durung rampung ing proyek kasebut - kurang dhukungan protokol binar memcached.

NB: Protokol ASCII ing memcached luwih alon tinimbang sing binar, lan cara standar hashing tombol sing konsisten mung bisa digunakake karo protokol binar. Nanging iki ora nggawe masalah kanggo kasus tartamtu.

Trik kasebut ana ing tas: sampeyan mung kudu ngalih menyang protokol ASCII lan kabeh bakal bisa .... Nanging, ing kasus iki, pakulinan nggoleki jawaban ing dokumentasi ing php.net main guyon kejem. Sampeyan ora bakal nemokake jawaban sing bener ana ... kajaba, mesthi, sampeyan gulung menyang mburi, ngendi ing bagean "Cathetan kontribusi pangguna" bakal setya lan jawaban unfairly downvoted.

Ya, jeneng pilihan sing bener yaiku memcached.sess_binary_protocol. Sampeyan kudu dipateni, sawise sesi kasebut bakal digunakake. Kabeh sing isih ana yaiku nyelehake wadhah nganggo mcrouter menyang pod nganggo PHP!

kesimpulan

Mangkono, kanthi mung owah-owahan infrastruktur kita bisa ngatasi masalah: masalah karo toleransi fault memcached wis ditanggulangi, lan linuwih panyimpenan cache wis tambah. Saliyane kaluwihan sing jelas kanggo aplikasi kasebut, iki menehi ruang kanggo maneuver nalika nggarap platform: nalika kabeh komponen duwe cadangan, urip administrator wis disederhanakake. Ya, cara iki uga duwe kekurangan, bisa uga katon kaya "kruk", nanging yen ngirit dhuwit, ngubur masalah lan ora nyebabake sing anyar - kenapa ora?

PS

Waca uga ing blog kita:

Source: www.habr.com

Add a comment