கிடைமட்டமாக memcached அளவிடுவதற்கு mcrouter ஐப் பயன்படுத்துதல்

கிடைமட்டமாக memcached அளவிடுவதற்கு mcrouter ஐப் பயன்படுத்துதல்

எந்தவொரு மொழியிலும் உயர்-சுமை திட்டங்களை உருவாக்குவதற்கு ஒரு சிறப்பு அணுகுமுறை மற்றும் சிறப்பு கருவிகளின் பயன்பாடு தேவைப்படுகிறது, ஆனால் PHP இல் உள்ள பயன்பாடுகளுக்கு வரும்போது, ​​நீங்கள் உருவாக்க வேண்டிய நிலைமை மிகவும் மோசமாகிவிடும், எடுத்துக்காட்டாக, சொந்த பயன்பாட்டு சேவையகம். இந்த குறிப்பில், விநியோகிக்கப்பட்ட அமர்வு சேமிப்பு மற்றும் memcached இல் டேட்டா கேச்சிங் பற்றிய பழக்கமான வலி மற்றும் ஒரு “வார்டு” திட்டத்தில் இந்த சிக்கல்களை எவ்வாறு தீர்த்தோம் என்பதைப் பற்றி பேசுவோம்.

இந்த நிகழ்வின் ஹீரோ சிம்ஃபோனி 2.3 கட்டமைப்பை அடிப்படையாகக் கொண்ட ஒரு PHP பயன்பாடாகும், இது புதுப்பிப்பதற்கான வணிகத் திட்டங்களில் சேர்க்கப்படவில்லை. மிகவும் நிலையான அமர்வு சேமிப்பகத்துடன் கூடுதலாக, இந்தத் திட்டம் முழுமையாகப் பயன்படுத்தப்பட்டது "எல்லாவற்றையும் தேக்கி வைப்பது" கொள்கை memcached இல்: தரவுத்தளம் மற்றும் API சேவையகங்களுக்கான கோரிக்கைகளுக்கான பதில்கள், பல்வேறு கொடிகள், குறியீடு செயல்படுத்தலை ஒத்திசைப்பதற்கான பூட்டுகள் மற்றும் பல. அத்தகைய சூழ்நிலையில், மெம்கேச் செய்யப்பட்ட செயலிழப்பு பயன்பாட்டின் செயல்பாட்டிற்கு ஆபத்தானது. கூடுதலாக, கேச் இழப்பு கடுமையான விளைவுகளுக்கு வழிவகுக்கிறது: டிபிஎம்எஸ் சீம்களில் வெடிக்கத் தொடங்குகிறது, ஏபிஐ சேவைகள் கோரிக்கைகளைத் தடை செய்யத் தொடங்குகின்றன. நிலைமையை உறுதிப்படுத்த பல நிமிடங்கள் ஆகலாம், இந்த நேரத்தில் சேவை மிகவும் மெதுவாக இருக்கும் அல்லது முற்றிலும் கிடைக்காது.

நாங்கள் வழங்க வேண்டியிருந்தது சிறிய முயற்சியுடன் பயன்பாட்டை கிடைமட்டமாக அளவிடும் திறன், அதாவது மூலக் குறியீட்டில் குறைந்தபட்ச மாற்றங்கள் மற்றும் முழு செயல்பாடும் பாதுகாக்கப்படுகிறது. கேச் செயலிழப்பை எதிர்ப்பது மட்டுமல்லாமல், அதிலிருந்து தரவு இழப்பைக் குறைக்கவும் முயற்சிக்கவும்.

memcached தானே தவறு?

பொதுவாக, PHPக்கான memcached நீட்டிப்பு, பெட்டிக்கு வெளியே விநியோகிக்கப்பட்ட தரவு மற்றும் அமர்வு சேமிப்பகத்தை ஆதரிக்கிறது. நிலையான விசை ஹேஷிங்கிற்கான வழிமுறையானது, பல சேவையகங்களில் தரவை சமமாக விநியோகிக்க உங்களை அனுமதிக்கிறது, குழுவிலிருந்து ஒரு குறிப்பிட்ட சேவையகத்திற்கு ஒவ்வொரு குறிப்பிட்ட விசையையும் தனித்தனியாகக் குறிப்பிடுகிறது, மேலும் உள்ளமைக்கப்பட்ட தோல்விக் கருவிகள் கேச்சிங் சேவையின் உயர் கிடைக்கும் தன்மையை உறுதி செய்கின்றன (ஆனால், துரதிர்ஷ்டவசமாக, தகவல் இல்லை).

