درک کوئری‌های بلادرنگ در مقیاس بزرگ

برای راهنمایی در مورد مقیاس‌بندی برنامه بدون سرور خود فراتر از هزاران عملیات در ثانیه یا صدها هزار کاربر همزمان، این سند را مطالعه کنید. این سند شامل مباحث پیشرفته‌ای است که به شما در درک عمیق سیستم کمک می‌کند. اگر تازه کار با Cloud Firestore را شروع کرده‌اید، به جای آن به راهنمای شروع سریع مراجعه کنید.

Cloud Firestore و کیت‌های توسعه نرم‌افزار موبایل/وب فایربیس، مدلی قدرتمند برای توسعه برنامه‌های بدون سرور ارائه می‌دهند که در آن کد سمت کلاینت مستقیماً به پایگاه داده دسترسی پیدا می‌کند. این کیت‌ها به کلاینت‌ها اجازه می‌دهند تا به‌روزرسانی‌های داده‌ها را به‌صورت بلادرنگ دریافت کنند. شما می‌توانید از به‌روزرسانی‌های بلادرنگ برای ساخت برنامه‌های واکنش‌گرا که نیازی به زیرساخت سرور ندارند، استفاده کنید. اگرچه راه‌اندازی و اجرای چیزی بسیار آسان است، اما درک محدودیت‌های سیستم‌هایی که Cloud Firestore را تشکیل می‌دهند، به شما کمک می‌کند تا برنامه بدون سرور شما با افزایش ترافیک، مقیاس‌پذیر و عملکرد خوبی داشته باشد.

برای مشاوره در مورد مقیاس‌بندی برنامه خود، به بخش‌های زیر مراجعه کنید.

یک مکان پایگاه داده نزدیک به کاربران خود انتخاب کنید

نمودار زیر معماری یک برنامه بلادرنگ را نشان می‌دهد:

مثال معماری برنامه بلادرنگ

وقتی برنامه‌ای که روی دستگاه کاربر (موبایل یا وب) در حال اجرا است، اتصالی به Cloud Firestore برقرار می‌کند، این اتصال به یک سرور Frontend Cloud Firestore در همان منطقه‌ای که پایگاه داده شما در آن قرار دارد، هدایت می‌شود. به عنوان مثال، اگر پایگاه داده شما در us-east1 باشد، اتصال به یک سرور Frontend Cloud Firestore نیز در us-east1 می‌رود. این اتصالات طولانی مدت هستند و تا زمانی که صریحاً توسط برنامه بسته نشوند، باز می‌مانند. Frontend داده‌ها را از سیستم‌های ذخیره‌سازی Cloud Firestore زیرین می‌خواند.

فاصله بین موقعیت فیزیکی کاربر و محل پایگاه داده Cloud Firestore بر میزان تأخیر کاربر تأثیر می‌گذارد. به عنوان مثال، کاربری در هند که برنامه‌اش با پایگاه داده‌ای در منطقه Google Cloud در آمریکای شمالی ارتباط برقرار می‌کند، ممکن است تجربه کندتری داشته باشد و برنامه نسبت به زمانی که پایگاه داده در نزدیکی او قرار دارد، مانند هند یا بخش دیگری از آسیا، سرعت کمتری داشته باشد.

طراحی برای قابلیت اطمینان

مباحث زیر قابلیت اطمینان برنامه شما را بهبود می‌بخشند یا بر آن تأثیر می‌گذارند:

فعال کردن حالت آفلاین

کیت‌های توسعه نرم‌افزار Firebase، پایداری داده‌های آفلاین را فراهم می‌کنند. اگر برنامه روی دستگاه کاربر نتواند به Cloud Firestore متصل شود، برنامه با کار با داده‌های ذخیره‌شده محلی، قابل استفاده باقی می‌ماند. این امر دسترسی به داده‌ها را حتی زمانی که کاربران با اتصال اینترنت پرنوسان مواجه می‌شوند یا دسترسی کامل را برای چند ساعت یا چند روز از دست می‌دهند، تضمین می‌کند. برای جزئیات بیشتر در مورد حالت آفلاین، به بخش «فعال کردن داده‌های آفلاین» مراجعه کنید.

درک تلاش‌های مجدد خودکار

کیت‌های توسعه نرم‌افزار (SDK) فایربیس (Firebase SDK) عملیات تلاش مجدد (retry) و برقراری مجدد اتصالات قطع‌شده را انجام می‌دهند. این امر به رفع خطاهای گذرا ناشی از راه‌اندازی مجدد سرورها یا مشکلات شبکه بین کلاینت و پایگاه داده کمک می‌کند.

بین مکان‌های منطقه‌ای و چند منطقه‌ای یکی را انتخاب کنید

هنگام انتخاب بین مکان‌های منطقه‌ای و چند منطقه‌ای، چندین بده‌بستان وجود دارد. تفاوت اصلی در نحوه تکثیر داده‌ها است. این موضوع تضمین دسترسی‌پذیری برنامه شما را تعیین می‌کند. یک نمونه چند منطقه‌ای، قابلیت اطمینان سرویس‌دهی قوی‌تری را ارائه می‌دهد و دوام داده‌های شما را افزایش می‌دهد، اما بده‌بستان هزینه است.

سیستم پرس و جو در زمان واقعی را درک کنید

کوئری‌های بلادرنگ، که به آنها شنونده‌های اسنپ‌شات نیز گفته می‌شود، به برنامه اجازه می‌دهند تا به تغییرات در پایگاه داده گوش دهد و به محض تغییر داده‌ها، اعلان‌های با تأخیر کم دریافت کند. یک برنامه می‌تواند با نظرسنجی دوره‌ای از پایگاه داده برای به‌روزرسانی‌ها، به همان نتیجه برسد، اما اغلب کندتر، گران‌تر و به کد بیشتری نیاز دارد. برای مثال‌هایی از نحوه تنظیم و استفاده از کوئری‌های بلادرنگ، به «دریافت به‌روزرسانی‌های بلادرنگ» مراجعه کنید. بخش‌های بعدی به جزئیات نحوه کار شنونده‌های اسنپ‌شات می‌پردازند و برخی از بهترین شیوه‌ها را برای مقیاس‌بندی کوئری‌های بلادرنگ با حفظ عملکرد شرح می‌دهند.

دو کاربر را تصور کنید که از طریق یک برنامه پیام‌رسان ساخته شده با یکی از SDK های موبایل به Cloud Firestore متصل می‌شوند.

کلاینت A برای افزودن و به‌روزرسانی اسناد در مجموعه‌ای به نام chatroom در پایگاه داده می‌نویسد:

collection chatroom:
    document message1:
      from: 'Sparky'
      message: 'Welcome to Cloud Firestore!'

    document message2:
      from: 'Santa'
      message: 'Presents are coming'

کلاینت B با استفاده از یک شنونده‌ی اسنپ‌شات، به به‌روزرسانی‌های همان مجموعه گوش می‌دهد. هر زمان که کسی پیام جدیدی ایجاد کند، کلاینت B فوراً اعلان دریافت می‌کند. نمودار زیر معماری پشت یک شنونده‌ی اسنپ‌شات را نشان می‌دهد:

معماری اتصال شنونده اسنپ‌شات

توالی رویدادهای زیر زمانی اتفاق می‌افتد که کلاینت B یک snapshot listener را به پایگاه داده متصل می‌کند:

  1. کلاینت B با فراخوانی onSnapshot(collection("chatroom")) از طریق Firebase SDK، اتصالی به Cloud Firestore برقرار می‌کند و یک شنونده (listener) ثبت می‌کند. این شنونده می‌تواند ساعت‌ها فعال بماند.
  2. رابط کاربری Cloud Firestore از سیستم ذخیره‌سازی زیربنایی برای بوت‌استرپ کردن مجموعه داده‌ها پرس‌وجو می‌کند. این پرس‌وجو کل مجموعه نتایج اسناد منطبق را بارگذاری می‌کند. ما به این پرس‌وجو، پرس‌وجوی نمونه‌برداری (polling query) می‌گوییم. سپس سیستم ، قوانین امنیتی Firebase پایگاه داده را ارزیابی می‌کند تا تأیید کند که کاربر می‌تواند به این داده‌ها دسترسی داشته باشد. اگر کاربر مجاز باشد، پایگاه داده داده‌ها را به کاربر بازمی‌گرداند.
  3. سپس درخواست کلاینت B به حالت شنود (listening mode) می‌رود. شنودکننده در یک کنترل‌کننده اشتراک (subscription handler) ثبت می‌شود و منتظر به‌روزرسانی داده‌ها می‌ماند.
  4. اکنون کلاینت A یک عملیات نوشتن برای تغییر یک سند ارسال می‌کند.
  5. پایگاه داده، تغییر سند را در سیستم ذخیره‌سازی خود ثبت می‌کند.
  6. از نظر تراکنشی، سیستم همان به‌روزرسانی را در یک گزارش تغییرات داخلی ثبت می‌کند. این گزارش تغییرات، ترتیب دقیقی از تغییرات را هنگام وقوع تعیین می‌کند.
  7. در عوض، فایل تغییرات، داده‌های به‌روزرسانی‌شده را به مجموعه‌ای از کنترل‌کننده‌های اشتراک ارسال می‌کند.
  8. یک تطبیق‌دهنده‌ی پرس‌وجوی معکوس اجرا می‌شود تا ببیند آیا سند به‌روزرسانی‌شده با هیچ یک از شنوندگان اسنپ‌شات ثبت‌شده‌ی فعلی مطابقت دارد یا خیر. در این مثال، سند با شنوندگان اسنپ‌شات کلاینت B مطابقت دارد. همانطور که از نامش پیداست، می‌توانید تطبیق‌دهنده‌ی پرس‌وجوی معکوس را به عنوان یک پرس‌وجوی معمولی پایگاه داده در نظر بگیرید که به صورت معکوس انجام می‌شود. به جای جستجو در اسناد برای یافتن مواردی که با یک پرس‌وجو مطابقت دارند، به طور مؤثر در پرس‌وجوها جستجو می‌کند تا مواردی را که با یک سند ورودی مطابقت دارند، پیدا کند. پس از یافتن یک تطابق، سیستم سند مورد نظر را به شنوندگان اسنپ‌شات ارسال می‌کند. سپس سیستم قوانین امنیتی Firebase پایگاه داده را ارزیابی می‌کند تا اطمینان حاصل شود که فقط کاربران مجاز داده‌ها را دریافت می‌کنند.
  9. سیستم به‌روزرسانی سند را به SDK روی دستگاه کلاینت B ارسال می‌کند و فراخوانی onSnapshot فعال می‌شود. اگر پایداری محلی فعال باشد، SDK به‌روزرسانی را در حافظه پنهان محلی نیز اعمال می‌کند.

بخش کلیدی مقیاس‌پذیری Cloud Firestore به خروجی از گزارش تغییرات تا کنترل‌کننده‌های اشتراک و سرورهای frontend بستگی دارد. خروجی به یک تغییر داده اجازه می‌دهد تا به طور موثر منتشر شود تا به میلیون‌ها پرس‌وجوی بلادرنگ و کاربران متصل خدمت‌رسانی کند. Cloud Cloud Firestore با اجرای کپی‌های زیادی از همه این اجزا در چندین منطقه (یا چندین منطقه در صورت استقرار چند منطقه‌ای)، به دسترسی‌پذیری و مقیاس‌پذیری بالایی دست می‌یابد.

شایان ذکر است که تمام عملیات خواندن صادر شده از SDK های موبایل و وب از مدل بالا پیروی می‌کنند. آنها یک پرس و جوی نمونه‌برداری (polling query) و به دنبال آن حالت گوش دادن (listening mode) را برای حفظ ضمانت‌های سازگاری انجام می‌دهند. این امر در مورد شنونده‌های بلادرنگ، فراخوانی‌ها برای بازیابی یک سند و پرس و جوهای یک‌باره نیز صدق می‌کند. می‌توانید بازیابی‌های تک سند و پرس و جوهای یک‌باره را به عنوان شنونده‌های کوتاه‌مدت snapshot listeners در نظر بگیرید که محدودیت‌های مشابهی در مورد عملکرد دارند.

بهترین شیوه‌ها را برای مقیاس‌بندی کوئری‌های بلادرنگ به کار ببرید

برای طراحی کوئری‌های مقیاس‌پذیر و بلادرنگ، از بهترین شیوه‌های زیر استفاده کنید.

ترافیک بالای نوشتن در سیستم را درک کنید

این بخش به شما کمک می‌کند تا بفهمید سیستم چگونه به تعداد فزاینده درخواست‌های نوشتن پاسخ می‌دهد.

گزارش‌های تغییرات Cloud Firestore که کوئری‌های بلادرنگ را هدایت می‌کنند، با افزایش ترافیک نوشتن، به طور خودکار به صورت افقی مقیاس‌بندی می‌شوند. با افزایش نرخ نوشتن برای یک پایگاه داده فراتر از آنچه یک سرور می‌تواند مدیریت کند، گزارش تغییرات بین چندین سرور تقسیم می‌شود و پردازش کوئری شروع به مصرف داده‌ها از چندین کنترل‌کننده اشتراک به جای یک سرور می‌کند. از دیدگاه کلاینت و SDK، همه اینها شفاف است و هنگام وقوع تقسیم‌بندی‌ها، هیچ اقدامی از برنامه لازم نیست. نمودار زیر نحوه مقیاس‌بندی کوئری‌های بلادرنگ را نشان می‌دهد:

معماری خروجی گزارش تغییرات

مقیاس‌بندی خودکار به شما امکان می‌دهد ترافیک نوشتن خود را بدون محدودیت افزایش دهید، اما با افزایش ترافیک، ممکن است سیستم برای پاسخگویی مدتی طول بکشد. برای جلوگیری از ایجاد یک نقطه داغ نوشتن، توصیه‌های قانون ۵-۵-۵ را دنبال کنید. Key Visualizer ابزاری مفید برای تجزیه و تحلیل نقاط داغ نوشتن است.

بسیاری از برنامه‌ها رشد ارگانیک قابل پیش‌بینی دارند که Cloud Firestore می‌تواند بدون اقدامات احتیاطی آن را در خود جای دهد. با این حال، حجم کارهای دسته‌ای مانند وارد کردن یک مجموعه داده بزرگ، می‌تواند نوشتن‌ها را خیلی سریع افزایش دهد. هنگام طراحی برنامه خود، از منبع ترافیک نوشتن خود آگاه باشید.

درک کنید که چگونه می‌نویسند و می‌خوانند با هم تعامل دارند

می‌توانید سیستم کوئری بلادرنگ را به عنوان یک خط لوله در نظر بگیرید که عملیات نوشتن را به خوانندگان متصل می‌کند. هر زمان که یک سند ایجاد، به‌روزرسانی یا حذف می‌شود، تغییر از سیستم ذخیره‌سازی به شنوندگان ثبت‌شده فعلی منتشر می‌شود. ساختار گزارش تغییرات Cloud Firestore ثبات قوی را تضمین می‌کند، به این معنی که برنامه شما هرگز اعلان‌هایی از به‌روزرسانی‌هایی که در مقایسه با زمانی که پایگاه داده تغییرات داده‌ها را ثبت کرده است، نامرتب هستند، دریافت نمی‌کند. این امر با حذف موارد حاشیه‌ای پیرامون ثبات داده‌ها، توسعه برنامه را ساده می‌کند.

این خط لوله متصل به این معنی است که یک عملیات نوشتن که باعث ایجاد نقاط حساس یا رقابت قفل می‌شود، می‌تواند بر عملیات خواندن تأثیر منفی بگذارد. هنگامی که عملیات نوشتن با شکست مواجه می‌شود یا با مشکل مواجه می‌شود، ممکن است عملیات خواندن در انتظار داده‌های سازگار از گزارش تغییرات متوقف شود. اگر این اتفاق در برنامه شما رخ دهد، ممکن است هم عملیات نوشتن کند و هم زمان پاسخ کند مرتبط برای پرس‌وجوها را مشاهده کنید. اجتناب از نقاط حساس، کلید جلوگیری از این مشکل است.

اسناد و عملیات نوشتن را کوچک نگه دارید

هنگام ساخت برنامه‌هایی با استفاده از snapshot listeners، معمولاً می‌خواهید کاربران به سرعت از تغییرات داده‌ها مطلع شوند. برای دستیابی به این هدف، سعی کنید همه چیز را کوچک نگه دارید. سیستم می‌تواند اسناد کوچک با ده‌ها فیلد را خیلی سریع از طریق سیستم ارسال کند. اسناد بزرگتر با صدها فیلد و داده‌های حجیم، زمان بیشتری برای پردازش نیاز دارند.

به همین ترتیب، برای کم کردن تأخیر، از عملیات‌های کوتاه و سریع commit و write استفاده کنید. دسته‌های بزرگ ممکن است از دیدگاه نویسنده، توان عملیاتی بالاتری به شما بدهند، اما در واقع ممکن است زمان اعلان برای snapshot listeners را افزایش دهند. این اغلب در مقایسه با استفاده از سایر سیستم‌های پایگاه داده که در آنها ممکن است از batching برای بهبود عملکرد استفاده کنید، متناقض است.

از شنوندگان کارآمد استفاده کنید

با افزایش نرخ نوشتن برای پایگاه داده شما، Cloud Firestore پردازش داده‌ها را بین سرورهای زیادی تقسیم می‌کند. الگوریتم شاردینگ Cloud Firestore سعی می‌کند داده‌ها را از یک مجموعه یا گروه مجموعه یکسان در یک سرور changelog یکسان قرار دهد. این سیستم سعی می‌کند توان عملیاتی نوشتن ممکن را به حداکثر برساند و در عین حال تعداد سرورهای درگیر در پردازش یک پرس‌وجو را تا حد امکان کم نگه دارد.

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

برای جلوگیری از این پاسخ‌های کندتر، طرحواره و برنامه خود را طوری طراحی کنید که سیستم بتواند بدون مراجعه به سرورهای مختلف، به شنوندگان (listeners) خدمت‌رسانی کند. شاید بهتر باشد داده‌های خود را به مجموعه‌های کوچک‌تر با نرخ نوشتن پایین‌تر تقسیم کنید.

این شبیه به تفکر در مورد کوئری‌های عملکردی در یک پایگاه داده رابطه‌ای است که نیاز به اسکن کامل جدول دارند. در یک پایگاه داده رابطه‌ای، کوئری‌ای که نیاز به اسکن کامل جدول دارد، معادل یک شنونده اسنپ‌شات است که یک مجموعه با ریزش بالا را تماشا می‌کند. این کوئری ممکن است در مقایسه با کوئری‌ای که پایگاه داده می‌تواند با استفاده از یک شاخص خاص‌تر به آن پاسخ دهد، کندتر عمل کند. یک کوئری با شاخص خاص‌تر مانند یک شنونده اسنپ‌شات است که یک سند واحد یا مجموعه‌ای را که کمتر تغییر می‌کند، تماشا می‌کند. شما باید برنامه خود را بارگذاری کنید تا به بهترین شکل رفتار و نیاز مورد استفاده خود را درک کنید.

نظرسنجی‌ها را سریع نگه دارید

یکی دیگر از بخش‌های کلیدی کوئری‌های واکنش‌گرای بلادرنگ، اطمینان از سریع و کارآمد بودن کوئری نمونه‌برداری (polling query) برای بوت‌استرپ کردن داده‌ها است. اولین باری که یک شنونده‌ی اسنپ‌شات جدید متصل می‌شود، شنونده باید کل مجموعه نتایج را بارگذاری کرده و آن را به دستگاه کاربر ارسال کند. کوئری‌های کند، واکنش‌پذیری برنامه‌ی شما را کاهش می‌دهند. این شامل کوئری‌هایی می‌شود که سعی می‌کنند اسناد زیادی را بخوانند یا کوئری‌هایی که از ایندکس‌های مناسب استفاده نمی‌کنند.

یک شنونده همچنین ممکن است تحت برخی شرایط از حالت گوش دادن به حالت نظرسنجی برگردد. این اتفاق به طور خودکار رخ می‌دهد و برای SDKها و برنامه شما شفاف است. شرایط زیر ممکن است باعث ایجاد حالت نظرسنجی شود:

اگر کوئری‌های نظرسنجی شما به اندازه کافی سریع باشند، وضعیت نظرسنجی برای کاربران برنامه شما شفاف می‌شود.

به شنوندگان با عمر طولانی توجه کنید

باز کردن و زنده نگه داشتن شنونده‌ها تا حد امکان، اغلب مقرون به صرفه‌ترین راه برای ساخت برنامه‌ای است که از Cloud Firestore استفاده می‌کند. هنگام استفاده از Cloud Firestore ، هزینه اسنادی که به برنامه شما بازگردانده می‌شوند، از شما دریافت می‌شود و نه برای حفظ یک اتصال باز. یک شنونده اسنپ‌شات با عمر طولانی، فقط داده‌هایی را که برای ارائه پرس‌وجو در طول عمر خود نیاز دارد، می‌خواند. این شامل یک عملیات اولیه نمونه‌برداری و به دنبال آن اعلان‌هایی است که هنگام تغییر داده‌ها ارسال می‌شوند. از سوی دیگر، پرس‌وجوهای یک‌باره، داده‌هایی را که ممکن است از آخرین اجرای پرس‌وجو توسط برنامه تغییر نکرده باشند، دوباره می‌خوانند.

در مواردی که برنامه شما باید نرخ بالایی از داده مصرف کند، ممکن است شنونده‌های snapshot مناسب نباشند. به عنوان مثال، اگر مورد استفاده شما اسناد زیادی را در هر ثانیه از طریق یک اتصال برای مدت زمان طولانی ارسال می‌کند، بهتر است از کوئری‌های one-shot که با فرکانس پایین‌تری اجرا می‌شوند، استفاده کنید.

قدم بعدی چیست؟

،

برای راهنمایی در مورد مقیاس‌بندی برنامه بدون سرور خود فراتر از هزاران عملیات در ثانیه یا صدها هزار کاربر همزمان، این سند را مطالعه کنید. این سند شامل مباحث پیشرفته‌ای است که به شما در درک عمیق سیستم کمک می‌کند. اگر تازه کار با Cloud Firestore را شروع کرده‌اید، به جای آن به راهنمای شروع سریع مراجعه کنید.

Cloud Firestore و کیت‌های توسعه نرم‌افزار موبایل/وب فایربیس، مدلی قدرتمند برای توسعه برنامه‌های بدون سرور ارائه می‌دهند که در آن کد سمت کلاینت مستقیماً به پایگاه داده دسترسی پیدا می‌کند. این کیت‌ها به کلاینت‌ها اجازه می‌دهند تا به‌روزرسانی‌های داده‌ها را به‌صورت بلادرنگ دریافت کنند. شما می‌توانید از به‌روزرسانی‌های بلادرنگ برای ساخت برنامه‌های واکنش‌گرا که نیازی به زیرساخت سرور ندارند، استفاده کنید. اگرچه راه‌اندازی و اجرای چیزی بسیار آسان است، اما درک محدودیت‌های سیستم‌هایی که Cloud Firestore را تشکیل می‌دهند، به شما کمک می‌کند تا برنامه بدون سرور شما با افزایش ترافیک، مقیاس‌پذیر و عملکرد خوبی داشته باشد.

برای مشاوره در مورد مقیاس‌بندی برنامه خود، به بخش‌های زیر مراجعه کنید.

یک مکان پایگاه داده نزدیک به کاربران خود انتخاب کنید

نمودار زیر معماری یک برنامه بلادرنگ را نشان می‌دهد:

مثال معماری برنامه بلادرنگ

وقتی برنامه‌ای که روی دستگاه کاربر (موبایل یا وب) در حال اجرا است، اتصالی به Cloud Firestore برقرار می‌کند، این اتصال به یک سرور Frontend Cloud Firestore در همان منطقه‌ای که پایگاه داده شما در آن قرار دارد، هدایت می‌شود. به عنوان مثال، اگر پایگاه داده شما در us-east1 باشد، اتصال به یک سرور Frontend Cloud Firestore نیز در us-east1 می‌رود. این اتصالات طولانی مدت هستند و تا زمانی که صریحاً توسط برنامه بسته نشوند، باز می‌مانند. Frontend داده‌ها را از سیستم‌های ذخیره‌سازی Cloud Firestore زیرین می‌خواند.

فاصله بین موقعیت فیزیکی کاربر و محل پایگاه داده Cloud Firestore بر میزان تأخیر کاربر تأثیر می‌گذارد. به عنوان مثال، کاربری در هند که برنامه‌اش با پایگاه داده‌ای در منطقه Google Cloud در آمریکای شمالی ارتباط برقرار می‌کند، ممکن است تجربه کندتری داشته باشد و برنامه نسبت به زمانی که پایگاه داده در نزدیکی او قرار دارد، مانند هند یا بخش دیگری از آسیا، سرعت کمتری داشته باشد.

طراحی برای قابلیت اطمینان

مباحث زیر قابلیت اطمینان برنامه شما را بهبود می‌بخشند یا بر آن تأثیر می‌گذارند:

فعال کردن حالت آفلاین

کیت‌های توسعه نرم‌افزار Firebase، پایداری داده‌های آفلاین را فراهم می‌کنند. اگر برنامه روی دستگاه کاربر نتواند به Cloud Firestore متصل شود، برنامه با کار با داده‌های ذخیره‌شده محلی، قابل استفاده باقی می‌ماند. این امر دسترسی به داده‌ها را حتی زمانی که کاربران با اتصال اینترنت پرنوسان مواجه می‌شوند یا دسترسی کامل را برای چند ساعت یا چند روز از دست می‌دهند، تضمین می‌کند. برای جزئیات بیشتر در مورد حالت آفلاین، به بخش «فعال کردن داده‌های آفلاین» مراجعه کنید.

درک تلاش‌های مجدد خودکار

کیت‌های توسعه نرم‌افزار (SDK) فایربیس (Firebase SDK) عملیات تلاش مجدد (retry) و برقراری مجدد اتصالات قطع‌شده را انجام می‌دهند. این امر به رفع خطاهای گذرا ناشی از راه‌اندازی مجدد سرورها یا مشکلات شبکه بین کلاینت و پایگاه داده کمک می‌کند.

بین مکان‌های منطقه‌ای و چند منطقه‌ای یکی را انتخاب کنید

هنگام انتخاب بین مکان‌های منطقه‌ای و چند منطقه‌ای، چندین بده‌بستان وجود دارد. تفاوت اصلی در نحوه تکثیر داده‌ها است. این موضوع تضمین دسترسی‌پذیری برنامه شما را تعیین می‌کند. یک نمونه چند منطقه‌ای، قابلیت اطمینان سرویس‌دهی قوی‌تری را ارائه می‌دهد و دوام داده‌های شما را افزایش می‌دهد، اما بده‌بستان هزینه است.

سیستم پرس و جو در زمان واقعی را درک کنید

کوئری‌های بلادرنگ، که به آنها شنونده‌های اسنپ‌شات نیز گفته می‌شود، به برنامه اجازه می‌دهند تا به تغییرات در پایگاه داده گوش دهد و به محض تغییر داده‌ها، اعلان‌های با تأخیر کم دریافت کند. یک برنامه می‌تواند با نظرسنجی دوره‌ای از پایگاه داده برای به‌روزرسانی‌ها، به همان نتیجه برسد، اما اغلب کندتر، گران‌تر و به کد بیشتری نیاز دارد. برای مثال‌هایی از نحوه تنظیم و استفاده از کوئری‌های بلادرنگ، به «دریافت به‌روزرسانی‌های بلادرنگ» مراجعه کنید. بخش‌های بعدی به جزئیات نحوه کار شنونده‌های اسنپ‌شات می‌پردازند و برخی از بهترین شیوه‌ها را برای مقیاس‌بندی کوئری‌های بلادرنگ با حفظ عملکرد شرح می‌دهند.

دو کاربر را تصور کنید که از طریق یک برنامه پیام‌رسان ساخته شده با یکی از SDK های موبایل به Cloud Firestore متصل می‌شوند.

کلاینت A برای افزودن و به‌روزرسانی اسناد در مجموعه‌ای به نام chatroom در پایگاه داده می‌نویسد:

collection chatroom:
    document message1:
      from: 'Sparky'
      message: 'Welcome to Cloud Firestore!'

    document message2:
      from: 'Santa'
      message: 'Presents are coming'

کلاینت B با استفاده از یک شنونده‌ی اسنپ‌شات، به به‌روزرسانی‌های همان مجموعه گوش می‌دهد. هر زمان که کسی پیام جدیدی ایجاد کند، کلاینت B فوراً اعلان دریافت می‌کند. نمودار زیر معماری پشت یک شنونده‌ی اسنپ‌شات را نشان می‌دهد:

معماری اتصال شنونده اسنپ‌شات

توالی رویدادهای زیر زمانی اتفاق می‌افتد که کلاینت B یک snapshot listener را به پایگاه داده متصل می‌کند:

  1. کلاینت B با فراخوانی onSnapshot(collection("chatroom")) از طریق Firebase SDK، اتصالی به Cloud Firestore برقرار می‌کند و یک شنونده (listener) ثبت می‌کند. این شنونده می‌تواند ساعت‌ها فعال بماند.
  2. رابط کاربری Cloud Firestore از سیستم ذخیره‌سازی زیربنایی برای بوت‌استرپ کردن مجموعه داده‌ها پرس‌وجو می‌کند. این پرس‌وجو کل مجموعه نتایج اسناد منطبق را بارگذاری می‌کند. ما به این پرس‌وجو، پرس‌وجوی نمونه‌برداری (polling query) می‌گوییم. سپس سیستم ، قوانین امنیتی Firebase پایگاه داده را ارزیابی می‌کند تا تأیید کند که کاربر می‌تواند به این داده‌ها دسترسی داشته باشد. اگر کاربر مجاز باشد، پایگاه داده داده‌ها را به کاربر بازمی‌گرداند.
  3. سپس درخواست کلاینت B به حالت شنود (listening mode) می‌رود. شنودکننده در یک کنترل‌کننده اشتراک (subscription handler) ثبت می‌شود و منتظر به‌روزرسانی داده‌ها می‌ماند.
  4. اکنون کلاینت A یک عملیات نوشتن برای تغییر یک سند ارسال می‌کند.
  5. پایگاه داده، تغییر سند را در سیستم ذخیره‌سازی خود ثبت می‌کند.
  6. از نظر تراکنشی، سیستم همان به‌روزرسانی را در یک گزارش تغییرات داخلی ثبت می‌کند. این گزارش تغییرات، ترتیب دقیقی از تغییرات را هنگام وقوع تعیین می‌کند.
  7. در عوض، فایل تغییرات، داده‌های به‌روزرسانی‌شده را به مجموعه‌ای از کنترل‌کننده‌های اشتراک ارسال می‌کند.
  8. یک تطبیق‌دهنده‌ی پرس‌وجوی معکوس اجرا می‌شود تا ببیند آیا سند به‌روزرسانی‌شده با هیچ یک از شنوندگان اسنپ‌شات ثبت‌شده‌ی فعلی مطابقت دارد یا خیر. در این مثال، سند با شنوندگان اسنپ‌شات کلاینت B مطابقت دارد. همانطور که از نامش پیداست، می‌توانید تطبیق‌دهنده‌ی پرس‌وجوی معکوس را به عنوان یک پرس‌وجوی معمولی پایگاه داده در نظر بگیرید که به صورت معکوس انجام می‌شود. به جای جستجو در اسناد برای یافتن مواردی که با یک پرس‌وجو مطابقت دارند، به طور مؤثر در پرس‌وجوها جستجو می‌کند تا مواردی را که با یک سند ورودی مطابقت دارند، پیدا کند. پس از یافتن یک تطابق، سیستم سند مورد نظر را به شنوندگان اسنپ‌شات ارسال می‌کند. سپس سیستم قوانین امنیتی Firebase پایگاه داده را ارزیابی می‌کند تا اطمینان حاصل شود که فقط کاربران مجاز داده‌ها را دریافت می‌کنند.
  9. سیستم به‌روزرسانی سند را به SDK روی دستگاه کلاینت B ارسال می‌کند و فراخوانی onSnapshot فعال می‌شود. اگر پایداری محلی فعال باشد، SDK به‌روزرسانی را در حافظه پنهان محلی نیز اعمال می‌کند.

بخش کلیدی مقیاس‌پذیری Cloud Firestore به خروجی از گزارش تغییرات تا کنترل‌کننده‌های اشتراک و سرورهای frontend بستگی دارد. خروجی به یک تغییر داده اجازه می‌دهد تا به طور موثر منتشر شود تا به میلیون‌ها پرس‌وجوی بلادرنگ و کاربران متصل خدمت‌رسانی کند. Cloud Cloud Firestore با اجرای کپی‌های زیادی از همه این اجزا در چندین منطقه (یا چندین منطقه در صورت استقرار چند منطقه‌ای)، به دسترسی‌پذیری و مقیاس‌پذیری بالایی دست می‌یابد.

شایان ذکر است که تمام عملیات خواندن صادر شده از SDK های موبایل و وب از مدل بالا پیروی می‌کنند. آنها یک پرس و جوی نمونه‌برداری (polling query) و به دنبال آن حالت گوش دادن (listening mode) را برای حفظ ضمانت‌های سازگاری انجام می‌دهند. این امر در مورد شنونده‌های بلادرنگ، فراخوانی‌ها برای بازیابی یک سند و پرس و جوهای یک‌باره نیز صدق می‌کند. می‌توانید بازیابی‌های تک سند و پرس و جوهای یک‌باره را به عنوان شنونده‌های کوتاه‌مدت snapshot listeners در نظر بگیرید که محدودیت‌های مشابهی در مورد عملکرد دارند.

بهترین شیوه‌ها را برای مقیاس‌بندی کوئری‌های بلادرنگ به کار ببرید

برای طراحی کوئری‌های مقیاس‌پذیر و بلادرنگ، از بهترین شیوه‌های زیر استفاده کنید.

ترافیک بالای نوشتن در سیستم را درک کنید

این بخش به شما کمک می‌کند تا بفهمید سیستم چگونه به تعداد فزاینده درخواست‌های نوشتن پاسخ می‌دهد.

گزارش‌های تغییرات Cloud Firestore که کوئری‌های بلادرنگ را هدایت می‌کنند، با افزایش ترافیک نوشتن، به طور خودکار به صورت افقی مقیاس‌بندی می‌شوند. با افزایش نرخ نوشتن برای یک پایگاه داده فراتر از آنچه یک سرور می‌تواند مدیریت کند، گزارش تغییرات بین چندین سرور تقسیم می‌شود و پردازش کوئری شروع به مصرف داده‌ها از چندین کنترل‌کننده اشتراک به جای یک سرور می‌کند. از دیدگاه کلاینت و SDK، همه اینها شفاف است و هنگام وقوع تقسیم‌بندی‌ها، هیچ اقدامی از برنامه لازم نیست. نمودار زیر نحوه مقیاس‌بندی کوئری‌های بلادرنگ را نشان می‌دهد:

معماری خروجی گزارش تغییرات

مقیاس‌بندی خودکار به شما امکان می‌دهد ترافیک نوشتن خود را بدون محدودیت افزایش دهید، اما با افزایش ترافیک، ممکن است سیستم برای پاسخگویی مدتی طول بکشد. برای جلوگیری از ایجاد یک نقطه داغ نوشتن، توصیه‌های قانون ۵-۵-۵ را دنبال کنید. Key Visualizer ابزاری مفید برای تجزیه و تحلیل نقاط داغ نوشتن است.

بسیاری از برنامه‌ها رشد ارگانیک قابل پیش‌بینی دارند که Cloud Firestore می‌تواند بدون اقدامات احتیاطی آن را در خود جای دهد. با این حال، حجم کارهای دسته‌ای مانند وارد کردن یک مجموعه داده بزرگ، می‌تواند نوشتن‌ها را خیلی سریع افزایش دهد. هنگام طراحی برنامه خود، از منبع ترافیک نوشتن خود آگاه باشید.

درک کنید که چگونه می‌نویسند و می‌خوانند با هم تعامل دارند

می‌توانید سیستم کوئری بلادرنگ را به عنوان یک خط لوله در نظر بگیرید که عملیات نوشتن را به خوانندگان متصل می‌کند. هر زمان که یک سند ایجاد، به‌روزرسانی یا حذف می‌شود، تغییر از سیستم ذخیره‌سازی به شنوندگان ثبت‌شده فعلی منتشر می‌شود. ساختار گزارش تغییرات Cloud Firestore ثبات قوی را تضمین می‌کند، به این معنی که برنامه شما هرگز اعلان‌هایی از به‌روزرسانی‌هایی که در مقایسه با زمانی که پایگاه داده تغییرات داده‌ها را ثبت کرده است، نامرتب هستند، دریافت نمی‌کند. این امر با حذف موارد حاشیه‌ای پیرامون ثبات داده‌ها، توسعه برنامه را ساده می‌کند.

این خط لوله متصل به این معنی است که یک عملیات نوشتن که باعث ایجاد نقاط حساس یا رقابت در قفل می‌شود، می‌تواند بر عملیات خواندن تأثیر منفی بگذارد. هنگامی که عملیات نوشتن با شکست مواجه می‌شود یا با مشکل مواجه می‌شود، ممکن است عملیات خواندن در انتظار داده‌های سازگار از گزارش تغییرات متوقف شود. اگر این اتفاق در برنامه شما رخ دهد، ممکن است هم عملیات نوشتن کند و هم زمان پاسخ کند مرتبط برای پرس‌وجوها را مشاهده کنید. اجتناب از نقاط حساس، کلید جلوگیری از این مشکل است.

اسناد و عملیات نوشتن را کوچک نگه دارید

هنگام ساخت برنامه‌هایی با استفاده از snapshot listeners، معمولاً می‌خواهید کاربران به سرعت از تغییرات داده‌ها مطلع شوند. برای دستیابی به این هدف، سعی کنید همه چیز را کوچک نگه دارید. سیستم می‌تواند اسناد کوچک با ده‌ها فیلد را خیلی سریع از طریق سیستم ارسال کند. اسناد بزرگتر با صدها فیلد و داده‌های حجیم، زمان بیشتری برای پردازش نیاز دارند.

به همین ترتیب، برای کم کردن تأخیر، از عملیات‌های کوتاه و سریع commit و write استفاده کنید. دسته‌های بزرگ ممکن است از دیدگاه نویسنده، توان عملیاتی بالاتری به شما بدهند، اما در واقع ممکن است زمان اعلان برای snapshot listeners را افزایش دهند. این اغلب در مقایسه با استفاده از سایر سیستم‌های پایگاه داده که در آنها ممکن است از batching برای بهبود عملکرد استفاده کنید، متناقض است.

از شنوندگان کارآمد استفاده کنید

با افزایش نرخ نوشتن برای پایگاه داده شما، Cloud Firestore پردازش داده‌ها را بین سرورهای زیادی تقسیم می‌کند. الگوریتم شاردینگ Cloud Firestore سعی می‌کند داده‌ها را از یک مجموعه یا گروه مجموعه یکسان در یک سرور changelog یکسان قرار دهد. این سیستم سعی می‌کند توان عملیاتی نوشتن ممکن را به حداکثر برساند و در عین حال تعداد سرورهای درگیر در پردازش یک پرس‌وجو را تا حد امکان کم نگه دارد.

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

برای جلوگیری از این پاسخ‌های کندتر، طرحواره و برنامه خود را طوری طراحی کنید که سیستم بتواند بدون مراجعه به سرورهای مختلف، به شنوندگان (listeners) خدمت‌رسانی کند. شاید بهتر باشد داده‌های خود را به مجموعه‌های کوچک‌تر با نرخ نوشتن پایین‌تر تقسیم کنید.

این شبیه به تفکر در مورد کوئری‌های عملکردی در یک پایگاه داده رابطه‌ای است که نیاز به اسکن کامل جدول دارند. در یک پایگاه داده رابطه‌ای، کوئری‌ای که نیاز به اسکن کامل جدول دارد، معادل یک شنونده اسنپ‌شات است که یک مجموعه با ریزش بالا را تماشا می‌کند. این کوئری ممکن است در مقایسه با کوئری‌ای که پایگاه داده می‌تواند با استفاده از یک شاخص خاص‌تر به آن سرویس دهد، کندتر عمل کند. یک کوئری با شاخص خاص‌تر مانند یک شنونده اسنپ‌شات است که یک سند واحد یا مجموعه‌ای را که کمتر تغییر می‌کند، تماشا می‌کند. شما باید برنامه خود را بارگذاری کنید تا به بهترین شکل رفتار و نیاز مورد استفاده خود را درک کنید.

نظرسنجی‌ها را سریع نگه دارید

یکی دیگر از بخش‌های کلیدی کوئری‌های واکنش‌گرای بلادرنگ، حصول اطمینان از سریع و کارآمد بودن کوئری نمونه‌برداری (polling query) برای بوت‌استرپ کردن داده‌ها است. اولین باری که یک شنونده‌ی اسنپ‌شات جدید متصل می‌شود، شنونده باید کل مجموعه نتایج را بارگذاری کرده و آن را به دستگاه کاربر ارسال کند. کوئری‌های کند، واکنش‌پذیری برنامه‌ی شما را کاهش می‌دهند. این شامل کوئری‌هایی می‌شود که سعی می‌کنند اسناد زیادی را بخوانند یا کوئری‌هایی که از ایندکس‌های مناسب استفاده نمی‌کنند.

یک شنونده همچنین ممکن است تحت برخی شرایط از حالت گوش دادن به حالت نظرسنجی برگردد. این اتفاق به طور خودکار رخ می‌دهد و برای SDKها و برنامه شما شفاف است. شرایط زیر ممکن است باعث ایجاد حالت نظرسنجی شود:

اگر کوئری‌های نظرسنجی شما به اندازه کافی سریع باشند، وضعیت نظرسنجی برای کاربران برنامه شما شفاف می‌شود.

به شنوندگان با عمر طولانی توجه کنید

باز کردن و زنده نگه داشتن شنونده‌ها تا حد امکان، اغلب مقرون به صرفه‌ترین راه برای ساخت برنامه‌ای است که از Cloud Firestore استفاده می‌کند. هنگام استفاده از Cloud Firestore ، هزینه اسنادی که به برنامه شما بازگردانده می‌شوند، از شما دریافت می‌شود و نه برای حفظ یک اتصال باز. یک شنونده اسنپ‌شات با عمر طولانی، فقط داده‌هایی را که برای ارائه پرس‌وجو در طول عمر خود نیاز دارد، می‌خواند. این شامل یک عملیات اولیه نمونه‌برداری و به دنبال آن اعلان‌هایی است که هنگام تغییر داده‌ها ارسال می‌شوند. از سوی دیگر، پرس‌وجوهای یک‌باره، داده‌هایی را که ممکن است از آخرین اجرای پرس‌وجو توسط برنامه تغییر نکرده باشند، دوباره می‌خوانند.

در مواردی که برنامه شما باید نرخ بالایی از داده مصرف کند، ممکن است شنونده‌های snapshot مناسب نباشند. به عنوان مثال، اگر مورد استفاده شما اسناد زیادی را در هر ثانیه از طریق یک اتصال برای مدت زمان طولانی ارسال می‌کند، بهتر است از کوئری‌های one-shot که با فرکانس پایین‌تری اجرا می‌شوند، استفاده کنید.

قدم بعدی چیست؟

،

برای راهنمایی در مورد مقیاس‌بندی برنامه بدون سرور خود فراتر از هزاران عملیات در ثانیه یا صدها هزار کاربر همزمان، این سند را مطالعه کنید. این سند شامل مباحث پیشرفته‌ای است که به شما در درک عمیق سیستم کمک می‌کند. اگر تازه کار با Cloud Firestore را شروع کرده‌اید، به جای آن به راهنمای شروع سریع مراجعه کنید.

Cloud Firestore و کیت‌های توسعه نرم‌افزار موبایل/وب فایربیس، مدلی قدرتمند برای توسعه برنامه‌های بدون سرور ارائه می‌دهند که در آن کد سمت کلاینت مستقیماً به پایگاه داده دسترسی پیدا می‌کند. این کیت‌ها به کلاینت‌ها اجازه می‌دهند تا به‌روزرسانی‌های داده‌ها را به‌صورت بلادرنگ دریافت کنند. شما می‌توانید از به‌روزرسانی‌های بلادرنگ برای ساخت برنامه‌های واکنش‌گرا که نیازی به زیرساخت سرور ندارند، استفاده کنید. اگرچه راه‌اندازی و اجرای چیزی بسیار آسان است، اما درک محدودیت‌های سیستم‌هایی که Cloud Firestore را تشکیل می‌دهند، به شما کمک می‌کند تا برنامه بدون سرور شما با افزایش ترافیک، مقیاس‌پذیر و عملکرد خوبی داشته باشد.

برای مشاوره در مورد مقیاس‌بندی برنامه خود، به بخش‌های زیر مراجعه کنید.

یک مکان پایگاه داده نزدیک به کاربران خود انتخاب کنید

نمودار زیر معماری یک برنامه بلادرنگ را نشان می‌دهد:

مثال معماری برنامه بلادرنگ

وقتی برنامه‌ای که روی دستگاه کاربر (موبایل یا وب) در حال اجرا است، اتصالی به Cloud Firestore برقرار می‌کند، این اتصال به یک سرور Frontend Cloud Firestore در همان منطقه‌ای که پایگاه داده شما در آن قرار دارد، هدایت می‌شود. به عنوان مثال، اگر پایگاه داده شما در us-east1 باشد، اتصال به یک سرور Frontend Cloud Firestore نیز در us-east1 می‌رود. این اتصالات طولانی مدت هستند و تا زمانی که صریحاً توسط برنامه بسته نشوند، باز می‌مانند. Frontend داده‌ها را از سیستم‌های ذخیره‌سازی Cloud Firestore زیرین می‌خواند.

The distance between a user's physical location and the Cloud Firestore database location affects the latency experienced by the user. For example, a user in India whose app talks to a database in a Google Cloud region in North America might find the experience slower and the app less snappy than if the database was instead located closer, such as in India or in another part of Asia.

Design for reliability

The following topics improve or affect your app's reliability:

Enable offline mode

The Firebase SDKs provide offline data persistence. If the app on the user's device can't connect to Cloud Firestore , the app remains usable by working with locally cached data. This ensures data access even when users experience spotty internet connections or completely lose access for several hours or days. For more details on offline mode, see Enable offline data .

Understand automatic retries

The Firebase SDKs take care of retrying operations and re-establishing broken connections. This helps work around transient errors caused by restarting servers or network issues between the client and the database.

Choose between regional and multi-regional locations

There are several trade-offs when choosing between regional and multi-regional locations. The main difference is how data is replicated. This drives the availability guarantees of your app. A multi-region instance gives stronger serving reliability and increases the durability of your data but the trade-off is cost.

Understand the real-time query system

Real-time queries, also called snapshot listeners, let the app listen to changes in the database and get low-latency notifications as soon as the data changes. An app can get the same result by periodically polling the database for updates, but it's often slower, more expensive, and requires more code. For examples of how to set up and use real-time queries, see Get real-time updates . The following sections get into details of how snapshot listeners work and describe some of the best practices for scaling real-time queries while retaining performance.

Imagine two users that connect to Cloud Firestore through a messaging app built with one of the mobile SDKs.

Client A writes to the database to add and update documents in a collection called chatroom :

collection chatroom:
    document message1:
      from: 'Sparky'
      message: 'Welcome to Cloud Firestore!'

    document message2:
      from: 'Santa'
      message: 'Presents are coming'

