په افقی ډول د میم کیچ اندازه کولو لپاره د میکروټر کارول

په افقی ډول د میم کیچ اندازه کولو لپاره د میکروټر کارول

په هره ژبه کې د لوړ بار پروژې رامینځته کول ځانګړي چلند او ځانګړي وسیلو کارولو ته اړتیا لري ، مګر کله چې دا په PHP کې غوښتنلیکونو ته راځي ، وضعیت دومره خراب کیدی شي چې تاسو باید وده وکړئ ، د مثال په توګه ، د خپل غوښتنلیک سرور. پدې یادښت کې به موږ د توزیع شوي سیشن ذخیره کولو سره د پیژندل شوي درد په اړه وغږیږو او په memcached کې د ډیټا کیشینګ او څنګه موږ دا ستونزې په یوه "وارډ" پروژه کې حل کړې.

د غونډې اتل د سیمفوني 2.3 چوکاټ پراساس د PHP غوښتنلیک دی ، کوم چې د تازه کولو سوداګرۍ پلانونو کې شامل ندي. د کافي معیاري سیشن ذخیره کولو سربیره ، دې پروژې بشپړه ګټه پورته کړې "د هرڅه زیرمه کول" پالیسي په memcached کې: ډیټابیس او API سرورونو ته غوښتنو ته ځوابونه ، مختلف بیرغونه ، د کوډ اجرا کولو همغږي کولو لپاره لاکونه او نور ډیر څه. په داسې حالت کې، د میمکیچ ماتول د غوښتنلیک عملیات لپاره وژونکي کیږي. برسېره پردې، د کیچ ضایع د جدي پایلو المل کیږي: DBMS په سیمونو کې د مینځلو پیل کوي، د API خدمتونه د غوښتنو بندیز پیل کوي، او داسې نور. د وضعیت ثبات ممکن لسګونه دقیقې وخت ونیسي، او پدې وخت کې به خدمت خورا ورو یا په بشپړه توګه شتون ونلري.

موږ باید چمتو کړو د لږې هڅې سره د غوښتنلیک افقی اندازه کولو وړتیا, i.e. د سرچینې کوډ کې لږترلږه بدلونونو سره او بشپړ فعالیت ساتل شوی. کیچ نه یوازې د ناکامۍ په وړاندې مقاومت وکړئ، بلکې هڅه وکړئ چې د دې څخه د معلوماتو ضایع کم کړئ.

پخپله memcached کې څه ستونزه ده؟

په عموم کې، د پی ایچ پی لپاره میمکیچ شوی توسیع د بکس څخه بهر توزیع شوي ډاټا او سیشن ذخیره ملاتړ کوي. د دوامداره کیلي هش کولو میکانیزم تاسو ته اجازه درکوي په مساوي ډول په ډیری سرورونو کې ډیټا ځای په ځای کړئ ، په ځانګړي ډول د ګروپ څخه یو ځانګړي سرور ته هر ځانګړي کیلي په ګوته کوي ، او د ناکامۍ رامینځته شوي وسیلې د کیچنګ خدمت لوړه شتون تضمینوي (مګر له بده مرغه ، هیڅ معلومات نشته).

د سیشن ذخیره کولو سره شیان یو څه ښه دي: تاسو کولی شئ تنظیم کړئ memcached.sess_number_of_replicas، د دې په پایله کې چې ډاټا به په یوځل کې په څو سرورونو کې زیرمه شي ، او د یوې میمکیچ شوي مثال د ناکامۍ په صورت کې ، ډاټا به له نورو څخه لیږدول کیږي. په هرصورت، که چیرې سرور د معلوماتو پرته بیرته آنلاین راشي (لکه څنګه چې معمولا د بیا پیل کولو وروسته پیښیږي)، ځینې کیلي به د هغې په ګټه بیا توزیع شي. په حقیقت کې دا به معنی ولري د غونډې د معلوماتو له لاسه ورکول، ځکه چې د ورکیدو په صورت کې بل نقل ته د "تلو" لپاره هیڅ لاره نشته.

د معیاري کتابتون وسیلې په عمده توګه هدف دي افقي اندازه کول: دوی تاسو ته اجازه درکوي چې کیچ لوی اندازې ته لوړ کړي او په مختلف سرورونو کې کوربه شوي کوډ څخه ورته لاسرسی چمتو کړي. په هرصورت، زموږ په وضعیت کې، د ذخیره شوي معلوماتو حجم د څو ګیګابایټ څخه ډیر نه دی، او د یو یا دوه نوډونو فعالیت کافي دی. په دې اساس، یوازینی ګټور معیاري وسیلې کیدی شي د میم کیچ شتون ډاډمن کړي پداسې حال کې چې لږترلږه یو کیچ مثال په کاري حالت کې ساتل کیږي. په هرصورت، دا ممکنه نه وه چې حتی د دې فرصت څخه ګټه پورته کړئ ... دلته دا د یادولو وړ ده چې په پروژه کې کارول شوي چوکاټ لرغونتوب، له همدې امله د سرورونو د حوض سره کار کولو لپاره د غوښتنلیک ترلاسه کول ناممکن وو. راځئ چې د سیشن ډیټا له لاسه ورکولو په اړه هم هیر نکړو: د پیرودونکي سترګې د کاروونکو لوی لاګ آوټ څخه راوتلې.

په مثالي توګه دا اړینه وه د ریکارډونو نقل کول په یاد شوي او بای پاس کولو ریپلیکسونو کې د خطا یا خطا په صورت کې. موږ سره د دې ستراتیژۍ په پلي کولو کې مرسته وکړه mcrouter.

mcrouter

دا یو میمکیچ شوی روټر دی چې د فیسبوک لخوا رامینځته شوی ترڅو خپلې ستونزې حل کړي. دا د memcached متن پروتوکول ملاتړ کوي، کوم چې اجازه ورکوي پیمانه memcached نصبونه د لیونتوب تناسب ته. د میکروټر تفصیلي توضیحات په کې موندل کیدی شي دا اعلان. د نورو شیانو په منځ کې پراخه فعالیت دا کولی شي هغه څه وکړي چې موږ ورته اړتیا لرو:

  • د ریکارډ نقل کول؛
  • که کومه تېروتنه رامنځته شي په ګروپ کې نورو سرورونو ته بیرته راستون شئ.

کار ته رسیدل!

د مایکروټر ترتیب

زه به مستقیم ترتیب ته لاړ شم:

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

ولې درې حوضونه؟ ولې سرورونه تکرار کیږي؟ راځئ چې معلومه کړو چې دا څنګه کار کوي.

  • پدې ترتیب کې ، میکروټر هغه لاره غوره کوي چې غوښتنه به یې د غوښتنې کمانډ پراساس لیږل کیږي. سړی ورته وايي OperationSelectorRoute.
  • د GET غوښتنې سمبالونکي ته ځي RandomRouteکوم چې په تصادفي ډول د سري شیانو تر مینځ پول یا لاره غوره کوي children. د دې صف هر عنصر په بدل کې یو سمبالونکی دی MissFailoverRoute، کوم چې به په حوض کې د هر سرور له لارې تیریږي تر هغه چې دا د معلوماتو سره ځواب ترلاسه کړي ، کوم چې پیرودونکي ته به بیرته راستون شي.
  • که موږ په ځانګړې توګه کارول MissFailoverRoute د دریو سرورونو د حوض سره، بیا ټولې غوښتنې به لومړی د میم کیچ شوي مثال ته راشي، او پاتې به د پاتې کیدو په اساس غوښتنې ترلاسه کړي کله چې هیڅ معلومات شتون نلري. دا ډول چلند به لامل شي په لیست کې په لومړي سرور کې ډیر بار، نو دا پریکړه وشوه چې درې حوضونه په مختلف ترتیبونو کې د ادرسونو سره رامینځته کړئ او په تصادفي ډول یې غوره کړئ.
  • نورې ټولې غوښتنې (او دا یو ریکارډ دی) په کارولو سره پروسس کیږي AllMajorityRoute. دا سمبالونکی په حوض کې ټولو سرورونو ته غوښتنې لیږي او لږترلږه د N/2 + 1 څخه ځوابونو ته انتظار کوي. د کارولو څخه AllSyncRoute د لیکلو عملیات باید پریښودل شي، ځکه چې دا طریقه مثبت ځواب ته اړتیا لري всех په ګروپ کې سرورونه - که نه نو دا به بیرته راشي SERVER_ERROR. که څه هم مایکروټر به موجود کیچونو کې ډاټا اضافه کړي ، د PHP فعالیت زنګ وهي یوه تېروتنه به راګرځوي او خبرتیا به پیدا کړي. AllMajorityRoute دومره سخت نه دی او اجازه ورکوي تر نیمایي پورې واحدونه پرته له دې چې پورته بیان شوي ستونزې له خدمت څخه لرې شي.

اصلي زیان دا سکیم دا دی چې که چیرې واقعیا په زیرمه کې هیڅ معلومات شتون نلري ، نو د پیرودونکي څخه د هرې غوښتنې لپاره N میم کیچ ته غوښتنې به واقعیا اجرا شي - ته ټول ته په حوض کې سرورونه. موږ کولی شو په حوضونو کې د سرورونو شمیر کم کړو، د بیلګې په توګه، دوه ته: د ذخیره کولو اعتبار قرباني کول، موږ ترلاسه کووоلوړ سرعت او لږ بار له غوښتنو څخه ورک شوي کیلي ته.

NB: تاسو ممکن د مایکروټر زده کړې لپاره ګټور لینکونه هم ومومئ په ويکي کې اسناد и د پروژې مسلې (د تړلو په شمول)، د مختلفو ترتیباتو بشپړ ذخیره نمایندګي کوي.

د میکروټر جوړول او چلول

زموږ غوښتنلیک (او پخپله memcached) په Kubernetes کې پرمخ ځي - په وینا، میکروټر هم هلته موقعیت لري. لپاره کانتینر مجلس موږ یی استعمالوو werf، هغه تشکیل چې د دې لپاره به ورته ښکاري:

NB: په مقاله کې ورکړل شوي لیستونه په ذخیره کې خپاره شوي فلانټ/مکروټر.

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)

... او خاکه یې راوباسه د هیلم چارټ. په زړه پورې خبره دا ده چې د عکسونو شمیر پراساس یوازې یو ترتیب جنراتور شتون لري (که څوک ډیر لیونیک او په زړه پوری اختیار ولري، په نظرونو کې یې شریک کړئ):

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

موږ دا د ازموینې چاپیریال ته واړوو او وګورو:

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

د خطا د متن لټون کومه پایله نه ده ورکړې، مګر د پوښتنې لپاره "مایکروټر پی ایچ پی"په سر کې د پروژې ترټولو پخوانۍ نا حل شوې ستونزه وه - د ملاتړ نشتوالی memcached بائنری پروتوکول.

NB: په memcached کې د ASCII پروتوکول د بائنری په پرتله ورو دی، او د دوامداره کیلي هش کولو معیاري وسیله یوازې د بائنری پروتوکول سره کار کوي. مګر دا د یوې ځانګړې قضیې لپاره ستونزې نه رامینځته کوي.

چال په کڅوړه کې دی: ټول هغه څه چې تاسو یې باید وکړئ د ASCII پروتوکول ته لاړشئ او هرڅه به کار وکړي .... په هرصورت، پدې حالت کې، د ځوابونو په لټه کې عادت په php.net کې اسناد یوه ظالمانه ټوکه وکړه. تاسو به هلته سم ځواب ونه مومئ ... پرته لدې چې ، البته ، تاسو پای ته سکرول کړئ ، چیرې چې برخه کې وي "د کارونکي مرسته شوي یادښتونه" وفادار به وي په غیر عادلانه ډول رد شوی ځواب.

هو، د سم انتخاب نوم دی memcached.sess_binary_protocol. دا باید غیر فعال وي، وروسته لدې چې ناستې به کار پیل کړي. ټول هغه څه چې پاتې دي د مایکروټر سره کانټینر د PHP سره پوډ ته واچوئ!

پایلې

په دې توګه، یوازې د زیربنایي بدلونونو سره موږ د دې توان درلود چې ستونزه حل کړو: د memcached غلطی زغم مسله حل شوې، او د کیچ ذخیره کولو اعتبار ډیر شوی. د غوښتنلیک لپاره د څرګندو ګټو سربیره، دا په پلیټ فارم کې د کار کولو په وخت کې د چلولو لپاره ځای ورکړ: کله چې ټولې برخې ریزرو ولري، د مدیر ژوند خورا ساده دی. هو، دا طریقه هم خپل نیمګړتیاوې لري، دا ممکن د "کرچ" په څیر ښکاري، مګر که دا پیسې خوندي کړي، ستونزه له منځه یوسي او د نوي لامل نه شي - ولې نه؟

PS

زموږ په بلاګ کې هم ولولئ:

سرچینه: www.habr.com

Add a comment