Стендап Сьогодні
📢 Канал в Telegram @stendap_sogodni
🦣 @stendap_sogodni@shevtsov.me в Федиверсі

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

Пости з тегом #Redis

08.11.2024

Пошук перегонів даних в Go

🏁 Перегони даних — це коли два рівночасні процеси наввипередки оновлюють змінну, без відома про існування один одного (Мені не дуже зрозуміло, чому це називається перегонами.) В результаті отримуємо напівзіпсоване значення, в якому не врахована частина обчислень. Причому, звісно, рівночасність — непередбачуване явище, тому псування трапляється не кожного разу, а може взагалі чекати на високе навантаження в продакшні.

Одним словом. Шукав, чому випадково хибиться тест. Звузив причину до ділянки з використанням go-redis#ClusterClient.ForEachMaster - вона збирала значення з усіх серверів Redis в один масив. Спочатку думав, що тесту бракує очікування (ще одна класична причина випадкових хиб) та намагався виправити. Тут є легка перевірка, насправді: додай свідомо перебільшене очікування — може, 10 секунд — якщо це не виправляє тест, то проблема в іншому.

А потім помітив в документації по ForEachMaster, що вона-то рівночасна!. Звісно, через рівночасність зміст вихідного масиву був неповним, до того ж для кожного хибного випадку різний. Щоб виправити, я додав збір результатів через канал, але можна було б й мьютекс поставити. Такі API з прихованою рівночасністю мене обурюють, бо з ними хоч знаєш, а не зробиш правильно.

Тут я згадав, що в Go є детектор перегонів та раптом дізнався, що він не увімкнений за замовчуванням. Увімкнув — та дійсно, проблемний тест відразу “засвітився”. Хотів вже увімкнути для всіх тестів та локальних запусків, але виявив пару проблем з цим. По-перше, тести з детектором тривають в три рази більше. По-друге, як не дивно, але для компіляції з детектором потрібно увімкнути CGO, а це йде зі своїм пакетом ускладнень, як-от неможливість кроскомпілювати з macOS в Linux. Довелося відмовитись.

Нарешті, детектор знайшов ще одну гідну обурення ситуацію. Такого я ще не бачив. Офіційних серіалізатор Protobuf у JSON - protojson - додає у випадкові місця JSON пробіли. Та цього навіть не можна вимкнути!. Пояснюють вони це тим, що “споживачі мусять не очікувати чіткого формату”, оскільки команда Protobuf з ним ще не визначилася (sic!) Тому поки відстежуємо обговорення, якому вже 4 роки, а в тесті довелося декодувати JSON та порівнювати не рядком, а за змістом.


17.12.2025

Redis як спільна памʼять

Типово я звик бачити Redis як кеш чогось, ну або як нішеву базу даних (бо, знаєте, хоч Redis і тримає все в памʼяті, там є можливість зберігати зміст на диск.)

Але хочу звернути увагу на інше бачення: Redis є спільною оперативною памʼяттю між багатьма вашими процесами чи машинами.

Якось оця тема спільної памʼяті мало використовується. Ну так, в класичних вебзастосунках стану немає, а отже і в такій памʼяті потреби немає. Але на вебзастосунках світ не закінчується. Може ви гру пишете, чи чат, чи ще щось багатокористувацьке. Чи бота для месенджера.

Але й у вебзастосунках є стан. Класичний приклад: обмеження частоти запитів. В межах однієї машини його робити нема сенсу, зате лічильник можна покласти в Redis. Є навіть офіційний посібник.

Redis достатньо швидкий: лише на 1-2 порядки повільніше за звичайну оперативку, та, наприклад, на порядок швидше ніж локальний SSD. (Єдина порада - не складати в один запис надто багато. Краще, коли це буде окремий примітив чи невеличкий обʼєкт.)

Redis вже містить захист від рівночасного доступу, бо всі команди виконуються послідовно. Єдине, що має сенс поєднувати повʼязані команди у транзакцію (чи взагалі написати скрипт, бо й таке тут є.)

Може, у вас є сервіс, який спирається на внутрішній стан, та через це його ніяк не виходить масштабувати - або хоча б тримати в двох екземплярах для надійності. Redis прийде на допомогу.