Firebase Realtime Database یک پایگاه داده ابری JSON بیدرنگ است که توسط Google در سال 2012 برای برنامههای موبایل و وب راهاندازی شد. همه دادهها در یک درخت JSON بزرگ ذخیره میشوند و از طریق اتصال WebSocket بین مشتریان متصل در زمان واقعی همگامسازی میشوند. طبق مستندات رسمی Firebase, 2025، Realtime Database میتواند تا 200,000 اتصال همزمان و تا 1000 عملیات نوشتن همزمان در ثانیه را پشتیبانی کند. پایگاه داده به زیرساخت سرور نیاز ندارد و SDK را برای iOS، Android، Web و پلتفرمهای سرور ارائه میدهد.
نکات اصلی
Firebase Realtime Database یک پایگاه داده ابری NoSQL است که دادهها را در زمان واقعی بین همه مشتریان متصل ذخیره و همگامسازی میکند. این پایگاه داده در سال 2012 به عنوان Firebase (قبل از خرید توسط Google) راهاندازی شد و اولین پایگاه داده ابری بیدرنگ برای توسعهدهندگان موبایل بود. دادهها در قالب JSON ارائه میشوند و در یک درخت سلسلهمراتبی سازماندهی میشوند که هر گره یک مسیر منحصربهفرد دارد.
ارزش اصلی Realtime Database همگامسازی داخلی است. وقتی برنامه دادهها را در هر دستگاهی تغییر میدهد، همه مشتریان متصل دیگر بلافاصله از طریق یک اتصال دائمی بهروزرسانی دریافت میکنند. این کار توسعهدهنده را از پیادهسازی مکانیزم همگامسازی شخصی، سرور WebSocket یا REST API برای انتقال داده بین مشتریان بینیاز میکند.
پایگاه داده SDK را برای همه پلتفرمهای اصلی ارائه میدهد: Android (Java, Kotlin)، iOS (Swift, Objective-C)، Web (JavaScript) و محیطهای سرور از طریق Admin SDK. طبق دادههای Google، Realtime Database در بیش از 1.5 میلیون پروژه فعال Firebase در سراسر جهان استفاده میشود. با وجود ظهور Firestore مدرنتر، Realtime Database همچنان یک انتخاب محبوب برای پروژههایی با ساختار داده ساده است.
برخلاف پایگاههای داده رابطهای، Realtime Database از جدولها و ردیفها استفاده نمیکند. همه دادهها یک درخت JSON واحد را تشکیل میدهند که شبیه اشیاء تو در توی JavaScript است. به عنوان مثال، برای ذخیره کاربران و پیامهایشان یک سلسلهمراتب ایجاد میشود: users/userId/name و messages/messageId/text. هر مسیر درخت یک رشته است و دادهها را میتوان مستقیماً از طریق این مسیر خواند.
{
"users": {
"user1": {
"name": "ایوان پتروف",
"email": "ivan@example.com"
},
"user2": {
"name": "ماریا سوکولوا",
"email": "maria@example.com"
}
},
"messages": {
"-Nabc123": {
"text": "سلام!",
"userId": "user1"
}
}
}
یک ویژگی مهم این است که تودرتویی عمیق بر عملکرد تأثیر میگذارد. وقتی برنامه دادهها را در یک مسیر خاص میخواند، تمام گرههای فرزند آن مسیر را بارگذاری میکند. بنابراین توصیه میشود ساختار داده را تا حد امکان مسطح طراحی کنید و از تودرتویی عمیقتر از 3–4 سطح خودداری کنید. برای حل این مشکل از نرمالزدایی دادهها استفاده میشود — تکرار اطلاعات در گرههای مختلف درخت.
Realtime Database و Firestore اغلب به عنوان دو پایگاه داده ابری بیدرنگ از Google مقایسه میشوند. انتخاب بین آنها به نیازهای خاص پروژه بستگی دارد: پیچیدگی پرسوجوها، سازگاری مورد نیاز و بار برنامهریزی شده. درک نقاط قوت هر پایگاه داده به تصمیمگیری معماری صحیح کمک میکند.
مزیت اصلی Realtime Database تاخیر همگامسازی پایین است. از آنجایی که همه دادهها در یک درخت JSON بدون لایههای انتزاعی اضافی ذخیره میشوند، همگامسازی سریعتر از Firestore است. برای برنامههایی که سرعت تحویل بهروزرسانی در آنها حیاتی است (چتها، بازیهای آنلاین، سیستمهای ویرایش مشترک)، Realtime Database ممکن است انتخاب مناسبتری باشد.
Realtime Database برای سناریوهایی با ساختار داده ساده و فراوانی بهروزرسانی بالا مناسبتر است. مثالهای معمول: چتها، لایکهای بیدرنگ، نشانگرهای تایپ، وضعیت حضور کاربران. این همچنین انتخاب خوبی برای نمونههای اولیه و پروژههایی با بودجه محدود است، زیرا قیمتگذاری بر اساس حجم داده است نه تعداد عملیات.
از سوی دیگر، برای برنامههایی با پرسوجوهای پیچیده (فیلتر کردن بر اساس چند فیلد، مرتبسازی، تجمیع) Firestore امکانات بسیار قدرتمندتری ارائه میدهد. Realtime Database فقط فیلتر کردن بر اساس یک پارامتر را پشتیبانی میکند و نمیتواند نتایج را بر اساس چند فیلد همزمان مرتب کند. اگر پروژه تحلیل داده پیچیده در سمت مشتری را برنامهریزی میکند، Firestore انتخاب عملیتری خواهد بود.
Realtime Database از یک اتصال دائمی WebSocket برای همگامسازی دوطرفه دادهها استفاده میکند. وقتی مشتری setValue یا updateChildren را در یک مسیر خاص فراخوانی میکند، دادهها از طریق کانال باز به سرور Firebase ارسال میشوند. سرور تغییرات را اعمال میکند و بهروزرسانیها را برای همه مشتریان مشترک در طول میلیثانیه پخش میکند. هر اتصال با یک کلید جلسه منحصربهفرد شناسایی میشود.
مکانیزم اشتراک از طریق listenerها کار میکند. توسعهدهنده میتواند تغییر یک گره خاص را دنبال کند (addListenerForSingleValueEvent) یا بهروزرسانیهای دائمی دریافت کند (addValueEventListener). در هر تغییر داده، callback onDataChange با تصویر کامل دادهها در مسیر مشخص فراخوانی میشود. این با Firestore متفاوت است، جایی که فقط اسناد تغییر یافته ارسال میشوند — در Realtime Database همیشه تمام دادههای گره بارگذاری میشوند.
Realtime Database از حالت آفلاین در Android و iOS از طریق ذخیرهسازی دیسک پشتیبانی میکند. SDK یک کپی محلی از دادهها را نگه میدارد و عملیات نوشتن را در غیاب شبکه ادامه میدهد. وقتی اتصال بازیابی میشود، تمام تغییرات انباشته شده به سرور ارسال میشوند. برای حل تعارضات از استراتژی last-write-wins استفاده میشود، اما توسعهدهنده میتواند منطق سفارشی را از طریق ServerValue.TIMESTAMP برای حل برخوردها پیادهسازی کند.
val database = FirebaseDatabase.getInstance()
val myRef = database.getReference("messages")
// نوشتن داده
myRef.push().setValue(
hashMapOf(
"text" to "پیام جدید",
"timestamp" to ServerValue.TIMESTAMP
)
)
// خواندن با بهروزرسانی دائمی
myRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val data = snapshot.getValue()
Log.d("TAG", "داده: $data")
}
override fun onCancelled(error: DatabaseError) {
Log.w("TAG", "خطا: ${error.message}")
}
})
برای بهینهسازی ترافیک و عملکرد، توصیه میشود به جای value listeners از child listeners استفاده کنید وقتی نیاز به ردیابی تغییرات گرههای فرزند خاص دارید. ChildEventListener callbackهای جداگانهای برای افزودن، تغییر، حذف و جابجایی عناصر فرزند فراهم میکند که کنترل دقیقتری بر بهروزرسانیهای UI و جلوگیری از بازترسیم همه عناصر لیست در هر تغییر داده امکانپذیر میسازد.
Realtime Database از زبان اعلامی قوانین برای کنترل دسترسی به دادهها استفاده میکند. قوانین مشخص میکنند چه کسی میتواند دادهها را در هر مسیر درخت JSON بخواند و بنویسد. آنها قبل از هر درخواست در سرور Firebase بررسی میشوند و برای مجوزدهی به منطق سرور نیاز ندارند. قوانین از متغیرها، اشیاء داخلی و توابع برای پیکربندی انعطافپذیر دسترسی پشتیبانی میکنند.
به طور پیشفرض دسترسی به پایگاه داده برای همه کاربران ممنوع است. توسعهدهنده تدریجاً دسترسی را با استفاده از قانین ".read" و ".write" در سطوح مختلف درخت باز میکند. شرایط میتوانند احراز هویت را از طریق متغیر auth، نوع درخواست (read/write) و دادههای موجود را از طریق شی data بررسی کنند. علاوه بر این، قوانین از اعتبارسنجی دادههای نوشته شده از طریق شی newData پشتیبانی میکنند.
{
"rules": {
"users": {
"$uid": {
// فقط مالک میتواند دادههای خود را بخواند
".read": "$uid === auth.uid",
// فقط مالک میتواند بنویسد
".write": "$uid === auth.uid",
// اعتبارسنجی فیلدها هنگام نوشتن
".validate": "newData.hasChildren(['name', 'email'])"
}
},
"messages": {
// هر کاربر احراز هویت شده میتواند بخواند
".read": "auth !== null",
// فقط احراز هویت شده میتواند بنویسد
".write": "auth !== null",
".indexOn": ["timestamp"]
}
}
}
قوانین همچنین از نمایهسازی دادهها از طریق دستور ".indexOn" پشتیبانی میکنند. بدون آن، پرسوجوهای مرتبسازی (orderByChild) رد میشوند یا ناکارآمد اجرا میشوند. نمایهها برای هر مسیری که مرتبسازی بر اساس یک فیلد خاص در آن انجام میشود مشخص میشوند. قوانین آبشاری هستند: قوانین عمیقتر قوانین والد را بازنویسی میکنند و اگر در یک سطح دسترسی وجود نداشته باشد، بسته به قانین والد مجاز یا ممنوع در نظر گرفته میشود.
Realtime Database از پنج نوع داده پشتیبانی میکند: String، Number، Boolean، Map (شی) و List (آرایه). عمق تودرتویی به 32 سطح محدود شده است و حداکثر اندازه یک گره نباید از 256 MB تجاوز کند. برای کار مؤثر با پایگاه داده، توصیه میشود ساختار داده مسطح طراحی کنید و برای جلوگیری از پرسوجوهای عمیق که حجم زیادی از داده را بارگذاری میکنند، از نرمالزدایی استفاده کنید.
بیایید یک مثال عملی از ادغام Realtime Database در برنامه Android برای وضعیت کاربران (online/offline) را بررسی کنیم. برنامه لیست کاربران را با وضعیت فعلی آنها که در زمان واقعی بهروز میشود نمایش میدهد. برای نمایش از Firebase Authentication برای شناسایی کاربران و کوروتینها برای عملیات ناهمگام استفاده میشود.
برای شروع، وابستگی firebase-database-ktx را به فایل build.gradle ماژول برنامه اضافه کنید. نسخه کتابخانه از طریق Firebase BoM برای تضمین سازگاری همه مؤلفهها مدیریت میشود. پس از افزودن وابستگی، باید Firebase را در کلاس Application یا از طریق مقداردهی تنبل در ViewModel مقداردهی کنید.
dependencies {
implementation platform("com.google.firebase:firebase-bom:33.0.0")
implementation "com.google.firebase:firebase-database-ktx"
implementation "com.google.firebase:firebase-auth-ktx"
}
پس از پیکربندی، یک مخزن برای کار با کاربران ایجاد میشود. هر کاربر با یک گره در درخت /users/{uid} با فیلدهای name، email و status نمایش داده میشود. برای ردیابی وضعیت از onDisconnect استفاده میشود — یک مکانیزم ویژه Firebase که به طور خودکار عملیات نوشتن را هنگام قطع اتصال مشتری انجام میدهد. این تضمین میکند که وضعیت کاربر در زمان بسته شدن برنامه یا از دست رفتن شبکه بدون کد اضافی در سمت مشتری به "offline" تغییر میکند.
class PresenceRepository {
private val database = FirebaseDatabase.getInstance()
private val auth = FirebaseAuth.getInstance()
private val presenceRef = database
.getReference("presence")
fun trackPresence() {
val uid = auth.currentUser?.uid ?: return
val userRef = presenceRef.child(uid)
userRef.onDisconnect().setValue("offline")
userRef.setValue("online")
}
fun getPresenceStream(): Flow<Map<String, String>> =
presenceRef.snapshotFlow()
.map { snapshot ->
(snapshot.value as? Map<*, *>)
?.mapKeys { it.key.toString() }
?.mapValues { it.value.toString() }
?: emptyMap()
}
}
عنصر کلیدی مثال onDisconnect است. این مکانیزم به شما امکان میدهد عملیات نوشتنی را تعیین کنید که هنگام قطع اتصال مشتری روی سرور اجرا میشود. در این حالت، وقتی کاربر قطع میشود، وضعیت او بدون نیاز به پردازش رویداد بسته شدن برنامه به طور خودکار روی "offline" تنظیم میشود. اگر برنامه به طور غیرمنتظره بسته شود، Firebase خود عملیات onDisconnect را اجرا میکند و سایر کاربران وضعیت صحیح را مشاهده میکنند.
سوالات متداول
Realtime Database دادهها را در یک درخت JSON ذخیره میکند و تاخیر همگامسازی کمتری فراهم میکند. Firestore از مجموعه اسناد استفاده میکند، پرسوجوهای پیچیده و سازگاری قوی را پشتیبانی میکند. Realtime Database برای چتهای ساده و وضعیتها بهتر است، Firestore برای برنامههایی با ساختار داده پیچیده و تحلیل.
حداکثر اندازه یک گره Realtime Database 256 MB است. عمق تودرتویی به 32 سطح محدود شده است. برای یک پروژه Firebase میتوان چندین پایگاه داده Realtime Database ایجاد کرد (تا 5 در طرح Spark و تا 100 در طرح Blaze) که امکان توزیع دادهها بین نمونههای مختلف را فراهم میکند.
Realtime Database با Firebase Authentication ادغام میشود. در قوانین امنیتی، متغیر auth حاوی uid کاربر احراز هویت شده در دسترس است. توسعهدهنده میتواند دسترسی را در سطح گرههای جداگانه درخت JSON محدود کند و مطابقت uid مالک داده را بررسی کند. کاربران ناشناس و احراز هویت نشده auth = null دارند.
بله، Realtime Database از تراکنشها از طریق روش runTransaction پشتیبانی میکند. تراکنش اتمی بودن عملیات خواندن-تغییر-نوشتن را برای یک گره تضمین میکند. در هنگام تغییرات همزمان، تراکنش با دادههای فعلی تکرار میشود. این برای شمارندهها، رتبهبندیها و سایر سناریوهایی که سازگاری داده مهم است مفید میباشد.
بله، Realtime Database از حالت آفلاین در Android و iOS پشتیبانی میکند. SDK دادهها را به صورت محلی ذخیره میکند و عملیات نوشتن را در غیاب شبکه ادامه میدهد. پس از بازیابی اتصال، تمام تغییرات انباشته شده با سرور همگامسازی میشوند. برای فعال کردن حالت آفلاین از روش keepSynced(true) در گره مورد نظر استفاده میشود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید