Яка причина помилки Redis та як її впіймати?

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

errorMessage: Timed out attempting to find data in the correct node!,

errorType: Object RedisClusterException,

Всім привіт. Зіштовхнулися з командою з досить рідкісною помилкою Redis й зараз шукаємо ідеї як її розв’язати. Можливо ви вже стикалися з цим і зможете поділитися досвідом або ідеями?

Продукт

Додаток для знайомств, 30 млн користувачів.

Проблема

Помилка виникає в рандомний час, в різних місцях, з різними даними — тобто це різні івенти. Немає якоїсь характерної залежності. В пікові навантаження, проблема ескалюється, нам прилітає пачка помилок вище, яка говорить про втрачені івенти*, які недоотримали аналітики. Останнім часом таких кейсів стало доволі багато — наприклад, за вчора втратили майже 25 тис.

За добу, в середньому, транспортуємо 500 млн івентів, тож поки 25 тис не виглядають критично, але для аналітиків, втрачені івенти можуть бути важливі, плюс раніше таких втрат в нас не було.

Питання:

  1. Яка причина помилки Redis — чому він тут не може знайти запис у ноді?
  2. Як зрозуміти де саме проблема та як піймати цю помилку?

Гіпотеза

Ми з командою думаємо, що можливо це щось на інфраструктурному рівні й вже готуємо середовище навантажувального тестування.

Буду вам вдячний за ваші ідеї щодо відповідей на ці питання.

*Івенти — дії користувачів в додатку або відпрацювання якоїсь логіки після дії користувачів.

Redis ми використовуємо у якості черг для обробки наших івентів.

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

cluster_library.c
timeout: float, value in seconds (optional, default is 0 meaning it will use default_socket_timeout)
default_socket_timeout в php = 60s

Думаю у вас timeout заданий явно. Якщо там поставити 0.1, а ваш сервер нормально так навантажений (а php з цим дуже гарно справляеться), ви будете отримувати цю помилку.

Тому, на мою думку, проблема тут не в Redis. Варто глянути на навантаження php серверів в плані CPU. Ну або підніміть цей таймаут до комфортного вам рівня.

Якщо підозра на інфру:
Є щось в логах серверів — dmesg ? Ящо навантаження велике, можливо не вистачає сокетів
Є щось і логах редісів ?
Є можливість перевірити мережу, запустити щось по типу mtr redis_ip з сервера який робить запити на редіс. Якщо серверів декілька з редісом, то у screen і подивитись що з Loss%

errorMessage: Timed out attempting to find data in the correct node!,

Я так розумію це помилка з логів самого проекту — не з редіс логів ?

Він може знайти. Він пише, що йому не вистачає часу, щоб знайти. Можливо навіть, що він вже й знайшов, але ось на коректний запис у логи, що знайшов, все ок, якраз часу не вистачило.
P.S.
Якщо все так, то він тоді крутий.

1. Перевірте конфігурацію Redis: Переконайтеся, що Redis налаштований на правильну адресу та порт. Переконайтеся, що RedisClusterException не спричинений неправильними налаштуваннями Redis.

2. Перевірте стан Redis нод: Переконайтеся, що всі ноди Redis працюють належним чином та вони не мають ніяких проблем з доступом до даних.

3. Перевірте навантаження: Переконайтеся, що навантаження на Redis не перевищує його можливостей. Якщо ви спостерігаєте пікові навантаження, можливо, вам потрібно масштабувати вашу інфраструктуру Redis.

4. Моніторинг та логування: Налаштуйте моніторинг та логування Redis, щоб відслідковувати помилки та проблеми. Це допоможе вам зрозуміти, де саме виникає проблема та як її піймати.

5. Тестування навантаження: Створіть тестові навантаження, які можуть симулювати різні сценарії використання вашого додатка. Це допоможе вам виявити проблеми з Redis під час високого навантаження.

6. Перевірте версію Redis: Переконайтеся, що ви використовуєте останню версію Redis та всі необхідні патчі та оновлення встановлені.

Так, ми це все зробили. Але нажаль, ці всі поінти не відкрили корінь проблеми

У вас є якісь підстави вважати, що проблема саме в редісі, а не в конкретному клієнті (який ви, до речі, не назвали)?

Окей, якщо погуглити errorMessage дословно, то результати майже одностайно натякають на те, що мова йде про phpredis. Одразу гугляться дві проблеми (чи як канонічно issue перекладати українською?) на ГХ, одна з яких ні про що, а от в другій є цікавий комент: github.com/...​88#issuecomment-366702828

З нього виходить, що клієнт постійно отримує від сервера MOVED (зациклено, до таймауту). Що в свою чергу може відбуватись лише в двох випадках: або кластер постійно переміщує слот між нодами (що малоймовірно, враховуючи що мова йде про доволі малий час між запитами; в конкретноу випадку описаному в коменті це точно не так), або клієнт шле запити не туди.

В цьому моменті корисно зробити паузу та з’їсти твікс закреслено покурити документацію: redis.io/...​r-spec/#moved-redirection В документації є цікаві речі: «...The client is not required to, but should try to memorize that hash slot 3999 is served by 127.0.0.1:6381...»

Схоже на те, що даний конкретний клієнт дійсно має якусь реалізацію такого кешу, оновлення якого викликається в випадку якщо клієнт отримав MOVED.

Отже, гіпотеза така: через певні причини (варто покурити уважно документацію редіса, щоб зрозуміти які: Live reconfiguration? щось інше? чи це взагалі «не баг, а фіча»?) кластер переміщує деякі слоти на інші ноди, але клієнт не оновлює вчасно закешований мапінг (чи робить це з помилками). Скажімо, документація радить не оновлювати кеш «поштучно» по факту отримання MOVED, а апати конфіг кластера цілком за першого ж редіректа («...When a redirection is encountered, it is likely multiple slots were reconfigured rather than just one, so updating the client configuration as soon as possible is often the best strategy» — мається на увазі команда CLUSTER SHARDS), і на перший погляд дана конретна реалізація цієї рекомендації не дотримується (але постався до цього скептично: мені чесно влом копатись в коді детально, може воно десь і є).

АПД. Можна спробувати відтворити: підняти локально невеличкий кластер (якщо гіпотеза вірна, це не проблема кількості даних, це проблема імплементації кешування саме мапінгу слотів до нод), в одному процесі періодично форсити перекидання слотів між нодами, в іншому бомбити кластер запитами на пошук переміщуваних ключів. Якщо гіпотеза вірна і це якийсь бажек в оновлення кешу в клієнті, повинні піймати цей ексепшн скоріше рано ніж пізно.

Гарні гіпотези! Дякую! Продовжуємо дослідження

Ми вважаємо що проблема на інфраструктурному рівні

Ну... перша думка — збільшити таймаут та подивитися, як це впливає на поведінку.

Ну а так подивитися в сирцевий код redis, розібратися, де ця помилка виникає. Додати туди більше логування. Додати код для відлагодження цієї ситуації. Написати застосунок, який повністю емулює ситуацію у контрольованому середовищі та посаилає 500 млн. івентів.

Зі збільшеним таймаутом помилок менше але є. Навантажувальне середовище створили. Помилку змогли репродюсити. Продовжуємо пошук

Спробуйте відштовхнутись від іншого — проблема не в redis, а в аплікухі. Наприклад у драйвері до redis.

Так, так. Дивимось в інсфраструктуру.

В мене вІдсутня відповідь на запитання про Redis Cluster, але хочу дослідити як працює swiping на сайтах знайомств, формування черг на основі фільтрів, які БД використовувати тоді зможу оформити в статтю

Якщо вашій компанії це цікаво то дайте знати та поділіться досвідом

Дякую за пропозицію. Інформація під NDA

Але ж ви можете дати посилання на публічну статтю де цей функціонал описаний найкраще на вашу думку

Підписатись на коментарі