Sharding, veriyi düğümler arasında bölerek veritabanlarını ölçeklendirir; ancak yönlendirme, yeniden dengeleme ve yeni hata modları ekleyerek sistemleri anlamayı zorlaştırır.

Sharding (başka bir deyişle yatay bölümleme), uygulamanıza tek bir veritabanı gibi görünen yapıyı alıp veriyi birden çok makineye, yani shardlara bölmek anlamına gelir. Her shard yalnızca satırların bir alt kümesini tutar; birlikte tam veri kümesini oluştururlar.
Yararlı bir zihinsel model, mantıksal yapı ile fiziksel yerleşim arasındaki farktır.
Uygulamanın bakış açısından, sorguları tek bir tabloymuş gibi çalıştırmak istersiniz. Alt katta sistem hangi shard(lar)la konuşulacağını belirlemelidir.
Sharding, replikasyondan farklıdır. Replikasyon aynı verinin kopyalarını birden çok düğüme koyar; esas olarak yüksek erişilebilirlik ve okuma ölçeklendirmesi içindir. Sharding ise veriyi böler; her düğüm farklı kayıtları tutar.
Ayrıca dikey ölçeklendirmeden de farklıdır: tek veritabanını daha güçlü bir makineye taşımaktır (daha fazla CPU/RAM/daha hızlı diskler). Dikey ölçeklendirme daha basit olabilir ama pratik sınırları ve maliyetleri vardır.
Sharding kapasiteyi artırır, ancak veritabanınızı “kolay” veya her sorguyu otomatik olarak daha hızlı yapmaz.
Bu yüzden sharding depolama ve throughput'u ölçeklendirme yolu olarak en iyi anlaşılmalıdır—her veritabanı davranışını ücretsiz olarak düzeltmez.
Sharding genellikle bir takımın ilk tercihi değildir. Takımlar başarılı bir sistem fiziksel sınırlarına ulaştığında veya operasyonel ağrı dayanılmaz olduğunda sharding'e yönelirler. Motivasyon daha çok "sharding istiyoruz" değil, "tek bir veritabanının tek bir hata noktası ve maliyet olmasını engellemenin bir yolu gerekiyor" şeklindedir.
Tek bir veritabanı düğümü çeşitli açılardan yer sıkıntısı çekebilir:
Bu sorunlar düzenli görünüyorsa, genellikle sorun tek bir kötü sorgu değil—bir makinenin çok fazla sorumluluk taşımasıdır.
Veritabanı sharding'i, veriyi ve trafiği birden çok düğüme yayar; böylece kapasite tek bir makineyi dikey olarak yükseltmek yerine makine ekleyerek büyür. İyi yapılırsa, iş yüklerini izole edebilir (bir tenant'in ani trafiği diğerlerinin gecikmesini bozmaz) ve maliyetleri kontrol altında tutar—çok büyük premium örneklere bağlı kalmadan.
Tekrarlayan desenler şunlardır: zirvede p95/p99 gecikmelerinin sürekli artması, replikasyon gecikmesinin uzaması, yedekleme/geri yük süresinin kabul edilebilir pencerenizi aşması ve "küçük" şema değişikliklerinin büyük olaylar haline gelmesi.
Karar vermeden önce takımlar genellikle daha basit seçenekleri tüketir: indeksleme ve sorgu düzeltmeleri, cache, read replica'lar, tek veritabanında partition'lama, eski verileri arşivleme ve donanım yükseltmeleri. Sharding ölçek problemini çözebilir ama koordinasyon, operasyonel karmaşıklık ve yeni hata modları getirir—bu yüzden bar yüksek olmalıdır.
Shardlanmış bir veritabanı tek bir şey değildir—işbirliği yapan küçük parçaların bir sistemidir. Sharding'in “anlaşılması zor” hissettirmesinin nedeni, doğruluk ve performansın bu parçaların nasıl etkileştiğine bağlı olmasıdır, sadece veritabanı motoruna değil.
Bir shard, verinin bir alt kümesidir ve genellikle kendi sunucusunda veya kümesinde depolanır. Her shard tipik olarak şunlara sahiptir:
Uygulama açısından, shardlanmış bir kurulum genellikle tek bir mantıksal veritabanı gibi görünmeye çalışır. Ama alt katta, tek düğümlü bir veritabanında “bir indeks bakışı” olacak sorgu, bir shard'ı bulma ve ardından aramayı yapma adımına dönüşebilir.
Bir router (bazen koordinatör, sorgu router'ı veya proxy olarak adlandırılır) trafik polisidir. Pratik soru: bu istek verildiğinde, hangi shard bununla ilgilenmeli?
İki yaygın desen vardır:
Router'lar uygulamadaki karmaşıklığı azaltır, ama dikkatli tasarlanmazsa darboğaz veya yeni bir hata noktası olabilirler.
Sharding metadata'ya dayanır—şunları tanımlayan bir gerçek kaynağı:
Bu bilgiler genellikle bir konfig servisinde (veya küçük bir kontrol planı veritabanında) tutulur. Metadata eski veya tutarsızsa, tüm shard'lar sağlıklı olsa bile router'lar trafiği yanlış yere gönderebilir.
Son olarak, sharding sistemi zaman içinde yaşanabilir tutan arka plan süreçlerine dayanır:
Bu işler genellikle başta göz ardı edilir, fakat üretimde birçok sürpriz burada çıkar—çünkü bu işler sistemi trafik hizmet ederken şekillendirir.
Bir shard anahtarı, sisteminizin bir satırı/dökümanı hangi shard'a koyacağını belirleyen alandır. Bu tek seçim, sorguların hedeflenip hedeflenmeyeceğini, masrafları ve hangi özelliklerin ileride “kolay” hissedileceğini sessizce belirler—çünkü ortak sorguların tek shard'a mı yoksa birçok shard'a mı gitmesini kontrol eder.
İyi bir anahtar genellikle şunlara sahiptir:
user_id).Çok kiracılı bir uygulamada tenant_id ile shardlama yaygındır: çoğu okuma ve yazma bir tenant için aynı shard'ta kalır ve tenant'lar yeterince fazla olduğunda yük dağılır.
Bazı anahtarlar neredeyse doğrudan sorun getirir:
Düşük kardinaliteli bir anahtar filtreleme için uygun görünse bile, ilgili satırlar her yerde olduğundan rutin sorguları genellikle scatter-gather sorgularına dönüştürür.
Yük dengeleme için en iyi shard anahtarı her zaman ürün sorguları için en iyi anahtar değildir.
region), hotspot'lar ve dengesiz kapasite riski alırsınız.Çoğu takım bu takası göze alır: shard anahtarını en sık ve gecikme açısından kritik işlemler için optimize edin; gerisini indeksler, denormalizasyon, replikalar veya özel analitik tablolarla yönetin.
Tek bir “en iyi” yol yoktur. Seçtiğiniz strateji sorguların nasıl yönlendirileceğini, verinin ne kadar eşit dağıtılacağını ve hangi erişim desenlerinin problem yaratacağını belirler.
Range sharding'de her shard bir anahtar uzayının bitişik bir dilimini sahiplenir—örneğin:
Routing açıktır: anahtara bak ve shard'ı seç.
Ancak hotspot riski vardır. Yeni kullanıcılar hep artan ID alıyorsa, “son” shard yazma darboğazı olur. Aralık sharding ayrıca düzensiz büyümeye duyarlıdır (bir aralık popüler olur, diğeri sessiz kalır). Artı tarafı: aralık sorguları fiziksel olarak gruplanmış veri sayesinde verimli olabilir (ör. "1–31 Ekim arasındaki siparişler").
Hash sharding anahtarın bir hash fonksiyonundan geçirilip sonuçla shard seçilmesine dayanır. Bu genellikle veriyi daha eşit dağıtır ve en yeni shard'a yığılma sorununu önler.
Takas: aralık sorguları zorlaşır. X ile Y arasındaki ID'leri sorgulamak artık küçük bir shard setine eşlenmeyebilir; birçok shard'ı dokunabilir.
Takımaların sıklıkla hafife aldığı pratik bir detay tutarlı hashing (consistent hashing) kullanmaktır. Doğrudan shard sayısına eşlemek (shard sayısı değişince her şeyi yeniden karıştırır) yerine, birçok sistem hash ring ve “sanal düğümler” kullanır, böylece kapasite eklenince yalnızca bir kısmı taşınır.
Directory sharding, anahtar → shard konumunu açıkça saklayan bir harita/servis kullanır. Bu en esnektir: belirli tenantları özel shardlara koyabilir, bir müşteriyi tek başına taşıyabilir ve düzensiz shard boyutlarını destekleyebilirsiniz.
Dezavantajı ek bir bağımlılıktır. Dizin yavaşsa, eskiyse veya ulaşılmazsa routing zarar görür—shard'lar sağlıklı olsa bile.
Gerçek sistemler genellikle yaklaşımları harmanlar. Bir bileşik shard anahtarı (örn. tenant_id + user_id) tenant'ları izole ederken tenant içinde yükü dağıtır. Alt-shardlama benzer: önce tenant'a göre yönlendir, sonra o tenant'ın shard grubunda hash yaparak tek bir "büyük tenant"ın tek bir shard'ı domine etmesini önle.
Shardlanmış bir veritabanının iki çok farklı “sorgu yolu” vardır. Hangi yolun kullanıldığını anlamak, performanstaki çoğu sürprizi ve neden sharding'in öngörülemez hissettirdiğini açıklar.
İdeal sonuç, sorguyu tam olarak bir shard'a yönlendirmektir. İstek shard anahtarını içeriyorsa veya router bununla eşleyebiliyorsa, sistem doğrudan doğru yere gönderebilir.
Bu yüzden takımlar sık okunanların "shard-key farkında" olmasına takıntılıdır. Tek shard, daha az ağ atlaması, daha basit yürütme, daha az kilit ve çok daha az koordinasyon demektir. Gecikme çoğunlukla veritabanının işi yapmasından gelir, küme üzerinde tartışmadan değil.
Bir sorgu kesin yönlendirilemiyorsa (ör. non-shard-key alanına göre filtreliyorsa), sistem bunu birçok veya tüm shardlara yayınlayabilir. Her shard sorguyu yerel olarak çalıştırır; ardından router (veya koordinatör) sonuçları birleştirir—sıralama, tekrarlardan arındırma, limit uygulama ve kısmi agregatları toplama.
Bu fan-out kuyruk gecikmesini büyütür: 9 shard hızlı cevap verse bile bir yavaş shard tüm isteği rehin alabilir. Ayrıca yükü katlar: bir kullanıcı isteği N shard isteğine dönüşür.
Shardlar arası join'ler pahalıdır çünkü birlikte olması gereken veriler artık shardlar arasında taşınmak zorundadır (veya bir koordinatöre). Basit agregasyonlar (COUNT, SUM, GROUP BY) bile iki aşamalı plan gerektirebilir: her shard üzerinde kısmi sonuç hesapla, sonra birleştir.
Çoğu sistem varsayılan olarak lokal indeksleri kullanır: her shard yalnızca kendi verisini indeksler. Bunlar bakım açısından ucuzdur ama routing'e yardımcı olmaz—dolayısıyla sorgular yine scatter olabilir.
Global indeksler shard anahtar olmayan alanlarda hedefli yönlendirme sağlayabilir, ama yazma yükünü, ekstra koordinasyonu ve ölçek/tutarlılık zorluklarını artırır.
Yazmalar, sharding'in "sadece ölçeklendirme" olmaktan çıkıp özelliklerin nasıl tasarlandığını değiştirdiği kısımdır. Tek bir shard'ı dokunan yazma hızlı ve basit olabilir. Mantıksal olarak iki shard'ı etkileyen bir yazma ise yavaş, hata eğilimli ve doğru yapmak açısından şaşırtıcı derecede zor olabilir.
Her istek tam olarak bir shard'a yönlendirilebiliyorsa (genellikle shard anahtar ile), veritabanı normal transaction mekanizmasını kullanabilir. O shard içinde atomiklik ve izolasyon elde edersiniz; operasyonel problemler tanıdık tek-düğüm sorunlarına benzer.
Mantıksal bir eylem iki shard'ı güncellemesi gerektiğinde (örn. para transferi, siparişi bir müşteriden diğerine taşıma, başka yerde saklanan bir agregatı güncelleme) dağıtık işlem alanına girersiniz.
Dağıtık işlemler zordur çünkü koordinasyon gerektirir: makineler yavaş olabilir, ağ bölünebilir veya yeniden başlatılabilir. İki fazlı commit benzeri protokoller ekstra tur-trip ekler, zaman aşımında bloklanabilir ve hataları belirsizleştirir: koordinatör ölmeden önce shard B değişikliği uyguladı mı? İstemci yeniden denediğinde yazmayı iki kere mi uygularsınız? Yeniden deneme yapılmazsa veri kaybı mı olur?
Sık kullanılan taktikler:
Shardlanmış sistemlerde yeniden denemeler kaçınılmazdır. Yazmaları idempotent yapmak için stabil operasyon ID'leri (örn. idempotency anahtarı) kullanın ve veritabanında "zaten uygulandı" işaretleri saklayın. Böylece zaman aşımı olursa istemci yeniden denediğinde ikinci deneme no-op olur; çift uygulama, yinelenen sipariş veya tutarsız sayaç önlenir.
Sharding verinizi makineler arasında böler, ama yedeklilik ihtiyacını ortadan kaldırmaz. Replikasyon bir shard'ın bir düğümü öldüğünde onu kullanılabilir tutar—aynı zamanda "şu an ne doğru?" sorusunu daha zor hale getirir.
Çoğu sistem her shard içinde replikasyon yapar: bir primary (leader) yazmaları kabul eder ve bir veya daha fazla replica bu değişiklikleri kopyalar. Primary düşerse sistem bir replicayı terfi ettirir (failover). Replikalar ayrıca okumaları karşılayarak yükü azaltabilir.
Takas zamanlamadır. Bir read replica milisaniyeler veya saniyeler geride olabilir. Bu boşluk normaldir, ama kullanıcı "az önce güncelledim, şimdi göreceğim" beklentisi olduğunda fark eder.
Shard kurulumlarında genellikle bir shard içinde güçlü tutarlılık ve shard'lar arasında daha zayıf garantiler ile karşılaşırsınız, özellikle çok-shard işlemler söz konusu olduğunda.
Sharding ile “tek doğru kaynak” genellikle şunu ifade eder: her veri parçası için yazılacak tek bir yetkili yer vardır (genellikle shard'ın leader'ı). Ancak küresel olarak her şeyin en son durumunu anında onaylayabilecek tek bir makine yoktur. Birçok yerel gerçek vardır ve bunlar replikasyon yoluyla senkron tutulmalıdır.
Kısıtlamalar farklı shard'larda bulunan verilerle kontrol edilmesi gerektiğinde zordur:
Bu seçimler sadece uygulama detayları değildir—ürününüz için "doğru"nün ne demek olduğunu tanımlar.
Yeniden dengeleme, gerçeklik değiştikçe shardlanmış veritabanını kullanılabilir tutan şeydir. Veri dengesiz büyür, başlangıçta dengeli görünen shard anahtarı çarpıklığa kayar, yeni düğümler eklenir veya donanım emekliye ayrılmalıdır. Bunların her biri bir shard'ı darboğaz haline getirebilir—ilk tasarım mükemmel görünse bile.
Tek bir veritabanının aksine, sharding verinin konumunu routing mantığına yerleştirir. Veri taşırken yalnızca byte kopyalamıyorsunuz—sorguların nereye gitmesi gerektiğini değiştiriyorsunuz. Bu yüzden yeniden dengeleme metadata ve istemciler kadar depolama ile ilgilidir.
Çoğu takım canlı bir iş akışı hedefler:
Bir shard haritası değişikliği, istemciler routing kararını cache'liyorsa kırıcı bir olay olabilir. İyi sistemler routing metadata'sını konfigürasyon gibi ele alır: versiyonlayın, sık yenileyin ve bir istemci taşınmış bir anahtarla karşılaştığında ne olacağını açıkça tanımlayın (yönlendir, yeniden dene veya proxy).
Yeniden dengeleme genellikle geçici performans düşüşlerine neden olur (ekstra yazmalar, cache çalkantısı, arka plan kopya yükü). Kısmi taşımalar yaygındır—bazı aralıklar önce taşınır—bu yüzden gözlemlenebilirlik ve geri alma planı (ör. haritayı geri çevirme ve çift yazmayı boşaltma) olmadan cutover'a başlamayın.
Sharding işin yayılacağını varsayar. Sürpriz şu ki, küme kağıt üzerinde "eşit" görünürken üretimde aşırı düzensiz davranabilir.
Bir anahtar alanının küçük bir dilimi trafiğin çoğunu çektiğinde hotspot oluşur—örneğin ünlü bir hesap, popüler bir ürün, ağır batch işi yapan bir tenant veya "bugün"ün tüm yazmaları çektiği zaman bazlı anahtar. Bu anahtarlar tek bir shard'a eşlendiğinde o shard darboğaz olur, diğerleri boştadır.
"Çarpıklık" tek bir şey değildir:
Her zaman örtüşmezler: daha az veriye sahip bir shard, en çok istenen anahtarlara sahipse en sıcak olabilir.
Çarpıklığı tespit etmek için gelişmiş izleme gerekmez. Shard başına panolarla başlayın:
Bir shard'ın gecikmesi QPS ile yükselip diğerleri sabit kalıyorsa, muhtemelen bir hotspot var demektir.
Çözümler genellikle basitlikten ödün verip dengeyi iyileştirir:
Sharding yalnızca daha fazla sunucu eklemez—aynı zamanda işlerin ters gitmesi için daha fazla yol ve sorun olduğunda bakılacak daha fazla yer ekler. Birçok olay "veritabanı kapandı" değil, "bir shard kapandı" veya "sistem verinin nerede olduğunu bilemiyor" şeklindedir.
Tekrar eden desenler şunlardır:
Tek düğümlü bir veritabanında bir logu takip edip bir metrik setine bakarsınız. Sharded bir sistemde, bir isteği shardlar arasında takip eden gözlemlenebilirlik gerekir.
Her istekte correlation ID'leri kullanın ve bunları API katmanından router'lara ve her shard'a kadar taşıyın. Bunu dağıtık izleme (distributed tracing) ile eşleştirerek bir scatter-gather sorguda hangi shard'ın yavaş veya başarısız olduğunu görebilirsiniz. Metrikler shard bazında kırılmalıdır (gecikme, kuyruk derinliği, hata oranı), aksi takdirde sıcak bir shard filo ortalamalarında gizlenir.
Sharding hataları genellikle doğruluk hataları olarak görünür:
"Veritabanını geri yükle" demek artık "doğru sırada birçok parçayı geri yükle" demektir. Önce metadatayı, sonra her shard'ı geri yüklemeniz ve shard sınırlarının ve routing kurallarının geri yüklenen noktayla eşleştiğini doğrulamanız gerekebilir. DR planları, tutarlı bir küme oluşturabileceğinizi kanıtlayan prova çalışmaları içermelidir—sadece bireysel makineleri kurtarmak yeterli değildir.
Sharding genellikle “ölçeklendirme düğmesi” olarak görülür, ama aynı zamanda sistem karmaşıklığında kalıcı bir artıştır. Verileri düğümler arası bölmeden performans ve güvenilirlik hedeflerinize ulaşabiliyorsanız, genellikle daha basit bir mimari, daha kolay hata ayıklama ve daha az operasyonel uç durum elde edersiniz.
Sharding'e başlamadan önce tek mantıksal veritabanını koruyan seçenekleri deneyin:
Sharding riskini azaltmanın pratik yollarından biri altyapıyı (routing sınırları, idempotency, taşıma iş akışları ve gözlemlenebilirlik) üretime bağlamadan önce prototiplemektir.
Örneğin, Koder.ai ile chat üzerinden küçük, gerçekçi bir servis hızla kurabilir—genellikle bir React yönetici UI'si artı Go arka ucu ve PostgreSQL—ve shard-anahtar farkındalıklı API'leri, idempotency anahtarlarını ve "cutover" davranışlarını güvenli bir sandbox'ta deneyebilirsiniz. Koder.ai planlama modu, anlık görüntüler/geri alma ve kaynak kodu dışa aktarma desteklediği için shard ile ilgili tasarım kararlarını yineleyip, kodu ve çalışma kitaplarını ana yığınıza geçirene dek test edebilirsiniz.
Sharding, veri setiniz veya yazma throughput'unuz açıkça tek düğüm sınırlarını aştığında ve sorgu desenlerinizin çoğu shard anahtarıyla güvenle yönlendirilebildiğinde daha uygundur (az çapraz-shard join, minimal scatter-gather sorgu).
Sık ad-hoc sorgular, sık çok-varlıklı işlemler, küresel benzersizlik kısıtları veya takımın operasyonel işi (yeniden dengeleme, resharding, olay müdahalesi) destekleyememesi durumunda sharding kötü bir uyumdur.
Sor:
Sharding'i erteleseniz bile, bir taşıma yolu tasarlayın: ileride engel olmayacak kimlikler seçin, tek-düğüm varsayımlarını kodlamaktan kaçının ve veriyi minimum kesintiyle nasıl taşıyacağınızı prova edin. En iyi zaman resharding'i planlamak, ihtiyacınız olmadan önce olandır.
Sharding (yatay bölümleme), tek bir mantıksal veri kümesini birden çok makineye (“shard”lara) bölerek her shard'ın farklı satırları tutmasıdır.
Replikasyon ise aynı verinin birden çok düğümde kopyalarını tutar—esas olarak erişilebilirlik ve okuma ölçeklendirme için kullanılır.
Dikey ölçeklendirme, tek bir veritabanı sunucusunu yükseltmeyi (daha fazla CPU/RAM/daha hızlı diskler) ifade eder. Operasyonel olarak daha basittir ama sonunda sert sınırlara veya yüksek maliyete takılırsınız.
Sharding, makineleri ekleyerek yatay olarak ölçeklendirir ama yönlendirme, yeniden dengeleme ve çapraz-shard doğruluk zorluklarını beraberinde getirir.
Takımlar genellikle tek bir düğümün tekrarlayan darboğaz olduğu durumlarda shardlar:
Sharding veri ve trafiği yayarak kapasitenin makine ekleyerek büyümesini sağlar.
Tipik bir sharded sistem şunları içerir:
Performans ve doğruluk bu parçaların tutarlı kalmasına bağlıdır.
Shard anahtarı, bir satırın hangi shard'ta saklanacağını belirlemek için kullanılan alandır. Bu seçim, isteklerin tek bir shard'a mı yoksa birçok shard'a mı gideceğini belirleyerek performansı ve maliyeti şekillendirir.
İyi shard anahtarları genellikle yüksek kardinaliteye, eşit dağılıma sahiptir ve sık kullanılan erişim desenleriyle uyumludur (ör. tenant_id veya user_id).
Kötü shard anahtarları genellikle şunlardır:
Bunlar hotspot'lara yol açar veya rutin sorguları scatter-gather fan-out'lara çevirir.
Yaygın stratejiler:
Eğer sorgu shard anahtarını içeriyorsa router tek bir shard'a gönderebilir—bu hızlı yol.
Kesin yönlendirilemeyen sorgular birçok/ tüm shardlara fan-out yapabilir (scatter-gather). Bu durumda tek bir yavaş shard tüm isteği bekletir ve bir kullanıcı isteği N shard isteğine dönüşür.
Tek-shard yazmalar normal veritabanı işlemleri gibi çalışır.
Çapraz-shard yazmalar makinelere koordinasyon gerektirir (çoğunlukla iki fazlı commit benzeri protokoller), bu da gecikmeyi ve hata belirsizliğini artırır. Pratik azaltıcılar:
Sharding yerine önce tek mantıksal veritabanını koruyan seçenekleri deneyin:
Sharding, tek düğüm sınırlarını aştığınızda ve kritik sorguların çoğu shard anahtarı ile yönlendirilebildiğinde daha uygundur.