Client B listens for updates in the same collection using a snapshot listener. Client B gets an immediate notification whenever someone creates a new message. The following diagram shows the architecture behind a snapshot listener:

Architecture of a snapshot listener connection

The following sequence of events takes place when Client B connects a snapshot listener to the database:

  1. Client B opens a connection to Cloud Firestore and registers a listener by making a call to onSnapshot(collection("chatroom")) through the Firebase SDK. This listener can stay active for hours.
  2. The Cloud Firestore frontend queries the underlying storage system to bootstrap the dataset. It loads the entire result set of matching documents. We refer to this as a polling query . The system then evaluates the database's Firebase Security Rules to verify that the user can access this data. If the user is authorized, the database returns the data to the user.
  3. Client B's query then moves into listen mode . The listener registers with a subscription handler and waits for updates to the data.
  4. Client A now sends a write operation to modify a document.
  5. The database commits the document change to its storage system.
  6. Transactionally, the system commits the same update to an internal changelog. The changelog establishes a strict ordering of changes as they happen.
  7. The changelog in turn fans out the updated data to a pool of subscription handlers.
  8. A reverse query matcher executes to see if the updated document matches any currently registered snapshot listeners. In this example, the document matches Client B's snapshot listener. As the name implies, you can think of the reverse query matcher as a normal database query but done in reverse. Instead of searching through documents to find those that match a query, it efficiently searches through queries to find those that match an incoming document. Upon finding a match, the system forwards the document in question to the snapshot listeners. Then the system evaluates the database's Firebase Security Rules to ensure that only authorized users receive the data.
  9. The system forwards the document update to the SDK on client B's device, and the onSnapshot callback fires. If local persistence is enabled, the SDK applies the update to the local cache as well.

A key part of Cloud Firestore 's scalability depends on the fan-out from the changelog to the subscription handlers and the frontend servers. The fan-out lets a single data change to propagate efficiently to serve millions of real-time queries and connected users. By running many replicas of all these components across multiple zones (or multiple regions in the case of a multi-region deployment), Cloud Firestore achieves high availability and scalability.

It's worth noting that all read operations issued from mobile and web SDKs follow the model above. They perform a polling query followed by listen mode to maintain consistency guarantees. This also applies to real-time listeners, calls to retrieve a document, and one-shot queries . You can think of single document retrievals and one-shot queries as short-lived snapshot listeners that come with similar constraints around performance.

Apply best practices for scaling real-time queries

Apply the following best practices to design scalable real-time queries.

Understand high write traffic in the system

This section helps you understand how the system responds to an increasing number of write requests.

The Cloud Firestore changelogs that drive the real-time queries automatically scale horizontally as write traffic increases. As the write rate for a database increases beyond what a single server can handle, the changelog is split across multiple servers, and the query processing starts to consume data from multiple subscription handlers instead of one. From the client and SDK's perspective, this is all transparent and no action is required from the app when splits happen. The following diagram demonstrates how real-time queries scale:

Architecture of changelog fan-out

Automatic scaling allows you to increase your write traffic without limits, but as the traffic ramps up, the system might take some time to respond. Follow the recommendations of the 5-5-5 rule to avoid creating a write hotspot. Key Visualizer is a useful tool for analyzing write hotspots.

Many apps have predictable organic growth, which Cloud Firestore can accommodate without precautions. Batch workloads like importing a large dataset, however, can ramp up writes too quickly. As you design your app, stay aware of where your write traffic comes from.

Understand how writes and reads interact

You can think of the real-time query system as a pipeline connecting write operations with readers. Any time a document is created, updated, or deleted, the change propagates from the storage system to the currently registered listeners. Cloud Firestore 's changelog structure guarantees strong consistency, which means that your app never receives notifications of updates that are out of order compared to when the database committed the data changes. This simplifies app development by removing edge cases around data consistency.

This connected pipeline means that a write operation causing hotspots or lock contention can negatively affect read operations. When write operations fail or experience throttling, a read might stall waiting for consistent data from the changelog. If this happens in your app, you might see both slow write operations and correlated slow response times for queries. Avoiding hotspots is the key to steering clear of this problem.

Keep documents and write operations small

When building apps with snapshot listeners, you typically want users to find out about data changes quickly. To achieve this, try to keep things small. The system can push small documents with tens of fields through the system very quickly. Larger documents with hundreds of fields and large data take longer to process.

Likewise, favor short, fast commit and write operations to keep latency low. Large batches might give you higher throughput from the writer's perspective but might actually increase the notification time for snapshot listeners. This is often counterintuitive compared to using other database systems where you might use batching to improve performance.

Use efficient listeners

As the write rates for your database increase, Cloud Firestore splits the data processing across many servers. Cloud Firestore 's sharding algorithm tries to co-locate data from the same collection or collection group onto the same changelog server. The system tries to maximize the possible write throughput while keeping the number of servers involved in the processing of a query as low as possible.

However, certain patterns might still lead to suboptimal behavior for snapshot listeners. For example, if your app stores most of its data in one large collection, the listener might need to connect to many server to receive all data it needs. This remains true even if you apply a query filter. Connecting to many servers increases the risk of slower responses.

To avoid these slower responses, design your schema and app so that the system can serve listeners without going to many different servers. It might work best to break your data into smaller collections with smaller write rates.

This is similar to thinking about the performance queries in a relational database that require full table scans. In a relational database, a query that requires a full table scan is the equivalent of a snapshot listener that watches a high-churn collection. It might perform slowly compared to a query that the database can serve using a more specific index. A query with a more specific index is like a snapshot listener that watches a single document or a collection that changes less often. You should load test your app to best understand the behavior and need of your use case.

Keep polling queries fast

Another key part of responsive real-time queries involves making sure that the polling query to bootstrap the data is fast and efficient. The first time a new snapshot listener connects, the listener must load the entire result set and send it to the user's device. Slow queries make your app less responsive. This includes, for example, queries that try to read many documents or queries that don't use the appropriate indexes.

A listener might also move back from a listening state to a polling state under some circumstances. This happens automatically and is transparent to the SDKs and your app. The following conditions might trigger a polling state:

  • The system re-balances a changelog due to changes in load.
  • Hotspots cause failed or delayed writes to the database.
  • Transient server restarts temporarily affect listeners.

If your polling queries are fast enough, a polling state becomes transparent to your app's users.

Favor long-lived listeners

Opening and keeping listeners alive for as long as possible is often the most cost-effective way to build an app that uses Cloud Firestore . When using Cloud Firestore , you are billed for the documents returned to your app and not for maintaining an open connection. A long-lived snapshot listener reads only the data it needs to serve the query throughout its lifetime. This includes an initial polling operation followed by notifications when the data actually changes. One-shot queries, on the other hand, re-read data that may not have changed since the app last executed the query.

In cases where your app must consume a high rate of data, snapshot listeners might not be appropriate. For example, if your use case pushes many documents per second through a connection for an extended period of time, it might be better to opt for one-shot queries that run at a lower frequency.

قدم بعدی چیست؟