mcrouter استعمال ڪندي افقي طور تي memcached ماپڻ لاءِ

mcrouter استعمال ڪندي افقي طور تي memcached ماپڻ لاءِ

ڪنهن به ٻوليءَ ۾ اعليٰ لوڊشيڊنگ جي منصوبن کي ترقي ڪرڻ لاءِ خاص طريقي ۽ خاص اوزارن جي استعمال جي ضرورت هوندي آهي، پر جڏهن اها 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 wiki تي دستاويز и پروجيڪٽ مسئلا (بشمول بند ٿيل)، مختلف ترتيبن جي مڪمل اسٽوريج جي نمائندگي ڪري ٿو.

بلڊنگ ۽ هلندڙ ميڪروٽر

اسان جي ايپليڪيشن (۽ پاڻ memcached) Kubernetes ۾ هلندو آهي - مطابق، mcrouter پڻ اتي موجود آهي. لاءِ ڪنٽينر اسيمبلي اسان استعمال ڪريون ٿا 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)

... ۽ ان جو خاڪو ٺاهيو هيلم چارٽ. دلچسپ ڳالهه اها آهي ته صرف هڪ ترتيب جنريٽر آهي 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 }}
         }
       }
     }
   }

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

غلطي جي متن جي ڳولا ڪرڻ سان ڪو به نتيجو نه آيو، پر سوال لاءِ “mcrouter php"سڀ کان اڳ منصوبي جو سڀ کان پراڻو حل ٿيل مسئلو هو - حمايت جي کوٽ memcached بائنري پروٽوڪول.

NB: memcached ۾ ASCII پروٽوڪول بائنري کان وڌيڪ سست آهي، ۽ معياري ڪنجي هيشنگ جا معياري وسيلا صرف بائنري پروٽوڪول سان ڪم ڪن ٿا. پر اهو هڪ خاص ڪيس لاءِ مسئلا پيدا نٿو ڪري.

چال بيگ ۾ آهي: توهان سڀني کي ڪرڻو آهي ASCII پروٽوڪول ڏانهن وڃو ۽ سڀ ڪجهه ڪم ڪندو .... بهرحال، هن معاملي ۾، جواب ڳولڻ جي عادت php.net تي دستاويز هڪ ظالمانه مذاق ڪيو. توهان اتي صحيح جواب نه ڳوليندا ... جيستائين، يقينا، توهان آخر تائين اسڪرال ڪريو، جتي سيڪشن ۾ "استعمال ڪندڙ ادا ڪيل نوٽس" وفادار ٿيندو ۽ غير منصفانه رد ٿيل جواب.

ها، صحيح آپشن جو نالو آهي memcached.sess_binary_protocol. ان کي غير فعال ٿيڻ گهرجي، جنهن کان پوءِ سيشن ڪم ڪرڻ شروع ڪندا. باقي اهو آهي ته ڪنٽينر کي ميڪروٽر سان گڏ هڪ پوڊ ۾ PHP سان!

ٿڪل

اهڙيء طرح، صرف بنيادي ڍانچي جي تبديلين سان اسان مسئلو حل ڪرڻ جي قابل ٿي ويا آهيون: ميمڪ ٿيل غلطي رواداري سان مسئلو حل ڪيو ويو آهي، ۽ ڪيش اسٽوريج جي اعتبار کي وڌايو ويو آهي. ايپليڪيشن جي واضح فائدن کان علاوه، هن پليٽ فارم تي ڪم ڪرڻ وقت انتشار لاء ڪمرو ڏنو: جڏهن سڀني اجزاء کي محفوظ آهي، منتظم جي زندگي تمام آسان آهي. ها، هن طريقي ۾ پڻ پنهنجون خاميون آهن، اهو ٿي سگهي ٿو "ڪيچ" وانگر، پر جيڪڏهن اهو پئسا بچائيندو آهي، مسئلو کي دفن ڪري ٿو ۽ نوان سبب نه ٿو ڏئي - ڇو نه؟

پي ايس

اسان جي بلاگ تي پڻ پڙهو:

جو ذريعو: www.habr.com

تبصرو شامل ڪريو