برنامه نویسی

تضمین سازگاری داده ها با الگوی صندوق عقب تراکنش در AWS

مقدمه

در سیستم های توزیع شده ، تضمین سازگاری داده ها در سراسر خدمات بسیار مهم است. کی معاملات پایگاه داده و صف پیام اتمی نیستند ، شکست می تواند باعث ناسازگاری شود.

در الگوی صندوق عقب معامله تضمین کردن پایگاه داده می نویسد و انتشار پیام به صورت اتمی رخ می دهد، اجتناب از وقایع از دست رفته.

1. مشکل: بانک اطلاعاتی و پیام رسانی اتمی نیستند

یک سرویس سفارش را تصور کنید که:
داده های سفارش را به Amazon RDS (postgresql/mysql) می نویسد.
برای سایر خدمات (به عنوان مثال ، موجودی ، حمل و نقل) یک رویداد (سفارش) به آمازون SQS منتشر می کند.

🔥 سناریوی شکست:
این سرویس سفارش RDS را می نویسد
این سرویس نتوانسته است سفارش داده شده به SQS ❌ (خطای شبکه ، زمان بندی و غیره) را منتشر کند

💥 مشکل: سفارش در پایگاه داده ذخیره می شود ، اما سایر خدمات (موجودی ، حمل و نقل) هرگز این رویداد را دریافت نمی کنند.
🚨 ناسازگاری داده ها می توانند منجر به:
مشتریانی که بدون تحقق سفارش شارژ می شوند.
بدون به روزرسانی موجودی ، منجر به بیش از حد.
هیچ حمل و نقل ایجاد نشده و منجر به حمایت از تشدید می شود.

2. راه حل الگوی صندوق عقب معامله

صندوق عقب معامله AWS

🔹 مرحله 1: جدول صندوق عقب را تعریف کنید

CREATE TABLE order_outbox (
    id SERIAL PRIMARY KEY,
    order_id UUID NOT NULL,
    event_type TEXT NOT NULL,
    payload JSONB NOT NULL,
    created_at TIMESTAMP DEFAULT NOW(),
    processed_at TIMESTAMP NULL
);
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

🔹 مرحله 2: سفارش و رویداد را در یک معامله بنویسید (TypeScript)

import { Pool } from 'pg';
const pool = new Pool({ connectionString: "your-db-connection" });

async function placeOrder(orderId: string, customerId: string, totalPrice: number) {
    const client = await pool.connect();
    try {
        await client.query('BEGIN');
        await client.query("INSERT INTO orders (order_id, customer_id, total_price) VALUES ($1, $2, $3)",
            [orderId, customerId, totalPrice]);
        await client.query("INSERT INTO order_outbox (order_id, event_type, payload) VALUES ($1, $2, $3)",
            [orderId, "OrderPlaced", JSON.stringify({ orderId, customerId, totalPrice })]);
        await client.query('COMMIT');
    } catch (error) {
        await client.query('ROLLBACK');
        throw error;
    } finally {
        client.release();
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

🔹 مرحله 3: نظرسنجی و انتشار رویدادها (AWS Lambda / ECS وظیفه)

import { Pool } from 'pg';
import { SNS } from 'aws-sdk';
const pool = new Pool({ connectionString: "your-db-connection" });
const sns = new SNS();
const topicArn = "arn:aws:sns:us-east-1:your-account-id:order-events";

async function processOutbox() {
    const client = await pool.connect();
    try {
        const { rows } = await client.query("SELECT id, payload FROM order_outbox WHERE processed_at IS NULL");
        for (const event of rows) {
            try {
                await sns.publish({ TopicArn: topicArn, Message: JSON.stringify(event.payload) }).promise();
                await client.query("UPDATE order_outbox SET processed_at = NOW() WHERE id = $1", [event.id]);
            } catch (error) {
                console.error(`Failed to send event ${event.id}:`, error);
            }
        }
    } catch (error) {
        console.error("Error processing outbox:", error);
    } finally {
        client.release();
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

4. چرا ما فقط نمی توانیم با SNS معامله برگشتیم

sns و پایگاه داده ها معاملات را به اشتراک نمی گذارند

  • پشتیبانی از پایگاه داده (RDS ، PostgreSQL ، MySQL) معاملات اسیدیبشر
  • Amazon SNS یک سرویس خارجی است و نمی تواند بخشی از همان معامله باشد.

🔹 سناریوهای شکست بدون صندوق

  • DB INSERT موفق می شود ، SNS شکست می خورد:
    • سفارش در ذخیره می شود RDS
    • پیام SNS شکست می خورد
    • خدمات دیگر هرگز این رویداد را دریافت نمی کنند!
  • پیام SNS ارسال شده ، درج DB شکست می خورد:
    • پیام SNS ارسال شده
    • DB INSERT شکست می خورد
    • خدمات دیگر رویدادی را برای نظم مشاهده می کنند که وجود ندارد!

🔹 در صورت عدم موفقیت باید چه اتفاقی بیفتد؟

  • در صورت عدم موفقیت SNS: این رویداد در صندوق عقب باقی مانده و بعداً می توان آن را مجدداً مورد استفاده قرار داد.
  • در صورت عدم موفقیت معاملات DB: هیچ چیز متعهد نیست ، و اطمینان از سازگاری دارد.
  • مجدداً و صف های برگ برگ (DLQ): پیام های SNS ناموفق را می توان برای اشکال زدایی بیشتر به DLQ منتقل کرد.

5. موارد استفاده در دنیای واقعی

  • پردازش سفارش تجارت الکترونیکی: تضمین سفارشات به طور قابل اعتماد به خدمات موجودی ، صورتحساب و حمل و نقل تبلیغ می شود.
  • پردازش پرداخت: اطمینان از معاملات باعث ایجاد اعلان ها و گزارش های صحیح می شود.
  • ثبت نام کاربر: تضمین ایمیل یا اعلان ها پس از ثبت نام جدید کاربر به طور قابل اعتماد ارسال می شود.
  • رویدادهای دستگاه IoT: اطمینان از داده های تله متری از دستگاه ها به طور مداوم منتشر می شود.

6. تفاوت از الگوی حماسه

نشان صندوق عقب معامله الگوی حماسه
رویکرد تضمین انتشار رویداد اتمی است معاملات را به مراحل کوچکتر تقسیم می کند
مورد استفاده پیام های قابل اعتماد را تضمین می کند فرایندهای کسب و کار چند مرحله ای را کنترل می کند
پیچیدگی ساده تر پیچیده تر
نمونه انتشار رویداد قابل اعتماد به SNS رزرو هتل و پرواز با مراحل برگشت

پایان

در الگوی صندوق عقب معامله تضمین کردن قوام رویداد با انجام معاملات پایگاه داده و انتشار رویداد Atomic. اجرای آن با آمازون RDS ، SNS و Lambda/ECS فراهم می کند قابل اعتماد ، مقیاس پذیر و جدا شده راه حل.

🚀 آیا این الگوی را پیاده سازی کرده اید؟ تجربه خود را در نظرات به اشتراک بگذارید!

🔔 برای بینش بیشتر معماری AWS دنبال کنید!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا