
په هره ژبه کې د لوړ بار پروژې رامینځته کول ځانګړي چلند او ځانګړي وسیلو کارولو ته اړتیا لري ، مګر کله چې دا په PHP کې غوښتنلیکونو ته راځي ، وضعیت دومره خراب کیدی شي چې تاسو باید وده وکړئ ، د مثال په توګه ، . پدې یادښت کې به موږ د توزیع شوي سیشن ذخیره کولو سره د پیژندل شوي درد په اړه وغږیږو او په memcached کې د ډیټا کیشینګ او څنګه موږ دا ستونزې په یوه "وارډ" پروژه کې حل کړې.
د غونډې اتل د سیمفوني 2.3 چوکاټ پراساس د PHP غوښتنلیک دی ، کوم چې د تازه کولو سوداګرۍ پلانونو کې شامل ندي. د کافي معیاري سیشن ذخیره کولو سربیره ، دې پروژې بشپړه ګټه پورته کړې "د هرڅه زیرمه کول" پالیسي په memcached کې: ډیټابیس او API سرورونو ته غوښتنو ته ځوابونه ، مختلف بیرغونه ، د کوډ اجرا کولو همغږي کولو لپاره لاکونه او نور ډیر څه. په داسې حالت کې، د میمکیچ ماتول د غوښتنلیک عملیات لپاره وژونکي کیږي. برسېره پردې، د کیچ ضایع د جدي پایلو المل کیږي: DBMS په سیمونو کې د مینځلو پیل کوي، د API خدمتونه د غوښتنو بندیز پیل کوي، او داسې نور. د وضعیت ثبات ممکن لسګونه دقیقې وخت ونیسي، او پدې وخت کې به خدمت خورا ورو یا په بشپړه توګه شتون ونلري.
موږ باید چمتو کړو د لږې هڅې سره د غوښتنلیک افقی اندازه کولو وړتیا, i.e. د سرچینې کوډ کې لږترلږه بدلونونو سره او بشپړ فعالیت ساتل شوی. کیچ نه یوازې د ناکامۍ په وړاندې مقاومت وکړئ، بلکې هڅه وکړئ چې د دې څخه د معلوماتو ضایع کم کړئ.
پخپله memcached کې څه ستونزه ده؟
په عموم کې، د پی ایچ پی لپاره میمکیچ شوی توسیع د بکس څخه بهر توزیع شوي ډاټا او سیشن ذخیره ملاتړ کوي. د دوامداره کیلي هش کولو میکانیزم تاسو ته اجازه درکوي په مساوي ډول په ډیری سرورونو کې ډیټا ځای په ځای کړئ ، په ځانګړي ډول د ګروپ څخه یو ځانګړي سرور ته هر ځانګړي کیلي په ګوته کوي ، او د ناکامۍ رامینځته شوي وسیلې د کیچنګ خدمت لوړه شتون تضمینوي (مګر له بده مرغه ، هیڅ معلومات نشته).
د سیشن ذخیره کولو سره شیان یو څه ښه دي: تاسو کولی شئ تنظیم کړئ memcached.sess_number_of_replicas، د دې په پایله کې چې ډاټا به په یوځل کې په څو سرورونو کې زیرمه شي ، او د یوې میمکیچ شوي مثال د ناکامۍ په صورت کې ، ډاټا به له نورو څخه لیږدول کیږي. په هرصورت، که چیرې سرور د معلوماتو پرته بیرته آنلاین راشي (لکه څنګه چې معمولا د بیا پیل کولو وروسته پیښیږي)، ځینې کیلي به د هغې په ګټه بیا توزیع شي. په حقیقت کې دا به معنی ولري د غونډې د معلوماتو له لاسه ورکول، ځکه چې د ورکیدو په صورت کې بل نقل ته د "تلو" لپاره هیڅ لاره نشته.
د معیاري کتابتون وسیلې په عمده توګه هدف دي افقي اندازه کول: دوی تاسو ته اجازه درکوي چې کیچ لوی اندازې ته لوړ کړي او په مختلف سرورونو کې کوربه شوي کوډ څخه ورته لاسرسی چمتو کړي. په هرصورت، زموږ په وضعیت کې، د ذخیره شوي معلوماتو حجم د څو ګیګابایټ څخه ډیر نه دی، او د یو یا دوه نوډونو فعالیت کافي دی. په دې اساس، یوازینی ګټور معیاري وسیلې کیدی شي د میم کیچ شتون ډاډمن کړي پداسې حال کې چې لږترلږه یو کیچ مثال په کاري حالت کې ساتل کیږي. په هرصورت، دا ممکنه نه وه چې حتی د دې فرصت څخه ګټه پورته کړئ ... دلته دا د یادولو وړ ده چې په پروژه کې کارول شوي چوکاټ لرغونتوب، له همدې امله د سرورونو د حوض سره کار کولو لپاره د غوښتنلیک ترلاسه کول ناممکن وو. راځئ چې د سیشن ډیټا له لاسه ورکولو په اړه هم هیر نکړو: د پیرودونکي سترګې د کاروونکو لوی لاګ آوټ څخه راوتلې.
په مثالي توګه دا اړینه وه د ریکارډونو نقل کول په یاد شوي او بای پاس کولو ریپلیکسونو کې د خطا یا خطا په صورت کې. موږ سره د دې ستراتیژۍ په پلي کولو کې مرسته وکړه .
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 کې پرمخ ځي - په وینا، میکروټر هم هلته موقعیت لري. لپاره کانتینر مجلس موږ یی استعمالوو ، هغه تشکیل چې د دې لپاره به ورته ښکاري:
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' ]()
... او خاکه یې راوباسه د هیلم چارټ. په زړه پورې خبره دا ده چې د عکسونو شمیر پراساس یوازې یو ترتیب جنراتور شتون لري (که څوک ډیر لیونیک او په زړه پوری اختیار ولري، په نظرونو کې یې شریک کړئ):
{{- $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 }}
}
}
}
}()
موږ دا د ازموینې چاپیریال ته واړوو او وګورو:
# 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 پروتوکول ته لاړشئ او هرڅه به کار وکړي .... په هرصورت، پدې حالت کې، د ځوابونو په لټه کې عادت یوه ظالمانه ټوکه وکړه. تاسو به هلته سم ځواب ونه مومئ ... پرته لدې چې ، البته ، تاسو پای ته سکرول کړئ ، چیرې چې برخه کې وي "د کارونکي مرسته شوي یادښتونه" وفادار به وي .
هو، د سم انتخاب نوم دی memcached.sess_binary_protocol. دا باید غیر فعال وي، وروسته لدې چې ناستې به کار پیل کړي. ټول هغه څه چې پاتې دي د مایکروټر سره کانټینر د PHP سره پوډ ته واچوئ!
پایلې
په دې توګه، یوازې د زیربنایي بدلونونو سره موږ د دې توان درلود چې ستونزه حل کړو: د memcached غلطی زغم مسله حل شوې، او د کیچ ذخیره کولو اعتبار ډیر شوی. د غوښتنلیک لپاره د څرګندو ګټو سربیره، دا په پلیټ فارم کې د کار کولو په وخت کې د چلولو لپاره ځای ورکړ: کله چې ټولې برخې ریزرو ولري، د مدیر ژوند خورا ساده دی. هو، دا طریقه هم خپل نیمګړتیاوې لري، دا ممکن د "کرچ" په څیر ښکاري، مګر که دا پیسې خوندي کړي، ستونزه له منځه یوسي او د نوي لامل نه شي - ولې نه؟
PS
زموږ په بلاګ کې هم ولولئ:
- "د ډیپ سره تمرین وکړئ" (د مثال په توګه د سیمفوني ډیمو کارول): и ;
- «".
سرچینه: www.habr.com
