
ڪنهن به ٻوليءَ ۾ اعليٰ لوڊشيڊنگ جي منصوبن کي ترقي ڪرڻ لاءِ خاص طريقي ۽ خاص اوزارن جي استعمال جي ضرورت هوندي آهي، پر جڏهن اها PHP ۾ ايپليڪيشنن جي اچي ٿي، صورتحال ايتري خراب ٿي سگهي ٿي جو توهان کي ترقي ڪرڻي پوندي، مثال طور، . هن نوٽ ۾ اسان واقف درد جي باري ۾ ڳالهائينداسين ورهايل سيشن اسٽوريج ۽ ڊيٽا ڪيشنگ سان گڏ ميمڪچ ۾ ۽ ڪيئن اسان انهن مسئلن کي هڪ "وارڊ" منصوبي ۾ حل ڪيو.
موقعي جو هيرو هڪ PHP ايپليڪيشن آهي جيڪو سمفوني 2.3 فريم ورڪ تي ٻڌل آهي، جيڪو تازه ڪاري ڪرڻ جي ڪاروباري منصوبن ۾ شامل ناهي. ڪافي معياري سيشن اسٽوريج جي اضافي ۾، هن منصوبي جو پورو استعمال ڪيو "سڀ ڪجهه ڪيش ڪرڻ" پاليسي memcached ۾: ڊيٽابيس ۽ API سرورز جي درخواستن جا جواب، مختلف جھنڊا، ڪوڊ جي عمل کي هم وقت سازي ڪرڻ لاءِ لاڪ ۽ وڌيڪ. اهڙي صورتحال ۾، ميمڪسڊ جي ڀڃڪڙي ايپليڪيشن جي آپريشن لاء موتمار ٿي ويندي آهي. اضافي طور تي، ڪيش جي نقصان کي سنجيده نتيجن جي ڪري ٿي: ڊي بي ايم ايس سيز تي دفن ٿيڻ شروع ٿئي ٿي، API خدمتون درخواستن تي پابندي لڳائڻ شروع ڪن ٿا، وغيره. صورتحال کي مستحڪم ڪرڻ ۾ ڏهه منٽ لڳن ٿا، ۽ ان دوران سروس انتهائي سست يا مڪمل طور تي دستياب نه هوندي.
اسان کي مهيا ڪرڻ جي ضرورت آهي ٿوري ڪوشش سان ايپليڪيشن کي افقي طور تي ماپڻ جي صلاحيت، i.e. ماخذ ڪوڊ ۾ گهٽ ۾ گهٽ تبديلين سان ۽ مڪمل ڪارڪردگي محفوظ آهي. ڪيش کي نه رڳو ناڪامين جي مزاحمتي بڻايو، پر ان مان ڊيٽا جي نقصان کي به گھٽ ڪرڻ جي ڪوشش ڪريو.
پاڻ memcached سان ڇا غلط آهي؟
عام طور تي، PHP لاءِ ميمڪيڊ ايڪسٽينشن ورهايل ڊيٽا ۽ سيشن اسٽوريج کي باڪس کان ٻاهر سپورٽ ڪري ٿي. هڪجهڙائي واري ڪي هيشنگ جو ميکانيزم توهان کي ڪيترن ئي سرورن تي ڊيٽا کي هڪجهڙائي سان رکڻ جي اجازت ڏئي ٿو، منفرد طور تي هر مخصوص ڪنجي کي گروپ مان هڪ مخصوص سرور ڏانهن ايڊريس ڪرڻ، ۽ بلٽ ان فيل اوور ٽولز ڪيشنگ سروس جي اعليٰ دستيابي کي يقيني بڻائي ٿو (پر بدقسمتي سان، ڪابه ڊيٽا).
شيون سيشن اسٽوريج سان ٿورو بهتر آهن: توهان ترتيب ڏئي سگهو ٿا memcached.sess_number_of_replicas، جنهن جي نتيجي ۾ ڊيٽا هڪ ئي وقت ڪيترن ئي سرورن تي محفوظ ڪئي ويندي، ۽ هڪ ميمڪيش ٿيل مثال جي ناڪامي جي صورت ۾، ڊيٽا ٻين کان منتقل ڪئي ويندي. بهرحال، جيڪڏهن سرور واپس آن لائن ڊيٽا کان سواءِ اچي ٿو (جيئن عام طور تي ٻيهر شروع ٿيڻ کان پوءِ ٿئي ٿو)، ڪجهه چاٻيون ان جي حق ۾ ٻيهر ورهائي وينديون. حقيقت ۾ هن جو مطلب ٿيندو سيشن ڊيٽا جي نقصان، ڇاڪاڻ ته مس جي صورت ۾ ڪنهن ٻئي نقل ڏانهن ”وڃڻ“ جو ڪو طريقو ناهي.
معياري لائبريري جا اوزار بنيادي طور تي مقصد آهن افقي اسڪيلنگ: اهي توهان کي ڪيش کي وڏي سائيز تائين وڌائڻ جي اجازت ڏين ٿا ۽ مختلف سرورز تي ميزباني ڪيل ڪوڊ مان ان تائين رسائي فراهم ڪن ٿا. بهرحال، اسان جي صورتحال ۾، ذخيرو ٿيل ڊيٽا جو مقدار ڪيترن ئي گيگا بائيٽ کان وڌيڪ نه آهي، ۽ هڪ يا ٻه نوڊس جي ڪارڪردگي ڪافي آهي. ان جي مطابق، صرف ڪارائتو معياري اوزار ٿي سگهي ٿو memcached جي دستيابي کي يقيني بڻائڻ جڏهن ته ڪم ڪندڙ حالت ۾ گهٽ ۾ گهٽ هڪ ڪيش مثال برقرار رکڻ. تنهن هوندي به، ان موقعي مان فائدو وٺڻ ممڪن نه هو... هتي پراجيڪٽ ۾ استعمال ٿيل فريم ورڪ جي قديميت کي ياد ڪرڻ جي قابل آهي، اهو ئي سبب آهي ته اهو ناممڪن هو ته ايپليڪيشن کي سرور جي تلاء سان ڪم ڪرڻ لاء. اچو ته سيشن ڊيٽا جي نقصان جي باري ۾ پڻ نه وساريو: صارفين جي وڏي لاگ آئوٽ کان صارف جي اکين کي ڇڪايو ويو.
مثالي طور تي اهو گهربل هو يادگيري ۾ رڪارڊ جي نقل ۽ نقلن کي نظرانداز ڪرڻ غلطي يا غلطي جي صورت ۾. هن حڪمت عملي تي عمل ڪرڻ ۾ اسان جي مدد ڪئي .
ميڪروٽر
هي هڪ memcached روٽر آهي Facebook پاران ان جي مسئلن کي حل ڪرڻ لاءِ. اهو memcached ٽيڪسٽ پروٽوڪول کي سپورٽ ڪري ٿو، جيڪا اجازت ڏئي ٿي پيماني تي memcached تنصيب پاگل تناسب ڏانهن. mcrouter جي تفصيلي وضاحت ۾ ملي سگهي ٿو . ٻين شين جي وچ ۾ اهو ڪري سگهي ٿو جيڪو اسان کي گهرجي:
- نقل رڪارڊ؛
- گروپ ۾ ٻين سرورن ڏانهن واپس وڃو جيڪڏهن ڪا غلطي ٿئي ٿي.
ڪاروبار لاءِ!
mcrouter ترتيب
مان سڌو سنئون ترتيب ڏانھن ويندس:
{
"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"
]
}
}
}
}ٽي تلاءُ ڇو؟ سرور بار بار ڇو آهن؟ اچو ته سمجهون ته اهو ڪيئن ڪم ڪري ٿو.
- هن ترتيب ۾، mcrouter اهو رستو چونڊيندو آهي جنهن ڏانهن درخواست موڪلي ويندي درخواست جي حڪم جي بنياد تي. اهو ماڻهو هن کي ٻڌائي ٿو
OperationSelectorRoute. - GET درخواستون ھينڊلر ڏانھن وڃو
RandomRouteجيڪو بي ترتيب طور تي صف جي شين جي وچ ۾ پول يا رستو چونڊيندو آهيchildren. هن صف جو هر عنصر موڙ ۾ هڪ سنڀاليندڙ آهيMissFailoverRoute، جيڪو پول ۾ هر سرور جي ذريعي ويندو جيستائين اهو ڊيٽا سان جواب حاصل ڪري، جيڪو ڪلائنٽ ڏانهن واپس ڪيو ويندو. - جيڪڏهن اسان خاص طور تي استعمال ڪيو
MissFailoverRouteٽن سرورن جي تلاءَ سان، پوءِ سڀ درخواستون پھريون پھريون ميمڪيش ٿيل مثال ڏانھن اينديون، ۽ باقي رھي درخواستون وصول ڪنديون جڏھن ڪو ڊيٽا نه ھوندو. اهڙي طريقي جي نتيجي ۾ ٿيندو لسٽ ۾ پهرين سرور تي اضافي لوڊ، ان ڪري اهو فيصلو ڪيو ويو ته ٽن تلاءَ کي مختلف ترتيبن ۾ پتي سان ۽ انهن کي بي ترتيب طور تي چونڊيو. - ٻيون سڀئي درخواستون (۽ اهو هڪ رڪارڊ آهي) استعمال ڪندي عمل ڪيو وڃي ٿو
AllMajorityRoute. هي هينڊلر پول ۾ سڀني سرورن ڏانهن درخواستون موڪلي ٿو ۽ انهن مان گهٽ ۾ گهٽ N/2 + 1 جي جوابن جو انتظار ڪري ٿو. استعمال کانAllSyncRouteلکڻ جي عملن کي ڇڏي ڏنو ويو، ڇاڪاڻ ته هن طريقي جي مثبت جواب جي ضرورت آهي всех گروپ ۾ سرور - ٻي صورت ۾ اهو واپس ايندوSERVER_ERROR. جيتوڻيڪ mcrouter ڊيٽا شامل ڪندو موجود ڪيش ۾، ڪالنگ PHP فنڪشن غلطي واپس ڪندو ۽ نوٽيس پيدا ڪندو.AllMajorityRouteايترو سخت نه آهي ۽ مٿي بيان ڪيل مسئلن کان سواءِ اڌ يونٽن کي سروس مان ڪڍڻ جي اجازت ڏئي ٿو.
مکيه نقصان هي اسڪيم اهو آهي ته جيڪڏهن ڪيش ۾ واقعي ڪا به ڊيٽا نه آهي، ته پوءِ ڪلائنٽ جي هر درخواست لاءِ N جي درخواستن کي ميمڪيش ڪرڻ لاءِ اصل ۾ عمل ڪيو ويندو. سڀني لاء پول ۾ سرور. اسان پول ۾ سرورز جو تعداد گھٽائي سگھون ٿا، مثال طور، ٻن تائين: ذخيري جي اعتبار کي قربان ڪرڻ، اسان حاصل ڪريون ٿاоتيز رفتار ۽ گھٽ لوڊ درخواستن کان غائب چابين تائين.
NB: توهان پڻ ڳولي سگهو ٿا مفيد لنڪس سکڻ لاءِ mcrouter и (بشمول بند ٿيل)، مختلف ترتيبن جي مڪمل اسٽوريج جي نمائندگي ڪري ٿو.
بلڊنگ ۽ هلندڙ ميڪروٽر
اسان جي ايپليڪيشن (۽ پاڻ memcached) Kubernetes ۾ هلندو آهي - مطابق، mcrouter پڻ اتي موجود آهي. لاءِ ڪنٽينر اسيمبلي اسان استعمال ڪريون ٿا ، ترتيب جنهن لاءِ هن طرح نظر ايندي:
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' ]()
... ۽ ان جو خاڪو ٺاهيو هيلم چارٽ. دلچسپ ڳالهه اها آهي ته صرف هڪ ترتيب جنريٽر آهي replicas جي تعداد جي بنياد تي (جيڪڏهن ڪنهن وٽ وڌيڪ لاکونڪ ۽ خوبصورت آپشن آهي، ان کي تبصرن ۾ حصيداري ڪريو):
{{- $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 سان!
ٿڪل
اهڙيء طرح، صرف بنيادي ڍانچي جي تبديلين سان اسان مسئلو حل ڪرڻ جي قابل ٿي ويا آهيون: ميمڪ ٿيل غلطي رواداري سان مسئلو حل ڪيو ويو آهي، ۽ ڪيش اسٽوريج جي اعتبار کي وڌايو ويو آهي. ايپليڪيشن جي واضح فائدن کان علاوه، هن پليٽ فارم تي ڪم ڪرڻ وقت انتشار لاء ڪمرو ڏنو: جڏهن سڀني اجزاء کي محفوظ آهي، منتظم جي زندگي تمام آسان آهي. ها، هن طريقي ۾ پڻ پنهنجون خاميون آهن، اهو ٿي سگهي ٿو "ڪيچ" وانگر، پر جيڪڏهن اهو پئسا بچائيندو آهي، مسئلو کي دفن ڪري ٿو ۽ نوان سبب نه ٿو ڏئي - ڇو نه؟
پي ايس
اسان جي بلاگ تي پڻ پڙهو:
- "ڊپ سان مشق" (مثال طور symfony-demo استعمال ڪندي): и ;
- «».
جو ذريعو: www.habr.com
