MongoDB sharding, veriyi birden fazla sunucuya bölerek tek makinenin sınırlarının ötesine geçme yöntemidir. Tek bir replica set'te veri büyüdükçe önce bellek yetmez, sonra disk yetmez, en sonunda birincil üyenin yazma kapasitesi tavana vurur — çünkü replica set yatay olarak okuma ölçekler, yazma yükünün tamamı hep tek bir birincile biner. Sharding tam olarak bu duvarı yıkar: koleksiyonu parçalara ayırır, her parçayı ayrı bir replica set'e dağıtır ve yazma yükünü sunucu sayısına böler.
Bunun bir bedeli var ve bu rehberin en önemli mesajı da bu: sharding, kurulum karmaşıklığını üçe katlar, geri dönüşü zor bir karar olan parçalama anahtarı seçimini dayatır ve yanlış tasarlandığında hiçbir şeyi hızlandırmaz, sadece işletim yükünü artırır. Aşağıda önce sharding'in ne zaman gerçekten gerekli olduğunu, sonra kümenin üç bileşenini, parçalama anahtarı seçiminin kurallarını, aralık ile hash tabanlı parçalama arasındaki farkı, kurulum adımlarını ve dengeleyicinin nasıl izleneceğini anlatacağım. Sonda da sık yapılan hataların listesi var.
Sharding Ne Zaman Gerekir, Ne Zaman Gerekmez#
Sharding'e geçmeden önce cevaplamanız gereken tek soru şudur: tek bir replica set, sıcak verinizi (working set) bellekte tutabiliyor mu ve yazma hacminizi karşılıyor mu? Cevap evetse sharding size hız kazandırmaz; aksine ek bir ağ atlaması ekleyerek gecikmeyi biraz artırır.
Sharding'i gerçekten gerektiren üç durum var. Birincisi bellek duvarı: veri kümesi, en büyük makinenizin belleğine sığmıyor ve sorgular sürekli diske iniyor. İkincisi yazma duvarı: tek birincil düğüm, gelen yazma hacmini karşılayamıyor; disk kuyruğu sürekli dolu ve gecikme tırmanıyor. Üçüncüsü depolama duvarı: veri, tek sunucuya takabileceğiniz en büyük diskten büyük.
Bunların hiçbiri geçerli değilken önce ucuz yolları deneyin: index tasarımını düzeltmek çoğu zaman on kat kazanç verir, ve bunu nasıl yapacağınızı MongoDB index ve sorgu optimizasyonu yazısında bulabilirsiniz. Raporlama sorgularını ikincil üyelere kaydırmak, gereksiz alanları projeksiyonla elemek, eski veriyi arşiv koleksiyonuna taşımak da sharding'den çok daha ucuz adımlardır.
| Belirti | Önce dene | Sharding gerekir mi |
|---|---|---|
| Sorgular yavaş, işlemci düşük | Index tasarımı | Hayır |
| Rapor sorguları uygulamayı yavaşlatıyor | İkincilden okuma | Hayır |
| Disk doldu ama veri çoğu eski | Arşivleme, TTL index | Hayır |
| Sıcak veri belleğe sığmıyor | Bellek yükseltmesi | Sınır aşıldıysa evet |
| Tek birincil yazmaya yetişemiyor | Toplu yazma, disk yükseltmesi | Sınır aşıldıysa evet |
| Veri tek diskten büyük | — | Evet |
Sharded Cluster'ın Üç Bileşeni#
Parçalanmış bir küme, üç ayrı rolden oluşur ve üçü de ayrı süreçlerdir.
Shard'lar, asıl veriyi tutar. Üretimde her shard kendi başına bir replica set olmalıdır; aksi hâlde tek bir sunucunun arızası kümenin o parçasındaki veriyi tamamen erişilemez yapar. Yani üç shard'lı bir küme, aslında dokuz mongod süreci demektir. Replica set kurulumunu henüz yapmadıysanız MongoDB replica set kurulumu yazısı bu temel adımı anlatıyor.
Config sunucuları, hangi veri aralığının hangi shard'da olduğunu tutan meta veriyi barındırır. Bunlar da bir replica set olarak çalışır ve kümenin beynidir; config replica set'ini kaybederseniz veriniz duruyor olsa bile küme çalışamaz. Bu yüzden config sunucularını üç ayrı fiziksel makineye dağıtın.
mongos, yönlendiricidir. Uygulamanız doğrudan shard'lara değil, mongos'a bağlanır. mongos hiçbir veri tutmaz, config sunucularından aldığı haritayı önbelleğe alır ve gelen her sorguyu doğru shard'a (ya da gerekiyorsa hepsine) iletir. Durumsuz olduğu için istediğiniz kadar mongos çalıştırabilirsiniz; en yaygın ve en sağlıklı desen, her uygulama sunucusuna yerel bir mongos kurmaktır — böylece ağ üzerinde fazladan bir atlama olmaz.
# Tipik bir üç shard'lı kümenin süreç sayısı
# 3 shard x 3 üye = 9 mongod
# 1 config set x 3 üye = 3 mongod
# her uygulama sunucusunda 1 mongos
Bu tablo, sharding'in neden hafife alınmaması gerektiğini iyi anlatır: en küçük üretim kümesi bile on iki mongod süreci demektir.
Parçalama Anahtarı Seçimi#
Parçalama anahtarı (shard key), MongoDB'de vereceğiniz en kritik ve en zor geri alınabilir karardır. Bu anahtar, her belgenin hangi parçaya düşeceğini belirler ve sorgularınızın tek bir shard'a mı yoksa hepsine birden mi gideceğini tayin eder. İyi bir anahtarın üç özelliği vardır:
- Yüksek kardinalite. Anahtarın alabileceği değer sayısı, olası parça sayısından çok daha fazla olmalıdır. İki değerli bir alan (
aktif: true/false) yalnızca iki parça üretebilir; bu, kümeniz ne kadar büyük olursa olsun bir sınırdır. - Düşük frekans. Hiçbir değer, verinin çok büyük bir bölümüne karşılık gelmemelidir. Müşterilerinizin yüzde kırkı tek bir kurumsal hesaba aitse,
musteriIdanahtarı o hesabın parçasını devasa ve hareketsiz yapar. - Tekdüze artmayan (non-monotonic) yapı.
_id(ObjectId), zaman damgası ya da otomatik artan sayaç gibi sürekli artan değerler, tüm yeni yazmaların aynı parçaya gitmesine yol açar. Buna sıcak parça (hot shard) denir ve sharding'in tüm amacını yok eder: on sunucunuz olur, dokuzu boş durur.
Pratikte en iyi sonucu genellikle bileşik anahtarlar verir. Örneğin çok kiracılı bir uygulamada { musteriId: 1, olusturma: 1 } anahtarı hem dağılımı sağlar hem de bir müşterinin verisini birlikte tutar, böylece o müşteriye ait sorgular tek shard'a gider.
// Kötü: tekdüze artan, tüm yazmalar son parçaya gider
sh.shardCollection("uygulamadb.olaylar", { olusturma: 1 })
// Daha iyi: hash ile eşit dağılım (aralık sorgusu kaybedilir)
sh.shardCollection("uygulamadb.olaylar", { _id: "hashed" })
// En iyi: bileşik anahtar — dağılım + kiracı yerelliği
sh.shardCollection("uygulamadb.olaylar", { musteriId: 1, olusturma: 1 })
Anahtar alanı için mutlaka bir index bulunmalıdır; shardCollection bunu talep eder ve yoksa boş koleksiyonda kendisi oluşturur. Ayrıca anahtar alanı her belgede bulunmak zorundadır ve bir belgenin anahtar değerini değiştirmek özel kısıtlara tabidir. Bu yüzden anahtarı, uygulamanın veri modeli oturduktan sonra ve gerçek sorgu desenlerine bakarak seçin.
Aralık, Hash ve Bölge Tabanlı Parçalama#
MongoDB üç dağıtım stratejisi sunar ve seçim doğrudan sorgu desenlerinize bağlıdır.
| Strateji | Dağılım | Aralık sorgusu | Tipik kullanım |
|---|---|---|---|
| Aralık (ranged) | Anahtar değerine göre | Verimli, tek shard'a gider | Kiracı bazlı, tarih aralıklı |
| Hash | Anahtarın karmasına göre | Verimsiz, tüm shard'lara yayılır | Tekdüze artan anahtar zorunluysa |
| Bölge (zone) | Elle tanımlı aralık-shard eşlemesi | Aralığa bağlı | Coğrafi ayrım, sıcak-soğuk katman |
Hash tabanlı parçalama, sıcak parça sorununu kesin biçimde çözer çünkü ardışık değerler bile birbirine uzak karmalara düşer. Bedeli şudur: find({ olusturma: { $gte: ..., $lt: ... } }) gibi bir aralık sorgusu artık tek bir shard'a yönlendirilemez, kümedeki tüm shard'lara yayınlanır ve sonuçlar mongos'ta birleştirilir. Küçük kümede bu tolere edilebilir, yirmi shard'lı bir kümede her sorgu için yirmi ağ isteği demektir.
Bölge tabanlı parçalama ise daha az bilinen ama çok işe yarayan bir araçtır. Belirli anahtar aralıklarını belirli shard'lara sabitlersiniz; örneğin son üç ayın verisini hızlı NVMe diskli shard'larda, daha eski veriyi ucuz ve yavaş disklerde tutabilirsiniz:
// Shard'lara etiket ata
sh.addShardToZone("rs1", "sicak")
sh.addShardToZone("rs3", "soguk")
// Anahtar aralıklarını bölgelere bağla
sh.updateZoneKeyRange("uygulamadb.olaylar",
{ olusturma: ISODate("2026-06-01") }, { olusturma: MaxKey }, "sicak")
sh.updateZoneKeyRange("uygulamadb.olaylar",
{ olusturma: MinKey }, { olusturma: ISODate("2026-06-01") }, "soguk")
Bölge kuralları tanımlandıktan sonra dengeleyici, yığınları kendiliğinden doğru shard'lara taşır. Coğrafi dağıtımda da aynı mekanizma kullanılır: Avrupa müşterilerinin verisini Avrupa'daki shard'larda tutmak, hem gecikmeyi hem de veri yerelliği yükümlülüklerini karşılar.
Kurulum: Config Sunucuları, Shard'lar ve mongos#
Kurulum sırası önemlidir: önce config replica set, sonra shard replica set'leri, en sonda mongos. Config sunucularının yapılandırmasında configsvr rolü belirtilir:
# /etc/mongod.conf — config sunucusu
sharding:
clusterRole: configsvr
replication:
replSetName: cfgrs
net:
port: 27019
bindIp: 127.0.0.1,185.12.34.56
security:
keyFile: /etc/mongodb/keyfile
authorization: enabled
// Config replica set'i başlat (üç config sunucusundan birinde)
rs.initiate({
_id: "cfgrs",
configsvr: true,
members: [
{ _id: 0, host: "cfg1.firmaniz.com:27019" },
{ _id: 1, host: "cfg2.firmaniz.com:27019" },
{ _id: 2, host: "cfg3.firmaniz.com:27019" }
]
})
Shard sunucularında rol shardsvr olur ve her shard kendi replica set adını taşır:
# /etc/mongod.conf — shard üyesi
sharding:
clusterRole: shardsvr
replication:
replSetName: rs1
net:
port: 27018
bindIp: 127.0.0.1,185.12.34.60
security:
keyFile: /etc/mongodb/keyfile
authorization: enabled
Ardından mongos'u başlatın; mongos'un kendi veri dizini yoktur, yalnızca config set'ini bilir:
# /etc/mongos.conf
sharding:
configDB: cfgrs/cfg1.firmaniz.com:27019,cfg2.firmaniz.com:27019,cfg3.firmaniz.com:27019
net:
port: 27017
bindIp: 127.0.0.1,10.0.0.7
security:
keyFile: /etc/mongodb/keyfile
sudo mongos --config /etc/mongos.conf --fork --logpath /var/log/mongodb/mongos.log
Son adım, shard'ları kümeye eklemek ve koleksiyonu parçalamaktır. Bu komutlar mongos üzerinden çalıştırılır, doğrudan shard'lara bağlanarak değil:
// mongos'a bağlan
sh.addShard("rs1/shard1a.firmaniz.com:27018,shard1b.firmaniz.com:27018")
sh.addShard("rs2/shard2a.firmaniz.com:27018,shard2b.firmaniz.com:27018")
// Veritabanında parçalamayı etkinleştir
sh.enableSharding("uygulamadb")
// Anahtar için index oluştur ve koleksiyonu parçala
db.getSiblingDB("uygulamadb").olaylar.createIndex({ musteriId: 1, olusturma: 1 })
sh.shardCollection("uygulamadb.olaylar", { musteriId: 1, olusturma: 1 })
// Durumu gör
sh.status()
Yığınlar, Dengeleyici ve İzleme#
MongoDB veriyi belge belge değil, yığın (chunk) denen anahtar aralıkları hâlinde dağıtır. Bir yığın belirlenen boyutu aştığında bölünür ve dengeleyici (balancer), shard'lar arasındaki yığın sayısı dengesizleştiğinde arka planda taşıma yapar. Varsayılan yığın boyutu MongoDB sürümüne göre 64 MB ya da 128 MB'dır ve nadiren değiştirilmesi gerekir.
// Dengeleyici durumu
sh.getBalancerState()
sh.isBalancerRunning()
// Bakım penceresi için geçici olarak durdur
sh.stopBalancer()
sh.startBalancer()
// Yalnızca gece 01:00-05:00 arasında çalışsın
db.getSiblingDB("config").settings.updateOne(
{ _id: "balancer" },
{ $set: { activeWindow: { start: "01:00", stop: "05:00" } } },
{ upsert: true }
)
Dengeleyiciyi bir bakım penceresine sıkıştırmak, üretimde çok işe yarayan bir alışkanlıktır: yığın taşıma ciddi disk ve ağ trafiği üretir, gündüz saatlerinde bunu istemezsiniz. Dağılımın sağlıklı olup olmadığını görmek için:
// Koleksiyon başına shard dağılımı ve yığın sayıları
db.getSiblingDB("uygulamadb").olaylar.getShardDistribution()
// Örnek çıktı yorumu:
// Shard rs1 -> 512 chunk, 61 GB
// Shard rs2 -> 509 chunk, 60 GB (dengeli)
// Shard rs3 -> 4 chunk, 1 GB (sorunlu: anahtar dağılımı bozuk)
Üçüncü shard'ın neredeyse boş kalması, anahtarın ya tekdüze arttığını ya da kardinalitesinin düşük olduğunu gösterir. Bu tablo, parçalama anahtarını yanlış seçtiğinizin en net kanıtıdır.
Sorgu Yönlendirme ve Sık Yapılan Hatalar#
mongos, bir sorguda parçalama anahtarını görürse onu doğrudan ilgili shard'a gönderir; buna hedefli (targeted) sorgu denir. Anahtarı görmezse sorguyu tüm shard'lara yayınlar (scatter-gather), sonuçları toplar ve birleştirir. İkinci durum, shard sayısı arttıkça giderek pahalılaşır.
// Hedefli: anahtar sorguda var, tek shard'a gider
db.olaylar.find({ musteriId: 4821, olusturma: { $gte: ISODate("2026-08-01") } })
// Yayınlanan: anahtar yok, tüm shard'lara sorulur
db.olaylar.find({ durum: "hata" })
// explain ile hangi shard'lara gittiğini görün
db.olaylar.find({ durum: "hata" }).explain("executionStats").shards
En sık gördüğüm hatalar şunlar:
- Erken sharding. Tek replica set yeterken küme kurmak, kazanç sağlamadan işletim yükünü üçe katlar. Önce index, önbellek ve donanım yolunu tüketin.
- Tekdüze artan anahtar seçmek.
_idya da tarih üzerinden aralık parçalaması, tüm yeni yazmaları son parçaya yığar. Ölçüm yapmadan bunu fark etmezsiniz;getShardDistribution()çıktısı size gerçeği söyler. - Config sunucularını tek makineye kurmak. Config replica set'i kaybedildiğinde küme çalışamaz, veriniz duruyor olsa bile. Üç ayrı makineye dağıtın ve ayrıca yedekleyin.
- Uygulamayı doğrudan shard'a bağlamak. Tek bir shard'a bağlanan bir istemci, verinin yalnızca bir bölümünü görür ve yaptığı yazmalar meta veriyle tutarsızlaşabilir. Tüm erişim mongos üzerinden olmalıdır.
- Yedeklemeyi atlamak. Parçalanmış bir kümede yedekleme, tek düğüme göre daha karmaşıktır: shard'ların ve config sunucularının yedeği birlikte, tutarlı bir anda alınmalıdır. Yedekleme stratejinizi küme kurulumuyla aynı anda planlayın.
- Dengeleyiciyi hiç izlememek. Kapalı kalmış ya da sürekli çalışan bir dengeleyici, ikisi de sorun işaretidir;
sh.isBalancerRunning()çıktısını izleme sisteminize ekleyin.
Sıkça Sorulan Sorular#
Sharding ne zaman gerekli olur#
Tek bir replica set'in sıcak verinizi bellekte tutamadığı, yazma hacmini karşılayamadığı ya da veri hacminin tek diske sığmadığı noktada gerekir. Bu üçünden hiçbiri geçerli değilse sharding size hız kazandırmaz, sadece karmaşıklık ekler. Önce index tasarımını düzeltmek, raporları ikincil üyelere kaydırmak ve eski veriyi arşivlemek çok daha ucuz ve etkili adımlardır.
Parçalama anahtarını sonradan değiştirebilir miyim#
Yeni MongoDB sürümlerinde mevcut bir anahtarın sonuna alan ekleyerek onu iyileştirmek (refine) mümkündür, ancak anahtarı tamamen farklı bir alanla değiştirmek doğrudan desteklenmez. Bu durumda pratik yol, doğru anahtarla yeni bir koleksiyon oluşturup veriyi taşımaktır ki bu da büyük koleksiyonlarda ciddi bir operasyondur. Bu yüzden anahtar seçimini veri modeliniz oturduktan sonra ve gerçek sorgu desenlerine bakarak yapın.
Kaç shard ile başlamalıyım#
En az iki shard olmalıdır, yoksa parçalamanın bir anlamı yoktur; ancak pratikte üç ile başlamak daha sağlıklıdır, çünkü dengeleyicinin davranışını ve dağılımı üç parça üzerinde çok daha net gözlemlersiniz. Her shard'ın kendi içinde üç üyeli bir replica set olması gerektiğini unutmayın; yani üç shard'lı bir küme dokuz veri düğümü demektir.
mongos'u nerede çalıştırmalıyım#
En yaygın ve en verimli desen, her uygulama sunucusunda yerel bir mongos süreci çalıştırmaktır. Böylece uygulama ile yönlendirici arasında ağ atlaması olmaz ve mongos, o sunucunun bağlantı havuzunu yönetir. mongos durumsuzdur, veri tutmaz ve çökerse yalnızca yeniden başlatılır; bu yüzden ayrı bir yüksek erişilebilirlik katmanı gerektirmez.
Parçalanmamış koleksiyonlar nerede durur#
Bir veritabanında parçalamayı etkinleştirdiğinizde, o veritabanının parçalanmamış tüm koleksiyonları "birincil shard" adı verilen tek bir shard'da durur. Yani küçük tablolarınızı parçalamak zorunda değilsiniz; ama o birincil shard'ın bu ek yükü taşıyabildiğinden emin olun. Hangi shard'ın birincil olduğunu sh.status() çıktısında görebilirsiniz.
Sharding okuma performansını artırır mı#
Doğrudan değil. Sorgunuz parçalama anahtarını içeriyorsa tek shard'a gider ve tek replica set'e göre benzer hızda çalışır; içermiyorsa tüm shard'lara yayılır ve mongos sonuçları birleştirirken ek gecikme oluşur. Sharding'in asıl kazancı toplam yazma kapasitesi ve veri hacmidir; okuma performansı için önce index tasarımına ve ikincil üyelerden okumaya bakın.
Kapanış#
Sharding, MongoDB'nin en güçlü ama en pahalı özelliğidir. Aklınızda kalması gereken dört şey var: sharding'e ancak tek replica set gerçekten yetersiz kaldığında geçin, parçalama anahtarını yüksek kardinaliteli ve tekdüze artmayan bir alandan (tercihen bileşik) seçin, config sunucularını üç ayrı makineye dağıtıp ayrıca yedekleyin ve getShardDistribution() çıktısını düzenli olarak kontrol ederek dağılımın gerçekten dengeli olduğunu doğrulayın. Yanlış anahtarla kurulmuş bir küme, tek sunucudan daha yavaş çalışabilir.
On iki süreçli bir kümeyi ayağa kaldırmak için öngörülebilir kaynaklara ve düşük gecikmeli bir özel ağa ihtiyacınız olur. VDS, bulut sunucu ve daha yüksek hacimler için dedicated sunucu paketlerimiz bu tür kümeler için uygundur; kurulum, dengeleyici bakımı ve izleme tarafını devretmek isterseniz sunucu yönetimi hizmetimiz bu yükü üstlenir.