Firebase Realtime Database, Google tarafından 2012 yılında mobil ve web uygulamaları için piyasaya sürülen bir bulut JSON gerçek zamanlı veritabanıdır. Tüm veriler tek bir büyük JSON ağacında saklanır ve WebSocket bağlantısı üzerinden bağlı istemciler arasında gerçek zamanlı olarak senkronize edilir. Resmi belgelere göre Firebase, 2025, Realtime Database 200.000'e kadar eşzamanlı bağlantıyı yönetebilir ve saniyede 1.000'e kadar eşzamanlı yazmayı destekler. Veritabanı sunucu altyapısı gerektirmez ve iOS, Android, Web ve sunucu platformları için SDK sağlar.
Önemli Noktalar
Firebase Realtime Database, bağlı tüm istemciler arasında verileri gerçek zamanlı olarak depolayan ve senkronize eden bir bulut NoSQL veritabanıdır. 2012 yılında Firebase olarak piyasaya sürülen (Google tarafından satın alınmadan önce), mobil geliştiriciler için ilk bulut gerçek zamanlı veritabanı oldu. Veriler JSON formatında temsil edilir ve her düğümün benzersiz bir yola sahip olduğu hiyerarşik bir ağaçta organize edilir.
Realtime Database'in temel değeri yerleşik senkronizasyondur. Bir uygulama herhangi bir cihazda verileri değiştirdiğinde, diğer tüm bağlı istemciler kalıcı bağlantı üzerinden anında güncellemeyi alır. Bu, geliştiricinin istemciler arasında veri aktarımı için kendi senkronizasyon mekanizmasını, WebSocket sunucusunu veya REST API'sini uygulama ihtiyacını ortadan kaldırır.
Veritabanı, tüm ana platformlar için SDK sağlar: Android (Java, Kotlin), iOS (Swift, Objective-C), Web (JavaScript) ve Admin SDK aracılığıyla sunucu ortamları. Google'a göre, Realtime Database dünya çapında 1,5 milyondan fazla aktif Firebase projesinde kullanılmaktadır. Daha modern Firestore'un ortaya çıkmasına rağmen, Realtime Database basit veri yapısına sahip projeler için popüler bir seçim olmaya devam etmektedir.
İlişkisel veritabanlarının aksine, Realtime Database tablolar ve satırlar kullanmaz. Tüm veriler, iç içe geçmiş JavaScript nesnelerine benzeyen tek bir JSON ağacıdır. Örneğin, kullanıcıları ve mesajlarını depolamak için bir hiyerarşi oluşturulur: users/userId/name ve messages/messageId/text. Ağaçtaki her yol bir dizedir ve verilere bu yol üzerinden doğrudan erişilebilir.
{
"users": {
"user1": {
"name": "İvan Petrov",
"email": "ivan@example.com"
},
"user2": {
"name": "Mariya Sokolova",
"email": "maria@example.com"
}
},
"messages": {
"-Nabc123": {
"text": "Merhaba!",
"userId": "user1"
}
}
}
Önemli bir özellik, derin iç içe geçmenin performansı etkilemesidir. Bir uygulama belirli bir yolda veri okuduğunda, o yolun tüm alt düğümlerini yükler. Bu nedenle, veri yapısının mümkün olduğunca düz tasarlanması ve 3-4 seviyeden daha derin iç içe geçmekten kaçınılması önerilir. Bu sorunu aşmak için veri normalizasyonunun kaldırılması (denormalizasyon) kullanılır — bilgilerin farklı ağaç düğümlerinde çoğaltılması.
Realtime Database ve Firestore, Google'ın iki bulut gerçek zamanlı veritabanı olarak sıkça karşılaştırılır. Aralarındaki seçim, projenin özel gereksinimlerine bağlıdır: sorgu karmaşıklığı, gereken tutarlılık ve beklenen yük. Her veritabanının güçlü yönlerini anlamak, doğru mimari kararı vermeye yardımcı olur.
Realtime Database'in ana avantajı düşük senkronizasyon gecikmesidir. Tüm veriler ek soyutlama katmanları olmadan tek bir JSON ağacında depolandığından, senkronizasyon Firestore'dan daha hızlıdır. Güncelleme teslimat hızının kritik olduğu uygulamalar (sohbetler, çevrimiçi oyunlar, işbirlikçi düzenleme sistemleri) için Realtime Database daha uygun bir seçim olabilir.
Realtime Database, basit veri yapısı ve yüksek güncelleme sıklığı olan senaryolar için daha uygundur. Tipik örnekler: sohbetler, gerçek zamanlı beğeniler, yazma göstergeleri, kullanıcı varlık durumları. Ayrıca prototipler ve sınırlı bütçeli projeler için de iyi bir seçimdir, çünkü fiyatlandırma işlem sayısına değil, veri hacmine dayanır.
Öte yandan, karmaşık sorgular (birden çok alana göre filtreleme, sıralama, toplama) gerektiren uygulamalar için Firestore çok daha güçlü yetenekler sunar. Realtime Database yalnızca tek bir parametreye göre filtrelemeyi destekler ve sonuçları birden çok alana göre aynı anda sıralayamaz. Bir proje istemci tarafında karmaşık veri analizi planlıyorsa, Firestore daha pratik bir seçim olacaktır.
Realtime Database, çift yönlü veri senkronizasyonu için kalıcı bir WebSocket bağlantısı kullanır. Bir istemci belirli bir yolda setValue veya updateChildren çağrısı yaptığında, veriler açık kanal üzerinden Firebase sunucusuna gönderilir. Sunucu değişiklikleri uygular ve milisaniyeler içinde abone olan tüm istemcilere güncellemeleri dağıtır. Her bağlantı, benzersiz bir oturum anahtarıyla tanımlanır.
Abonelik mekanizması, dinleyiciler (listener) aracılığıyla çalışır. Bir geliştirici belirli bir düğümdeki değişikliklere abone olabilir (addListenerForSingleValueEvent) veya sürekli güncellemeler alabilir (addValueEventListener). Veriler her değiştiğinde, belirtilen yoldaki tam veri anlık görüntüsüyle birlikte onDataChange geri çağrımı tetiklenir. Bu, yalnızca değiştirilen belgelerin alındığı Firestore'dan farklıdır — Realtime Database'de her zaman düğümün tüm verileri yüklenir.
Realtime Database, disk önbelleği aracılığıyla Android ve iOS'ta çevrimdışı modu destekler. SDK, verilerin yerel bir kopyasını tutar ve ağ olmadığında yazma işlemlerini işlemeye devam eder. Bağlantı yenilendiğinde, birikmiş tüm değişiklikler sunucuya gönderilir. Çatışma çözümü için son yazan kazanır (last-write-wins) stratejisi kullanılır, ancak geliştiriciler çarpışma çözümü için ServerValue.TIMESTAMP aracılığıyla özel mantık uygulayabilir.
val database = FirebaseDatabase.getInstance()
val myRef = database.getReference("messages")
// Veri yazma
myRef.push().setValue(
hashMapOf(
"text" to "Yeni mesaj",
"timestamp" to ServerValue.TIMESTAMP
)
)
// Sürekli güncellemelerle okuma
myRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val data = snapshot.getValue()
Log.d("TAG", "Veri: $data")
}
override fun onCancelled(error: DatabaseError) {
Log.w("TAG", "Hata: ${error.message}")
}
})
Trafik ve performansı optimize etmek için, belirli alt düğümlerdeki değişiklikleri izlerken değer dinleyicileri (value listeners) yerine alt düğüm dinleyicileri (child listeners) kullanılması önerilir. ChildEventListener, alt öğelerin eklenmesi, değiştirilmesi, kaldırılması ve taşınması için ayrı geri çağrımlar sağlayarak kullanıcı arayüzü güncellemelerinin daha hassas kontrolünü sağlar ve her veri değişikliğinde tüm liste öğelerini yeniden çizmeyi önler.
Realtime Database, veri erişim kontrolü için bildirimsel bir kural dili kullanır. Kurallar, JSON ağacının her yolunda kimin veri okuyup yazabileceğini tanımlar. Her istekten önce Firebase sunucusunda kontrol edilirler ve yetkilendirme için sunucu tarafı mantığı gerektirmezler. Kurallar, esnek erişim yapılandırması için değişkenleri, yerleşik nesneleri ve işlevleri destekler.
Varsayılan olarak, veritabanına erişim tüm kullanıcılar için reddedilir. Geliştirici, ağacın çeşitli seviyelerinde ".read" ve ".write" kurallarını kullanarak erişimi kademeli olarak açar. Koşullar, auth değişkeni aracılığıyla kimlik doğrulamayı, istek türünü (okuma/yazma) ve data nesnesi aracılığıyla mevcut verileri kontrol edebilir. Ayrıca kurallar, newData nesnesi aracılığıyla yazılan verilerin doğrulanmasını destekler.
{
"rules": {
"users": {
"$uid": {
// Yalnızca sahibi verilerini okuyabilir
".read": "$uid === auth.uid",
// Yalnızca sahibi yazabilir
".write": "$uid === auth.uid",
// Yazarken alan doğrulama
".validate": "newData.hasChildren(['name', 'email'])"
}
},
"messages": {
// Kimliği doğrulanmış herhangi bir kullanıcı okuyabilir
".read": "auth !== null",
// Yalnızca kimliği doğrulanmış kullanıcı yazabilir
".write": "auth !== null",
".indexOn": ["timestamp"]
}
}
}
Kurallar ayrıca ".indexOn" yönergesi aracılığıyla veri indekslemeyi de destekler. Bu olmadan, sıralamalı sorgular (orderByChild) reddedilir veya verimsiz bir şekilde yürütülür. Dizinler, belirli bir alana göre sıralamanın yapıldığı her yol için belirtilir. Kurallar basamaklıdır: daha derin kurallar üst kuralları geçersiz kılar ve bir seviyede erişim tanımlanmamışsa, üst kurala bağlı olarak izin verilmiş veya reddedilmiş sayılır.
Realtime Database beş veri türünü destekler: String, Number, Boolean, Map (nesne) ve List (dizi). İç içe geçme derinliği 32 seviye ile sınırlıdır ve tek bir düğümün maksimum boyutu 256 MB'ı geçmemelidir. Veritabanıyla verimli çalışma için, düz bir veri yapısı tasarlanması ve büyük miktarlarda veri yükleyen derin sorgulardan kaçınmak için normalizasyonun kaldırılması önerilir.
Kullanıcı durumları (çevrimiçi/çevrimdışı) için bir Android uygulamasına Realtime Database entegrasyonunun pratik bir örneğini ele alalım. Uygulama, gerçek zamanlı olarak güncellenen mevcut durumlarıyla birlikte bir kullanıcı listesi gösterecektir. Gösterim için kullanıcı tanımlama için Firebase Authentication ve eşzamansız işlemler için coroutine'ler kullanılır.
Başlamak için, uygulama modülü build.gradle dosyasına firebase-database-ktx bağımlılığını ekleyin. Tüm bileşenlerin uyumluluğunu sağlamak için kütüphane sürümü Firebase BoM aracılığıyla yönetilir. Bağımlılığı ekledikten sonra Firebase, Application sınıfında veya ViewModel'de tembel başlatma yoluyla başlatılmalıdır.
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"
}
Yapılandırmadan sonra, kullanıcılarla çalışmak için bir depo (repository) oluşturulur. Her kullanıcı, name, email ve status alanlarıyla /users/{uid} ağacında bir düğümle temsil edilir. Durum izleme için onDisconnect kullanılır — istemci bağlantısı kesildiğinde otomatik olarak bir yazma işlemi gerçekleştiren özel bir Firebase mekanizması. Bu, istemci tarafında ek kod olmadan uygulama kapatıldığında veya ağ kaybedildiğinde kullanıcı durumunun "offline" olarak değişmesini sağlar.
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()
}
}
Örneğin anahtar öğesi onDisconnect'tir. Bu mekanizma, istemci bağlantısı kesildiğinde sunucuda yürütülecek bir yazma işlemi ayarlamaya olanak tanır. Bu durumda, kullanıcının bağlantısı kesildiğinde, uygulama kapanma olayını işlemeye gerek kalmadan durumu otomatik olarak "offline" olarak ayarlanır. Uygulama çökerse, Firebase onDisconnect işlemini kendisi gerçekleştirir ve diğer kullanıcılar doğru durumu görür.
Sıkça Sorulan Sorular
Realtime Database verileri tek bir JSON ağacında depolar ve daha düşük senkronizasyon gecikmesi sağlar. Firestore belge koleksiyonları kullanır, karmaşık sorguları ve güçlü tutarlılığı destekler. Realtime Database basit sohbetler ve durumlar için daha iyidir, Firestore karmaşık veri yapıları ve analitiği olan uygulamalar için daha iyidir.
Tek bir Realtime Database düğümünün maksimum boyutu 256 MB'dir. İç içe geçme derinliği 32 seviye ile sınırlıdır. Bir Firebase projesi için birden çok Realtime Database örneği oluşturulabilir (Spark planında 5'e kadar ve Blaze planında 100'e kadar), bu da verilerin farklı örnekler arasında dağıtılmasına olanak tanır.
Realtime Database, Firebase Authentication ile entegre olur. Güvenlik kurallarında, kimliği doğrulanmış kullanıcının uid'sini içeren auth değişkeni kullanılabilir. Geliştiriciler, veri sahibinin uid'sini kontrol ederek JSON ağacının tek tek düğüm seviyesinde erişimi kısıtlayabilir. Anonim ve kimliği doğrulanmamış kullanıcılar için auth = null'dur.
Evet, Realtime Database, runTransaction yöntemi aracılığıyla işlemleri destekler. Bir işlem, tek bir düğüm için okuma-değiştirme-yazma işleminin atomikliğini garanti eder. Eşzamanlı değişiklikler olduğunda, işlem güncel verilerle yeniden denenir. Bu, sayaçlar, derecelendirmeler ve veri tutarlılığının önemli olduğu diğer senaryolar için kullanışlıdır.
Evet, Realtime Database Android ve iOS'ta çevrimdışı modu destekler. SDK, verileri yerel olarak önbelleğe alır ve ağ olmadığında yazma işlemlerini işlemeye devam eder. Bağlantı yenilendiğinde, birikmiş tüm değişiklikler sunucuyla senkronize edilir. Çevrimdışı modu etkinleştirmek için, istenen düğümde keepSynced(true) yöntemini kullanın.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun