Технологія — потужний інструмент, що перетворює ідеї на реальність. Однак іноді вона створює проблеми, які змушують нас переосмислити підхід. Нещодавно я зіткнувся з проблемою непослідовності даних під час реалізації системи для отримання деталей дзвінків з API та зберігання їх у базі даних. Цей досвід висвітлив важливий аспект проектування баз даних: атомарність та її зв'язок — або відсутність зв'язку — з такими сценаріями.
Що таке атомарність?
Атомарність є основним принципом транзакцій бази даних, що гарантує, що серія операцій у транзакції або виконується повністю, або не виконується взагалі. Це схоже на перемикач світла — він або увімкнений, або вимкнений, але ніколи не в проміжному стані. Це гарантує, що в системі не залишиться часткових або непослідовних даних, навіть якщо операція не завершиться.
Однак у контексті проблеми, з якою я зіткнувся, проблема полягала не стільки в атомарності, скільки в видаленні дублікатів даних і ідемпотентності. Давайте розберемося.
Проблема: Дублікати даних при викликах API
Уявіть, що ви створюєте систему для отримання деталей дзвінків з API та зберігання їх у базі даних. Кожен дзвінок має унікальний ідентифікатор (call_id
), що забезпечує його унікальність. Досить просто, правда?
Але потім виникає реальна проблема. API випадково викликається кілька разів, повертаючи той самий call_id
кілька разів. Без захисту база даних обробляє кожну відповідь як новий запис, створюючи дублікати.
Наприклад:
- Виклик API повертає
{ call_id: 12345 }
і зберігається в базі даних. - API викликається знову та повертає
{ call_id: 12345 }
ще раз. - База даних, не знаючи про дублікати, створює новий запис, хоча він ідентичний.
Результат? Непослідовні дані, витрачений обсяг пам'яті та потенційні помилки в подальших етапах.
Рішення: Галузеві стандарти для ідемпотентності та видалення дублікатів
Ось як я вирішив проблему, використовуючи ефективні, стандартні рішення:
1. Впровадьте унікальні обмеження в базі даних
Перша лінія захисту — забезпечити унікальність на рівні бази даних. Додавши унікальне обмеження на поле call_id
, база даних автоматично відхиляє дублікати.
Приклад:
CREATE TABLE call_details (
id SERIAL PRIMARY KEY,
call_id TEXT UNIQUE,
data JSONB
);
Це гарантує, що жодні два рядки не можуть мати однаковий call_id
. Якщо спробувати вставити дублікати, база даних викине помилку, що запобігає непослідовним даним.
2. Використовуйте ідемпотентну логіку API
На рівні застосунку, перед вставкою запису, перевірте, чи існує вже дзвінок з таким самим call_id
у базі даних.
Приклад на Node.js:
const existingCall = await db.collection('call_details').findOne({ call_id: apiResponse.call_id });
if (!existingCall) {
await db.collection('call_details').insertOne({ call_id: apiResponse.call_id, data: apiResponse });
} else {
console.log('Дублікований дзвінок виявлений. Пропускаємо вставку.');
}
Це запобігає непотрібним операціям з базою даних і забезпечує збереження кожного дзвінка лише один раз.
3. Обчислюйте хеші для видалення дублікатів
Якщо відповідь API містить великий обсяг даних, можна обчислити хеш всієї відповіді і використовувати його як унікальний ключ. Це корисно, коли потрібно виявити дублікати на основі вмісту даних, а не тільки за ID.
Приклад:
const crypto = require('crypto');
const hash = crypto.createHash('sha256').update(JSON.stringify(apiResponse)).digest('hex');
const existingRecord = await db.collection('call_details').findOne({ hash });
if (!existingRecord) {
await db.collection('call_details').insertOne({ hash, data: apiResponse });
}
Уроки, що я засвоїв
Цей досвід підтвердив кілька важливих уроків:
- Зрозумійте природу проблеми: хоча атомарність важлива для консистентності транзакцій, для цієї проблеми знадобилися стратегії ідемпотентності та видалення дублікатів.
2.
Обмеження бази даних — ваш надійний союзник: Унікальні обмеження забезпечують надійний захист від дублікатів. - Поєднуйте логіку застосунку та бази даних: Використовуйте обидва шари для створення стійкої системи.
Останні думки
Кожен розробник стикається з такими проблемами, де межа між технічними концепціями, як атомарність, ідемпотентність і видалення дублікатів, розмивається. Використовуючи найкращі практики галузі, ми не лише можемо вирішити ці проблеми, але й проектувати системи, які є масштабованими, надійними та ефективними.
Пам’ятайте, технологія потужна, але саме те, як ми її використовуємо, робить різницю. Якщо ви стикалися з подібними проблемами або маєте інші рішення, буду радий почитати ваші думки в коментарях!
Перекладено з: The Double-Call Dilemma: Handling API Data Consistency with Industry-Standard Solutions