mcrouter භාවිතා කරමින් තිරස් අතට memcached පරිමාණය කිරීම

mcrouter භාවිතා කරමින් තිරස් අතට memcached පරිමාණය කිරීම

ඕනෑම භාෂාවකින් ඉහළ බරක් සහිත ව්‍යාපෘති සංවර්ධනය කිරීම සඳහා විශේෂ ප්‍රවේශයක් සහ විශේෂ මෙවලම් භාවිතා කිරීම අවශ්‍ය වේ, නමුත් PHP හි යෙදුම් සම්බන්ධයෙන්, තත්වය කෙතරම් උග්‍ර විය හැකි ද යත්, ඔබට සංවර්ධනය කිරීමට සිදු වේ, උදාහරණයක් ලෙස, තමන්ගේම යෙදුම් සේවාදායකය. මෙම සටහනෙන් අපි බෙදා හරින ලද සැසි ආචයනය සහ memcached හි දත්ත හැඹිලිය සමඟ හුරුපුරුදු වේදනාව සහ අපි එක් “වාට්ටුවක්” ව්‍යාපෘතියක් තුළ මෙම ගැටළු විසඳන ආකාරය ගැන කතා කරමු.

මෙම අවස්ථාවෙහි වීරයා යනු symfony 2.3 රාමුව මත පදනම් වූ PHP යෙදුමකි, එය යාවත්කාලීන කිරීමට ව්‍යාපාරික සැලසුම්වලට කිසිසේත්ම ඇතුළත් නොවේ. තරමක් සම්මත සැසි ආචයනයට අමතරව, මෙම ව්‍යාපෘතිය සම්පූර්ණයෙන්ම භාවිතා කළේය "සියල්ල හැඹිලි" ප්රතිපත්තිය memcached තුළ: දත්ත සමුදාය සහ API සේවාදායකයන් වෙත ඉල්ලීම් සඳහා ප්‍රතිචාර, විවිධ කොඩි, කේත ක්‍රියාත්මක කිරීම සමමුහුර්ත කිරීම සඳහා අගුලු සහ තවත් බොහෝ දේ. එවැනි තත්වයක් තුළ, memcached බිඳවැටීම යෙදුමේ ක්රියාකාරිත්වයට මාරාන්තික වේ. ඊට අමතරව, හැඹිලි නැතිවීම බරපතල ප්‍රතිවිපාකවලට තුඩු දෙයි: DBMS මැහුම්වලදී පුපුරා යාමට පටන් ගනී, API සේවා ඉල්ලීම් තහනම් කිරීමට පටන් ගනී. තත්වය ස්ථාවර කිරීමට මිනිත්තු දස ගණනක් ගත විය හැකි අතර, මෙම කාලය තුළ සේවාව ඉතා මන්දගාමී හෝ සම්පූර්ණයෙන්ම නොලැබේ.

අපට සැපයීමට අවශ්‍ය විය කුඩා උත්සාහයකින් යෙදුම තිරස් අතට පරිමාණය කිරීමේ හැකියාව, i.e. මූලාශ්‍ර කේතයේ අවම වෙනස්කම් සහ සම්පූර්ණ ක්‍රියාකාරීත්වය සංරක්ෂණය කර ඇත. හැඹිලිය අසාර්ථක වීමට ප්‍රතිරෝධී වනවා පමණක් නොව, එයින් දත්ත අලාභය අවම කිරීමට උත්සාහ කරන්න.

memcached එකේම වැරැද්ද මොකක්ද?

සාමාන්‍යයෙන්, PHP සඳහා වන memcached දිගුව බෙදා හරින ලද දත්ත සහ කොටුවෙන් පිටත සැසි ආචයනය සඳහා සහය දක්වයි. ස්ථාවර යතුරු හැෂිං සඳහා වන යාන්ත්‍රණය ඔබට බොහෝ සේවාදායකයන් මත ඒකාකාරව දත්ත බෙදා හැරීමට ඉඩ සලසයි, එක් එක් විශේෂිත යතුර සමූහයේ නිශ්චිත සේවාදායකයකට අනන්‍ය ලෙස ආමන්ත්‍රණය කරයි, සහ ගොඩනඟන ලද අසාර්ථක මෙවලම් හැඹිලි සේවාවේ ඉහළ ප්‍රතිලාභයක් සහතික කරයි (නමුත්, අවාසනාවකට, දත්ත නැත).

සැසි ආචයනය සමඟ දේවල් ටිකක් හොඳයි: ඔබට වින්‍යාසගත කළ හැක memcached.sess_number_of_replicas, එහි ප්‍රතිඵලයක් ලෙස දත්ත එකවර සේවාදායකයන් කිහිපයක ගබඩා වන අතර, එක් memcached අවස්ථාවක් අසාර්ථක වූ විට, දත්ත අනෙක් අයගෙන් මාරු කරනු ලැබේ. කෙසේ වෙතත්, සේවාදායකය දත්ත නොමැතිව නැවත සබැඳිව පැමිණේ නම් (සාමාන්‍යයෙන් නැවත ආරම්භ කිරීමෙන් පසුව සිදු වන පරිදි), සමහර යතුරු එයට පක්ෂව නැවත බෙදා හරිනු ලැබේ. ඇත්ත වශයෙන්ම මෙය අදහස් වනු ඇත සැසි දත්ත නැතිවීම, අතපසු වූ විට වෙනත් අනුරුවකට "යන්න" ක්‍රමයක් නැති නිසා.

සම්මත පුස්තකාල මෙවලම් ප්රධාන වශයෙන් ඉලක්ක කර ඇත තිරස් පරිමාණය කිරීම: ඒවා ඔබට හැඹිලිය දැවැන්ත ප්‍රමාණවලට වැඩි කිරීමට සහ විවිධ සේවාදායකයන් මත සත්කාරක කේත වලින් එයට ප්‍රවේශය ලබා දීමට ඉඩ සලසයි. කෙසේ වෙතත්, අපගේ තත්වය තුළ, ගබඩා කර ඇති දත්ත පරිමාව ගිගාබයිට් කිහිපයක් නොඉක්මවන අතර, නෝඩ් එකක් හෝ දෙකක කාර්ය සාධනය ප්රමාණවත් වේ. ඒ අනුව, එකම ප්‍රයෝජනවත් සම්මත මෙවලම් විය හැක්කේ වැඩ කරන තත්වයේ අවම වශයෙන් එක් හැඹිලි අවස්ථාවක් පවත්වා ගනිමින් memcached ලබා ගැනීමේ හැකියාව සහතික කිරීමයි. හැබැයි මේ අවස්ථාවෙන්වත් ප්‍රයෝජන ගන්න බැරි උනා... මෙන්න මේ ව්‍යාපෘතියේ භාවිතා කරපු රාමුවේ පෞරාණික බව මතක් කරන්න වටිනවා, ඒකයි සර්වර් සංචිතයක් එක්ක ඇප්ලිකේෂන් එක වැඩ කරගන්න බැරි වුනේ. සැසි දත්ත නැතිවීම ගැන ද අපි අමතක නොකරමු: පරිශීලකයින්ගේ දැවැන්ත ලොග්අවුට් වලින් පාරිභෝගිකයාගේ ඇස් ඇඹරී ගියේය.

ඉතා මැනවින් එය අවශ්ය විය memcached සහ bypassing replicas හි වාර්තා අනුකරණය කිරීම අත්වැරදීමක් හෝ වැරදීමක් සිදු වුවහොත්. මෙම උපාය මාර්ගය ක්‍රියාත්මක කිරීමට අපට උදව් විය mcrouter.

mcrouter