அமர்வு சேமிப்பகத்துடன் விஷயங்கள் கொஞ்சம் சிறப்பாக உள்ளன: நீங்கள் கட்டமைக்கலாம் memcached.sess_number_of_replicas, இதன் விளைவாக தரவு ஒரே நேரத்தில் பல சேவையகங்களில் சேமிக்கப்படும், மேலும் ஒரு மெம்கேச் செய்யப்பட்ட நிகழ்வு தோல்வியுற்றால், தரவு மற்றவர்களிடமிருந்து மாற்றப்படும். இருப்பினும், தரவு இல்லாமல் சேவையகம் மீண்டும் ஆன்லைனில் வந்தால் (வழக்கமாக மறுதொடக்கம் செய்த பிறகு நடக்கும்), சில விசைகள் அதற்குச் சாதகமாக மறுபகிர்வு செய்யப்படும். உண்மையில் இது அர்த்தம் அமர்வு தரவு இழப்பு, தவறினால் மற்றொரு பிரதிக்கு "செல்ல" வழி இல்லை என்பதால்.

நிலையான நூலகக் கருவிகள் முக்கியமாக நோக்கமாக உள்ளன கிடைமட்ட அளவிடுதல்: அவை தற்காலிக சேமிப்பை பிரம்மாண்டமான அளவுகளுக்கு அதிகரிக்கவும், வெவ்வேறு சேவையகங்களில் உள்ள குறியீட்டிலிருந்து அணுகலை வழங்கவும் உங்களை அனுமதிக்கின்றன. இருப்பினும், எங்கள் சூழ்நிலையில், சேமிக்கப்பட்ட தரவின் அளவு பல ஜிகாபைட்களுக்கு மேல் இல்லை, மேலும் ஒன்று அல்லது இரண்டு முனைகளின் செயல்திறன் போதுமானது. அதன்படி, வேலை நிலையில் குறைந்தபட்சம் ஒரு கேச் நிகழ்வையாவது பராமரிக்கும் போது, ​​மெம்கேச்டு கிடைப்பதை உறுதி செய்வதே பயனுள்ள நிலையான கருவிகள். இருப்பினும், இந்த வாய்ப்பை கூட பயன்படுத்திக் கொள்ள முடியவில்லை... திட்டத்தில் பயன்படுத்தப்பட்ட கட்டமைப்பின் பழமையான தன்மையை இங்கே நினைவுபடுத்துவது மதிப்புக்குரியது, அதனால்தான் சேவையகங்களின் தொகுப்புடன் வேலை செய்ய பயன்பாட்டைப் பெற முடியவில்லை. அமர்வு தரவு இழப்பு பற்றி மறந்துவிடக் கூடாது: பயனர்களின் பாரிய வெளியேற்றத்திலிருந்து வாடிக்கையாளரின் கண் இழுக்கப்பட்டது.

வெறுமனே அது தேவைப்பட்டது மெம்கேச் செய்யப்பட்ட மற்றும் பைபாஸ் பிரதிகளில் உள்ள பதிவுகளின் பிரதி தவறு அல்லது தவறு ஏற்பட்டால். இந்த உத்தியை செயல்படுத்த எங்களுக்கு உதவியது mcrouter.

mcrouter

இது ஃபேஸ்புக் தனது பிரச்சனைகளைத் தீர்க்க உருவாக்கிய மெம்கேச் செய்யப்பட்ட ரூட்டர் ஆகும். இது 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 மூன்று சேவையகங்களின் தொகுப்புடன், அனைத்து கோரிக்கைகளும் முதலில் மெம்கேச் செய்யப்பட்ட நிகழ்விற்கு வரும், மீதமுள்ளவை தரவு இல்லாத போது எஞ்சிய அடிப்படையில் கோரிக்கைகளைப் பெறும். அத்தகைய அணுகுமுறை வழிவகுக்கும் பட்டியலில் முதல் சர்வரில் அதிக சுமை, எனவே வெவ்வேறு வரிசைகளில் முகவரிகளுடன் மூன்று குளங்களை உருவாக்கி அவற்றை தோராயமாக தேர்ந்தெடுக்க முடிவு செய்யப்பட்டது.
  • மற்ற அனைத்து கோரிக்கைகளும் (இது ஒரு பதிவு) பயன்படுத்தி செயலாக்கப்படும் AllMajorityRoute. இந்த ஹேண்ட்லர் பூலில் உள்ள அனைத்து சேவையகங்களுக்கும் கோரிக்கைகளை அனுப்புகிறது மற்றும் குறைந்தது N/2 + 1 இன் பதில்களுக்காக காத்திருக்கிறது. பயன்பாட்டில் இருந்து AllSyncRoute இந்த முறைக்கு நேர்மறையான பதில் தேவை என்பதால், எழுதும் செயல்பாடுகளை கைவிட வேண்டியிருந்தது всех குழுவில் உள்ள சேவையகங்கள் - இல்லையெனில் அது திரும்பும் SERVER_ERROR. mcrouter கிடைக்கக்கூடிய தற்காலிக சேமிப்பில் தரவைச் சேர்க்கும் என்றாலும், அழைப்பு PHP செயல்பாடு ஒரு பிழை திரும்பும் மற்றும் அறிவிப்பை உருவாக்கும். AllMajorityRoute மிகவும் கண்டிப்பானது அல்ல, மேலும் மேலே விவரிக்கப்பட்ட சிக்கல்கள் இல்லாமல் பாதி யூனிட்களை சேவையிலிருந்து வெளியேற்ற அனுமதிக்கிறது.

முக்கிய குறைபாடு இந்தத் திட்டம் என்னவென்றால், கேச்சில் தரவு எதுவும் இல்லை என்றால், கிளையண்டின் ஒவ்வொரு கோரிக்கைக்கும் N கோரிக்கைகள் memcached க்கு உண்மையில் செயல்படுத்தப்படும். அனைவருக்கும் குளத்தில் உள்ள சேவையகங்கள். குளங்களில் உள்ள சேவையகங்களின் எண்ணிக்கையை நாம் இரண்டாகக் குறைக்கலாம்: சேமிப்பக நம்பகத்தன்மையை தியாகம் செய்வதுоஅதிக வேகம் மற்றும் கோரிக்கைகளிலிருந்து விடுபட்ட விசைகள் வரை குறைந்த சுமை.

NB: நீங்கள் mcrouter கற்கும் பயனுள்ள இணைப்புகளைக் காணலாம் விக்கியில் ஆவணங்கள் и திட்ட சிக்கல்கள் (மூடப்பட்டவை உட்பட), பல்வேறு கட்டமைப்புகளின் முழு களஞ்சியத்தையும் குறிக்கும்.

mcrouter ஐ உருவாக்குதல் மற்றும் இயக்குதல்

எங்கள் பயன்பாடு (மற்றும் மெம்கேச் செய்யப்பட்டது) குபெர்னெட்டஸில் இயங்குகிறது - அதன்படி, மெக்ரூட்டரும் அங்கு அமைந்துள்ளது. க்கு கொள்கலன் சட்டசபை நாம் பயன்படுத்த வெர்ஃப், அதற்கான கட்டமைப்பு இப்படி இருக்கும்:

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)

... மற்றும் அதை வரையவும் ஹெல்ம் விளக்கப்படம். சுவாரஸ்யமான விஷயம் என்னவென்றால், பிரதிகளின் எண்ணிக்கையின் அடிப்படையில் ஒரு config ஜெனரேட்டர் மட்டுமே உள்ளது (யாராவது மிகவும் லாகோனிக் மற்றும் நேர்த்தியான விருப்பம் இருந்தால், அதை கருத்துகளில் பகிர்ந்து கொள்ளுங்கள்):

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

கருத்தைச் சேர்