Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

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

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

13.05.2024

OpenSearch в тестовому оточенні

Як забезпечити кожному тесту чистий аркуш в OpenSearch? В теорії — просто. Проте щоб це ще й не гальмувало збірку, довелося попрацювати.


17.05.2024

Перевірка унікальності в OpenSearch

…А немає її! В ті чи інші причини. Певно, головним чином тому, що індексація відбувається асинхронно, а до індексації перевірки не буде.

Проте є один метод, перевірений часом. Це зробити унікальний ключ ідентифікатором. Таке працює в багатьох NoSQL базах, наприклад, в DynamoDB практично лягає в основу. Тільки з міркувань рівномірного розподілення значень в OpenSearch краще брати не прямо ключ (скажімо, URL сторінки), а хеш від нього.

(Взагалі підхід з використанням справжніх значень як ідентифікаторів називається “натуральні ключі” та був популярним в часи “голих” SQL баз. А з приходом ORM як головного методу доступу — занепав.)

Ідентифікатори в OpenSearch, звісно, унікальні. Але й тут криється нюанс - звичайна операція індексації не заборонить повторюваний ідентифікатор, а просто перезапише документ (тобто зробить “upsert”). А нам потрібна операція create.

Я вже натрапляв на проблему в тестах, що згенеровані фабрикою документи час від часу збігалися ідентифікаторами, вставлялися без create, та призводили до випадкових помилок.


01.06.2024

OpenSearch: база, де все відбувається не відразу

Нарешті зміг для себе зрозуміти, що мене понад усе дратує в роботі з OpenSearch: майже нічого в цій базі не відбувається синхронно. Я звик, що база даних є синхронною; звісно, реплікація займає час, але той вузол, з яким працюєш, все робить коли йому скажеш. В OpenSearch все не так.

Навіть з базовими діями — наприклад, індексацією одного документа — є спеціальний параметр refresh=wait_for, який змусить виклик чекати, поки документ не стане проіндексований. За замовчуванням індексація буде відкладена. Це відразу помічаєш у тестах, бо без цього параметра вони ніколи не будуть стабільними.

А коли маєш справу зі складнішими операціями, взагалі краще думати про них як про процеси; в деяких випадках — буквально. Наприклад, в PostgreSQL масове оновлення (UPDATE ... WHERE) теж може тривати навіть години, але таблиця може бути тільки у двох станах: не оновлена та оновлена. З OpenSearch масове оновлення опрацює скільки встигне та повернеться — далі запускай наново.

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

Все це добре, коли вас влаштовує кінцева узгодженість, а чи буде вона досягнена зараз, чи через хвилину — байдуже. Та це, певно, найбільша перешкода у використанні OpenSearch як традиційної бази даних.


12.02.2025

Оптимізація: треба йти глибше!

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

Вчора хотів написати пост “чому OpenSearch повільний, коли у вас надто багато шардів?” (Шард — це неподільний блок даних, як партиція; індекс — тобто колекція — складається з фіксованого набору шардів.) Всі радять робити шарди розміром у 10-50 Гб… але чи значить це, що робити їх меншими обовʼязково погано?

Виявилося, не дуже; дійсно, кожен шард коштує трохи памʼяті, але поки памʼять не вичерпана, додаткові шарди не суттєво впливають на швидкість операцій. Негативно — ні, але позитивно — теж ні, навіть попри те, що шард також є одиницею паралелізації. Бо щоб пришвидшити щось паралелізацією, потрібно більше ядер процесора, а не потоків.

Але це я знаю після того, як перевірив. А міг би залишитись із такою гадкою, витратити час на переформування індексів, та… нічого не отримати на заміну. Та це не перша та не остання ланка в розслідуванні! Перевіряти потрібно кожну.

Легко вказати на неприємну частину проєкту та сказати: проблема тут! (Мені, наприклад, доводилося витрачати час на алгоритмічну оптимізацію “некрасивого коду” там, де можна було обійтися як максимум кешем.) Але взагалі шукати причини — це ціле мистецтво. Треба знати, що важливо, що не важливо, та параноїдально собі не довіряти (що, до речі, називається науковим методом.)

Ото було колись — шукав, чому API повільний. Локально наче все було чудово, але більшість часу API проводив у серіалізації, тому я довго обирав оптимальний формат. А потім виявилося, що в продакшні є ще рукостискання TLS, та вся проблема зовсім не в серіалізації, а у встановленні підключення. Так що завжди перевіряти!


02.03.2025

Затримка оновлення в OpenSearch

В OpenSearch/ElasticSearch є така цікава особливість, що між внесенням змін та їхнім ефектом минає кілька секунд. Тобто буквально доведеться почекати, щоб побачити, що щось змінилось.

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

Зауважу, що затримка ніяк не є наслідком того, що OpenSearch є розподіленою базою. Навіть один індекс на одній машині буде оновлюватися так саме повільно. Взагалі OpenSearch оптимізований для великого масштабу, а на малому працює не набагато швидше. Також затримка не впливає на надійність — зміни нікуди не дінуться.

З досвідом традиційних СУБД це є повною нісенітницею. Проте типові використання OpenSearch - наприклад, аналіз журналів — не потребують моментального застосування змін. Будь-яка архітектура з OpenSearch всередині повинна розділяти запис та читання та передбачати ці затримки. Тому на роль головної бази - OLTP - вона фізично не підходить.