මෙය Facebook විසින් එහි ගැටළු විසඳීම සඳහා නිර්මාණය කරන ලද memcached router එකකි. එය ඉඩ දෙන memcached text protocol සඳහා සහය දක්වයි පරිමාණ 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 සේවාදායක තුනක සංචිතයක් සමඟින්, එවිට සියලුම ඉල්ලීම් පළමු memcached අවස්ථාවට පැමිණෙන අතර, ඉතිරිය දත්ත නොමැති විට අවශේෂ පදනමින් ඉල්ලීම් ලැබෙනු ඇත. එවැනි ප්රවේශයක් හේතු වනු ඇත ලැයිස්තුවේ පළමු සේවාදායකයේ අධික බර පැටවීම, එබැවින් විවිධ අනුපිළිවෙලින් ලිපින සහිත සංචිත තුනක් උත්පාදනය කිරීමට සහ අහඹු ලෙස තෝරා ගැනීමට තීරණය විය.
  • අනෙකුත් සියලුම ඉල්ලීම් (සහ මෙය වාර්තාවකි) භාවිතයෙන් සකසනු ලැබේ AllMajorityRoute. මෙම හසුරුවන්නා සංචිතයේ ඇති සියලුම සේවාදායකයන් වෙත ඉල්ලීම් යවන අතර අවම වශයෙන් N/2 + 1 වෙතින් ප්‍රතිචාර එනතෙක් බලා සිටී. භාවිතයේ සිට AllSyncRoute මක්නිසාද යත් මෙම ක්‍රමයට ධනාත්මක ප්‍රතිචාරයක් අවශ්‍ය වන බැවින් ලිවීමේ මෙහෙයුම් අත්හැරීමට සිදු විය всех කණ්ඩායමේ සේවාදායකයන් - එසේ නොමැතිනම් එය නැවත පැමිණේ SERVER_ERROR. mcrouter දත්ත ලබා ගත හැකි හැඹිලිවලට එකතු කළත්, ඇමතුම් PHP කාර්යය දෝෂයක් ආපසු ලබා දෙනු ඇත සහ දැනුම්දීම ජනනය කරනු ඇත. AllMajorityRoute එතරම් දැඩි නොවන අතර ඉහත විස්තර කර ඇති ගැටළු නොමැතිව ඒකක වලින් අඩක් දක්වා සේවයෙන් ඉවත් කිරීමට ඉඩ සලසයි.

ප්රධාන අවාසිය මෙම යෝජනා ක්‍රමය නම් හැඹිලියේ ඇත්ත වශයෙන්ම දත්ත නොමැති නම්, සේවාදායකයාගෙන් එක් එක් ඉල්ලීමක් සඳහා N ඉල්ලීම් memcached වෙත සැබවින්ම ක්‍රියාත්මක වනු ඇත - වෙත සැමට තටාකයේ සේවාදායකයන්. අපට තටාකවල ඇති සේවාදායකයන් සංඛ්‍යාව අඩු කළ හැකිය, උදාහරණයක් ලෙස, දෙකකට: ගබඩා විශ්වසනීයත්වය කැප කිරීම, අපට ලැබේоඉල්ලීම්වල සිට නැතිවූ යතුරු දක්වා වැඩි වේගයක් සහ අඩු බරක්.

NB: ඔබට mcrouter ඉගෙනීම සඳහා ප්‍රයෝජනවත් සබැඳි ද සොයා ගත හැක විකි හි ලේඛනගත කිරීම и ව්යාපෘති ගැටළු (වසා දැමූ ඒවා ඇතුළුව), විවිධ වින්‍යාසවල සම්පූර්ණ ගබඩාවක් නියෝජනය කරයි.

mcrouter ගොඩනැගීම සහ ධාවනය කිරීම

අපගේ යෙදුම (සහ memcached ම) Kubernetes හි ධාවනය වේ - ඒ අනුව, mcrouter ද එහි පිහිටා ඇත. සදහා බහාලුම් එකලස් කිරීම අපි පාවිච්චි කරන්නේ werf, ඒ සඳහා වන වින්‍යාසය මේ ආකාරයෙන් පෙනෙනු ඇත:

NB: ලිපියේ දක්වා ඇති ලැයිස්තුගත කිරීම් ගබඩාවේ පළ කර ඇත පැතලි / mcrouter.

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 >

දෝෂයේ පෙළ සෙවීමෙන් කිසිදු ප්‍රතිඵලයක් ලබා නොදුන් නමුත් විමසුම සඳහාmcrouter php"ව්‍යාපෘතියේ පැරණිතම නොවිසඳුණු ගැටලුව ඉදිරියෙන්ම විය. සහයෝගය නොමැතිකම memcached ද්විමය ප්‍රොටෝකෝලය.

NB: memcached හි ඇති ASCII ප්‍රොටෝකෝලය ද්විමය එකට වඩා මන්දගාමී වන අතර, ස්ථාවර යතුරු හැෂ් කිරීමේ සම්මත මාධ්‍ය ක්‍රියා කරන්නේ ද්විමය ප්‍රොටෝකෝලය සමඟ පමණි. නමුත් මෙය විශේෂිත නඩුවක් සඳහා ගැටළු ඇති නොකරයි.

උපක්‍රමය මල්ලේ ඇත: ඔබ කළ යුතුව ඇත්තේ ASCII ප්‍රොටෝකෝලය වෙත මාරු වීම සහ සියල්ල ක්‍රියාත්මක වනු ඇත.... කෙසේ වෙතත්, මෙම අවස්ථාවේ දී, පිළිතුරු සෙවීමේ පුරුද්ද php.net හි ලේඛනගත කිරීම කුරිරු විහිළුවක් කළා. ඔබට එහි නිවැරදි පිළිතුර සොයාගත නොහැකි වනු ඇත... ඇත්ත වශයෙන්ම, ඔබ කොටසෙහි කොතැනද, අවසානය දක්වා අනුචලනය කරන්නේ නම් මිස "පරිශීලක දායක සටහන්" විශ්වාසවන්ත වනු ඇත සහ අසාධාරණ ලෙස අඩු ඡන්දය දුන් පිළිතුර.

ඔව්, නිවැරදි විකල්පය නම වේ memcached.sess_binary_protocol. එය අක්‍රිය කළ යුතුය, ඉන් පසුව සැසි ක්‍රියා කිරීමට පටන් ගනී. ඉතිරිව ඇත්තේ mcrouter සහිත කන්ටේනරය PHP සහිත පොඩ් එකකට දැමීම පමණි!

නිගමනය

මේ අනුව, යටිතල ව්‍යුහාත්මක වෙනස්කම් සමඟින් අපට ගැටලුව විසඳීමට හැකි විය: memcached වැරදි ඉවසීමේ ගැටලුව විසඳා ඇති අතර, හැඹිලි ගබඩාවේ විශ්වසනීයත්වය වැඩි කර ඇත. යෙදුම සඳහා පැහැදිලි වාසි වලට අමතරව, මෙය වේදිකාවේ වැඩ කරන විට උපාමාරු සඳහා ඉඩ ලබා දුන්නේය: සියලුම සංරචක රක්ෂිතයක් ඇති විට, පරිපාලකගේ ජීවිතය බෙහෙවින් සරල කර ඇත. ඔව්, මෙම ක්‍රමයට එහි අඩුපාඩු ද ඇත, එය “කිහිලිකරුවක්” මෙන් පෙනෙන්නට පුළුවන, නමුත් එය මුදල් ඉතිරි කරයි නම්, ගැටලුව වළලන්නේ නම් සහ නව ඒවා ඇති නොකරන්නේ නම් - ඇයි නැත්තේ?

ප්රාදේශීය සභා

අපගේ බ්ලොග් අඩවියේ ද කියවන්න:

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න