مدل ها و پیش بینی ها را بخوانید
Read Model یک جدول/نمایه/نمای مخصوص طراحی شده برای خواندن سریع برای یک سناریوی خاص محصول است. پروجکشن یک فرآیند است که رویدادهای منبع/تغییرات را به خواندن مدل به روز رسانی (معمولا upsert idemotent) تبدیل می کند. در رابطه با CQRS، این به شما اجازه می دهد تا هسته OLTP را بارگیری کنید و خواندن p95/p99 را تثبیت کنید و «طراوت» را کنترل کنید.
ایده های اصلی:- در صورت درخواست، نه یک «طرح جهانی».
- به روز رسانی به صورت تدریجی و idemotively.
- به طور صریح نظم و ثبات را مدیریت کنید.
1) هنگامی که به استفاده از مدل های خوانده شده (و زمانی که نه)
مناسب:- خواندن سنگین مکرر (پیوستن/تجمع/انواع) با تاخیر به روز رسانی قابل قبول است.
- داشبورد، کاتالوگ، صفحات فرود، «top-N»، فیدهای شخصی، لیست های جستجو.
- به اشتراک گذاری بار: نوشتن هسته - سخت، خواندن هواپیما - سریع و مقیاس پذیر.
- عملیات نیاز به سخت ثابت «در هر ورودی» (پول، منحصر به فرد). یک راه قوی وجود دارد.
2) طرح معماری (طرح کلامی)
1. منبع تغییرات: رویدادهای دامنه (منبع رویداد) یا CDC از OLTP.
2. خط لوله پروجکشن: تجزیه کننده → تجمع/عدم عادی → upsert idemotent.
3. خواندن فروشگاه: پایگاه داده/شاخص بهینه سازی شده برای پرس و جو (RDBMS، ستون، جستجو).
4. API/مشتری: سریع SELECT/GET، با ویژگی های «as_of/freshness».
3) طراحی مدل را بخوانید
با یک پرس و جو شروع کنید: کدام فیلدها، فیلترها، مرتب سازی، صفحه بندی، N بالا ؟
Denormalize: داده های ادغام شده (نام ها، مقادیر، وضعیت ها) را ذخیره کنید.
کلید های:- تقسیم بندی: توسط 'tenant _ id'، تاریخ، منطقه.
- کلید اصلی: کلید کسب و کار + سطل زمان (به عنوان مثال «( ، )» یا «( )»).
- شاخص ها: با مکرر که در آن/سفارش توسط.
- TTL/احتباس: برای موارد نمایش موقت (به عنوان مثال 90 روز)
4) به روز رسانی جریان و idemotency
Upsert Idempotent اساس ثبات طرح است.
شبه:sql
-- Projection table
CREATE TABLE read_orders (
tenant_id TEXT,
order_id UUID,
status TEXT,
total NUMERIC(12,2),
customer JSONB,
updated_at TIMESTAMP,
PRIMARY KEY (tenant_id, order_id)
);
-- Idempotent update by event
INSERT INTO read_orders(tenant_id, order_id, status, total, customer, updated_at)
VALUES (:tenant,:id,:status,:total,:customer,:ts)
ON CONFLICT (tenant_id, order_id) DO UPDATE
SET status = EXCLUDED. status,
total = EXCLUDED. total,
customer = COALESCE(EXCLUDED. customer, read_orders. customer),
updated_at = GREATEST(EXCLUDED. updated_at, read_orders. updated_at);
قوانین و مقررات:
- هر پیام یک نسخه/زمان را حمل می کند ؛ فقط «تازه یا برابر» (idempotency) را بپذیرید.
- برای aggregates (شمارنده، مبالغ) - ذخیره دولت و استفاده از به روز رسانی جابجایی (یا روش CRDT).
5) منبع تغییر: رویدادها در مقابل CDC
رویدادها (منابع رویداد): معانی غنی، ساخت پیش بینی های مختلف آسان است. تکامل مدارها مهم است.
CDC (تکرار منطقی): به سادگی به یک پایگاه داده موجود متصل شوید ؛ DML → نقشه برداری sobyty و فیلتر به روز رسانی سر و صدا مورد نیاز خواهد بود.
- تضمین تحویل (حداقل یک بار) و DLQ برای پیام های «سمی».
- سفارش توسط کلید (کلید پارتیشن = 'tenant _ id: entity _ id').
6) نظم، علیت و «طراوت»
ترتیب بر اساس کلید: رویدادهای یک شیء باید به صورت متوالی بیایند ؛ استفاده از پارتیشن بندی و نسخه ها
جلسه/علت: برای نویسنده برای دیدن تغییرات آنها (RYW)، نسخه های علامت گذاری در نمایش داده ها را منتقل کنید.
staleness محدود: بازگشت به عنوان _ از/' X-Data-Freshness 'و نگه داشتن SLO (به عنوان مثال p95 ≤ 60 درجه سانتیگراد)
7) دانه های افزایشی و N بالا
نمونه ای از سطل های فروش دقیقه:sql
CREATE TABLE read_sales_minute (
tenant_id TEXT,
bucket TIMESTAMP, -- toStartOfMinute revenue NUMERIC(14,2),
orders INT,
PRIMARY KEY (tenant_id, bucket)
);
-- Update by Event
INSERT INTO read_sales_minute(tenant_id, bucket, revenue, orders)
VALUES (:tenant,:bucket,:amount, 1)
ON CONFLICT (tenant_id, bucket) DO UPDATE
SET revenue = read_sales_minute. revenue + EXCLUDED. revenue,
orders = read_sales_minute. orders + 1;
برای بالا N:
- یک ویترین رتبه بندی شده را حفظ کنید (به عنوان مثال، با «درآمد DESC») و فقط موقعیت های تغییر یافته را به روز کنید (جدول heap/skiplist/limited).
- «پنجره» بالا را ذخیره کنید (به عنوان مثال، 100-1000 خط در هر بخش).
8) جستجو و طرح ریزی جغرافیایی
جستجو (ES/Opensearch): سند غیرقانونی، تبدیل خط لوله، نسخه سند = نسخه منبع.
Geo: فروشگاه 'POINT/LAT، LON'، کاشی های قبل از جمع آوری/quads.
9) چند مستاجر و مناطق
'tenant _ id' در کلید های طرح ریزی و حوادث مورد نیاز است.
عدالت: محدود کردن توان پیش بینی های هر مستاجر (WFQ/DRR) به طوری که «پر سر و صدا» بقیه را کند نمی کند.
اقامت: طرح ریزی در همان منطقه به عنوان هسته نوشتن زندگی می کند ؛ نمایشگاه های بین منطقه ای - aggregates/summaries.
10) قابلیت مشاهده و SLO
معیارها:- 'projection _ lag _ ms' (istochnik → vitrina), 'freshness _ age _ ms' (از زمان آخرین دلتا).
- توان به روز رسانی، نرخ خطا، نرخ DLQ، redrive-موفقیت.
- اندازه پنجره، تأخیر خواندن p95/p99.
- Теги: 'tenant _ id'، 'entity _ id'، 'event _ id'، 'version'، 'projection _ name'، 'تلاش'.
- حاشیه نویسی: ادغام راه حل ها، حذف نسخه های قدیمی.
11) کتاب های بازی (کتاب های اجرا)
1. رشد تاخیر: بررسی اتصال/کارگزار، افزایش احزاب، شامل اولویت بندی ویترین های کلیدی است.
2. بسیاری از خطاهای طرحواره: freeze redrive, migrate schemas (backfill), restart with a new version of the mapper.
3. DLQ تکرار: کاهش دسته، فعال کردن «سایه» رسیدگی، افزایش idemotency.
4. ناسازگاری پنجره: بازسازی پنجره ها از ورود به سیستم/منبع در هر پنجره (مستاجر/پارتیشن انتخابی).
5. کلید های داغ: محدود کردن رقابت با کلید، اضافه کردن صف های محلی، قرار دادن واحد در یک ویترین جداگانه.
12) شمارش کامل (بازسازی) و backfill
رویکرد:- مصرف را متوقف کنید (یا به نسخه جدیدی از ویترین بروید).
- محاسبه مجدد در دسته (توسط دسته/تاریخ/مستاجر).
- فعال کردن سوئیچ دو فاز: ابتدا «خواندن __ v2» را پر کنید، سپس به صورت اتمی مسیریابی خواندن را تغییر دهید.
13) تکامل مدارهای (نسخه)
'schema _ version' in events/documents.
طرح ریزی می تواند چندین نسخه، مهاجرت در پرواز را بخواند.
برای تغییرات عمده - یک ویترین جدید v2 و ترافیک قناری.
14) امنیت و دسترسی
به ارث بردن RLS/ACL از منبع ویترین را در دسترسی گسترده تر از داده های اصلی قرار ندهید.
ماسک PII در پیش بینی های مورد نیاز برای UX/تجزیه و تحلیل.
حسابرسی redrives/recounts/ویرایش کتابچه راهنمای کاربر.
15) قالب پیکربندی
yaml projections:
read_orders:
source: kafka. orders. events partition_key: "{tenant_id}:{order_id}"
idempotency: version_ts upsert:
table: read_orders conflict_keys: [tenant_id, order_id]
freshness_slo_ms: 60000 dlq:
topic: orders. events. dlq redrive:
batch: 500 rate_limit_per_sec: 50 read_sales_minute:
source: cdc. orders partition_key: "{tenant_id}:{bucket_minute}"
aggregate: increment retention_days: 90 limits:
per_tenant_parallelism: 4 per_key_serial: true observability:
metrics: [projection_lag_ms, dlq_rate, redrive_success, read_p95_ms]
16) خطاهای معمول
«یک ویترین برای همه موارد» → به روز رسانی های سنگین و بد P99.
عدم توانایی → تکراری/جهش در aggregates.
Dual-write به طور مستقیم به ویترین و OLTP → اختلافات.
صفر دید از طراوت → انتظارات متضاد با محصول.
بازسازی بدون سوئیچ دو فاز → «سوراخ» در پاسخ.
بدون پارتیشن بندی/شاخص → هزینه و رشد تاخیر.
17) دستور العمل های سریع
کاتالوگ/جستجو: نمایشگاه سند + upsert افزایشی، تاخیر ≤ 5-15 ثانیه، شاخص برای فیلتر.
داشبورد: مخازن دقیقه/ساعت، واحدهای SUM/COUNT، طراوت p95 ≤ 60 ثانیه.
نوار شخصی: طرح ریزی توسط کاربر + علت/RYW برای نویسنده، بازگشت به حافظه پنهان.
SaaS جهانی: نمایشگاه های منطقه ای، جمع آوری متقابل منطقه ای ؛ عدالت در هر مستاجر
18) چک لیست پیش فروش
- نمایشگاه برای یک درخواست خاص طراحی شده است ؛ شاخص ها و احزاب وجود دارد.
- منبع تغییر انتخاب شده (حوادث/CDC) ؛ تضمین تحویل و سفارش کلیدی.
- upsert idempotent با نسخه/زمان ؛ محافظت در برابر حوادث «قدیمی»
- SLO تازه تعریف شده و پاسخ داده شده است («به عنوان _ از/طراوت»).
- DLQ و انتشار امن پیکربندی شده ؛ playbook در بازسازی/backfill.
- سریال و عدالت در هر مستاجر.
- معیارهای تاخیر/خطا/تاخیر، هشدارهای p95/p99 و رشد DLQ.
- نسخه مدار و استراتژی مهاجرت (v2 + سوئیچ).
- سیاست های دسترسی/PII به ارث برده شده و معتبر هستند.
نتیجه گیری
مدل ها و پیش بینی ها یک شتاب دهنده مهندسی هستند: شما هزینه کمی برای «طراوت» و زیرساخت های جریان برای دریافت میلی ثانیه قابل پیش بینی و بارگیری هسته ضبط می پردازید. طراحی فروشگاه ها با توجه به درخواست شما، به روز رسانی بی نظیر، اندازه گیری تاخیر و به وضوح وعده طراوت - و API های خود را حتی با افزایش بار، داده ها و جغرافیا سریع باقی خواهد ماند.