Блог

Әр серверге емес, бір рет жіберілетін ескертулер

Біздің операциялық ескертулердің бірі — жарияланған қолданба үшін "төмен несие" туралы — бізге күніне кем дегенде бір рет келуі керек. Бір түсте ол бес рет келді. Себебі: API-дің әр данасы қай ескертулерді бұрын жібергенін өз жадында сақтады, сондықтан екі сервер ескертуді екі рет жіберді, ал әр деплой сол жадты тазалап, оларға қайтадан жіберуге мүмкіндік берді. Дәл осы үлгі фондық жұмыстың да екі рет орындалуына әкеп соқты. Енді екеуі де ортақ сақтау арқылы үйлестіріледі және сақтау қолжетімсіз болса, қауіпсіз жағына қарай әрекет етеді.

Симптом

Mythex команданың назарын қажет ететін нәрсе болғанда ескертулер жібереді: қызмет құлады, жұмыс тоқтап қалды, немесе жарияланған қолданбаның несие балансы төмендеп барады. Әр ескертудің дедупликация терезесі бар — сол ескертудің бірнеше рет емес, бір рет жіберілетін кезеңі. Төмен несие ескертуі үшін бұл терезе 24 сағат.

Бір түсте бір ескертудің бес данасы бұл терезе ұстамай қалғанын білдірді. Одан да жаманы, олар әр жұп бір-бірінен шамамен 11 минут айырмашылықпен келді.

Неліктен бұлай болды

Біздің ескерту пакетіміз дедупликацияны жадта сақтады: "ескерту кілті → соңғы жіберілген уақыты" кестесі жұмыс істеп тұрған процестің ішінде. Бұл бір ғана процесс болып, ол ешқашан қайта іске қосылмаса жұмыс істейді. Өндірісте ондай жоқ:

  • Екі API репликасы. Өндірісте API-дің екі данасы жұмыс істейді. Әрқайсысының өз кестесі бар, сондықтан әрқайсысы ескертуді бір рет жіберді. Жұп осыдан шықты.
  • Деплойлар. Әр деплой екі репликаны бос кестесі бар жаңа процестермен алмастырады. Деплойдан кейін ескерту қайтадан жіберілді, яғни ол бұрын жіберілмегендей.

Әр жұптағы екі ескерту арасындағы шамамен 11 минуттық айырмашылық осы ескертуді туғызатын жұмыстан шықты. Ол екі репликада да жұмыс істейді және құлып алады, сондықтан репликалар кезекпен жеңіп шығады, әр бірі өз кезегі келгенде ескертуді көтереді.

Осы кодта екінші, тыныш қате бар еді. Кестенің шексіз өспеуі үшін ол 500 кілтке жеткенде өзін тазартатын: терезесіне қарамастан 15 минуттан ескі барлық жазбаны өшіретін. Жүктеме түскенде 24 сағаттық дедупликация он бес минутқа дейін ғана созылды.

Түзету

Әр ескерту үшін бір ортақ жазба

API ескерту жібермес бұрын оның дедупликация кілтін Redis-те талап етеді — екі репликаның да қосылатын, API қайта іске қосылғанда өшпейтін ортақ жадтық сақтау. Талап бір операция: "тек бұл кілт жоқ болса орнату, және оны терезе аяқталғанда мерзімі өткен деп белгілеу". Алдымен талап еткен репликa ескертуді жібереді; екіншісі кілтті бос емес деп тауып, үнсіз қалады. Деплойдан кейінгі жаңа процесс кілтті әлі де сол жерде табады.

Кілт пен терезе ескерту пакетінің бір ережесінен алынады, енді ол екі қабат арасында ортақ, сондықтан олар "бірдей ескерту" не екенін әр түрлі түсінбейді.

Сақтау қолжетімсіз болса — ашық қалдыру

Ең маңызды шешім Redis қолжетімсіз болғанда не істеу керектігі болды. Біз ескертуді бәрібір жіберуді таңдадық. Егер Redis өшсе немесе 1,5 секундта жауап бермесе, ескерту жіберіледі. Қайталанған ескерту — шу. Жіберілмеген ескерту — сізге хабар жетпеуі.

Ең ауыр ескерту, P0, дедупликациямен мүлдем ұсталмайды.

Әр жазбаның өз терезесі бар

Ескерту пакетінің өз жадтық дедупликациясында әр жазба енді терезесінің аяқталатын уақытын сақтайды, ал тазарту тек терезесі біткен жазбаларды өшіреді. 24 сағаттық кілт басқа ескерту қанша келсе де, 24 сағат бойы сақталады.

Сол ақау, басқа жерде

Дәл осы үлгі фондық жұмыстың да қос есе болуына себеп болды: біздің жұмыс орындарының күйін sandbox провайдерімізбен сәйкестендіріп отыратын қайта салыстыру (reconciliation) тапсырмасы. Әр жүріс аккаунттағы барлық sandbox-ты тізімдейді — өндірісте мыңдаған, шамамен бес секунд — және іске қосылған немесе тоқтатылған барлық жобаны. Екі репликада да бұл әр екі минут сайын жұмыс істеді.

Оның жазулары идемпотентті — оларды екі рет орындау бір рет орындаумен бірдей нәтиже береді — сондықтан ештеңе бұзылмады. Тек жұмыс екі есе көп болды. Енді әр екі минуттық терезе Redis-те біздің пайдалану есептегіштеріміз бұрын талап еткен сияқты талап етіледі, және жұмысты тек талап алған репликa орындайды. Redis қолжетімсіз болса, жүріс бәрібір орындалады: жұмысты екі рет істеу зиян емес, ал оны істемеу — иә.

Қалай сынадық

Тесттер нақты орнатуды модельдейді. Олар ескерту модулін "екі репликa" ретінде екі рет жүктеп, екеуін бір ортақ сақтауға бағыттайды, әрқайсысынан бірдей ескерту көтереді, содан кейін деплойдан кейінгі "үшінші таза дана" ретінде тағы бірін жүктеп, қайта көтереді. Нәтижесінде бір ескерту жіберіледі. Басқа тесттер басқа несие иесінің ескертуі әлі жіберілетінін, P0-ның екі репликадан да жіберілетінін, және сақтау өшкенде немесе уақыт асқанда да ескерту жіберілетінін тексереді. Тазарту түзетуінің өз тесті бар: 24 сағаттық кілт 20 минуттан кейін келген 600 басқа ескертуден аман шығады.

Қайта салыстыру тапсырмасы үшін екі репликa бір мезгілде, плюс сол терезедегі үшінші жүріс — бір ғана тізім шығады.

Осыдан не үйрендік

  • Жадтағы күй — әр процесске тән. Серверлер арасында шындық болуы керек нәрсе — "бір рет жіберілді", "бір рет орындалды" — оны бөлісетін жерде сақталуы керек.
  • Деплойлар — қайта іске қосулар. Келесі қайта іске қосылғанға дейін ғана сақталатын күй қалыпты жұмыс күнін де сақтамайды.
  • Қай жолмен құлайтынын шеш. Ескертулер үшін ортақ сақтау өшкенде ескерту аз емес, көп болуы керек.
  • Тек данаға емес, үлгіге қара. Ескерту айқын жағдай болды; қос есе жасалған қайта салыстыру тыныш шығын әкелген сол ақау болды.

Бұл Mythex ішінен көрінбейді. Платформаны қалай тұрақты ұстайтынымыз туралы көбірек білу үшін деплойларда 502 қатесін нөлге дейін қалай түсірдік және жетіспейтін swap файлы оқыңыз. Бірнеше серверді іске қосу идеясына жаңа болсаңыз, сервер деген не нұсқаулығы негіздерді түсіндіреді.

Mythex · Pricing · ЖИ көмегімен кез келген нәрсені жасаңыз · Сайттар мен қосымшаларға арналған үлгілер · Mythex салыстыруда · ЖИ-мен қосымша жасау сөздігі · ЖИ-мен қосымша жасауға арналған тегін құралдар · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)