34 puan yazan GN⁺ 2024-03-15 | 1 yorum | WhatsApp'ta paylaş
  • Figma’nın veritabanı ekibinin Postgres yığınını yatay olarak shard’lara böldüğü dokuz aylık yolculuğun ve bunun neredeyse sınırsız ölçeklenebilirliği nasıl mümkün kıldığının özeti

Figma’nın Postgres yığınını yatay shard’lara ayırma yolculuğu

  • Figma’nın veritabanı yığınının ölçeği 2020’den bu yana neredeyse 100 kat arttı: Bu, işin büyüdüğünü gösteren olumlu bir sorun olsa da aynı zamanda teknik zorluklar da yarattı. 2020’de AWS’nin en büyük fiziksel instance’ında tek bir Postgres veritabanı çalıştırılıyordu; 2022 sonuna gelindiğinde ise cache, read replica’lar ve dikey olarak bölünmüş birden çok veritabanını içeren dağıtık bir mimari kuruldu.
  • Dikey bölme: İlişkili tablo grupları kendi dikey partition’larına ayrılarak kademeli ölçeklenme kazanımları elde edildi ve büyümenin önünde kalmak için yeterli hareket alanı korundu. Örneğin, “Figma dosyaları” veya “organizasyonlar” gibi ilişkili tablo grupları kendi dikey partition’larına bölündü.
  • Yatay sharding’e geçiş: Yalnızca dikey bölmenin yeterli olmayacağı fark edildi. CPU kullanımını azaltmaya odaklanan ilk ölçeklenme çalışmalarının ardından, daha büyük ve daha çeşitli bir filoda farklı darboğazlar izlenmeye başlandı. Veritabanı ölçeklenme sınırları; CPU ve IO’dan tablo boyutuna ve yazılan satır sayısına kadar farklı açılardan nicel olarak ölçüldü. Bu sınırları belirlemek, shard başına ne kadar hareket alanı kaldığını öngörmek açısından kritik önemdeydi.
  • Tablo boyutu sınırları: Bazı tablolar birkaç terabayt ve milyarlarca satıra ulaşarak tek bir veritabanının yönetmesini zorlaştıracak boyutlara geldi. Bu boyutlarda, Postgres’in vacuum işlemleri sırasında güvenilirlik etkileniyordu; bu, transaction ID’lerin tükenip sistemi durdurmamasını sağlayan zorunlu bir arka plan işlemidir. En yoğun yazma alan tablolar, yakında Amazon RDS’nin desteklediği maksimum IOPS sınırını aşacaktı. Bu, dikey bölmeyle çözülemeyecek bir problemdi ve veritabanının çökmesini önlemek için daha büyük bir çözüme ihtiyaç vardı.

Ölçek büyütmek için temel oluşturma

  • Geliştirici etkisini en aza indirme: Karmaşık ilişkisel veri modelinin büyük bölümünü altyapı tarafında ele alarak, uygulama geliştiricilerinin kod tabanının büyük kısımlarını yeniden düzenlemek yerine Figma’da ilgi çekici yeni özellikler geliştirmeye odaklanması sağlandı.
  • Şeffaf ölçeklenme: Gelecekte ölçek büyütürken uygulama katmanında ek değişiklik gerekmemesi hedeflendi. Yani, tabloları uyumlu hale getirmek için yapılacak ilk hazırlığın ardından gelecekteki ölçekleme ürün ekipleri için şeffaf şekilde gerçekleşebilecekti.
  • Maliyetli backfill’den kaçınma: Figma’nın büyük tablolarını ya da tüm tablolarını kapsayan bir backfill içeren çözümlerden kaçınıldı. Tabloların boyutu ve Postgres’in throughput sınırları göz önüne alındığında, bu tür backfill işlemleri aylar sürecekti.
  • Kademeli ilerleme: Büyük üretim değişikliklerinin riskini azaltırken kademeli olarak devreye alınabilecek bir yaklaşım belirlendi. Bu sayede büyük kesinti riski düşürüldü ve veritabanı ekibinin migration sırasında Figma’nın güvenilirliğini koruması mümkün oldu.
  • Tek yönlü migration’dan kaçınma: Fiziksel sharding işlemleri tamamlandıktan sonra bile geri dönüş yapabilme yeteneği korundu. Bu, bilinmeyen değişkenler ortaya çıktığında kötü bir durumda sıkışıp kalma riskini azalttı.
  • Güçlü veri tutarlılığını koruma: Downtime olmadan uygulanması zor olan ya da tutarlılığı zedeleyen karmaşık çözümlerden, örneğin double-write’lardan kaçınıldı. İstenen şey, neredeyse sıfır downtime ile ölçeklenebilen bir çözümdü.
  • Güçlü yanlarımızdan yararlanma: Sıkışık teslim tarihleri altında çalışırken, mümkün olduğunca kademeli devreye alınabilecek bir yaklaşım tercih edildi. En hızlı büyüyen tablolar için mevcut uzmanlık ve tekniklerden yararlanılmak istendi.

Olası seçenekleri keşfetme

  • Yatay sharding veritabanı seçeneklerini değerlendirme: Postgres veya MySQL ile uyumlu yatay sharding veritabanıları için çeşitli popüler açık kaynak ve yönetilen çözümler vardı. CockroachDB, TiDB, Spanner ve Vitess değerlendirme sürecinde incelendi. Ancak bu alternatif veritabanlarına geçiş, iki farklı veritabanı deposu arasında tutarlılık ve güvenilirliği sağlamak için karmaşık veri migration’ları gerektirecekti.
  • Mevcut uzmanlıktan yararlanma: Son birkaç yılda RDS Postgres’i kararlı ve verimli şekilde işletme konusunda ciddi bir uzmanlık geliştirildi. Migration sırasında bu alan bilgisinin baştan inşa edilmesi gerekecekti. Son derece agresif büyüme oranı düşünüldüğünde, elde kalan zaman yalnızca birkaç aydı.
  • NoSQL veritabanı seçeneğini eleme: Şirket büyüdükçe sıkça tercih edilen bir diğer ölçeklenebilir çözüm NoSQL veritabanlarıdır. Ancak mevcut Postgres mimarisi üzerinde kurulmuş çok karmaşık bir ilişkisel veri modeli vardı ve NoSQL API’leri bu çeşitliliği sunmuyordu. Mühendislerin neredeyse tüm backend uygulamalarını yeniden yazmak yerine harika özellikler yayınlamaya ve yeni ürünler geliştirmeye odaklanması isteniyordu; bu yüzden NoSQL uygulanabilir bir çözüm değildi.
  • Mevcut RDS Postgres altyapısı üzerinde yatay sharding çözümü kurmayı değerlendirme: Küçük bir ekibin genel amaçlı yatay sharding ilişkisel veritabanını şirket içinde yeniden uygulaması mantıklı değildi. Böyle yapmak, büyük açık kaynak topluluklarının veya uzman veritabanı sağlayıcılarının geliştirdiği araçlarla rekabet etmek anlamına gelecekti. Ancak yatay sharding çözümü Figma’nın özel mimarisine göre özelleştirileceği için çok daha küçük bir özellik seti yeterli olabilirdi. Örneğin, shard’lar arası transaction hatalarını ele alabilecek yöntemleri olduğu için atomik shard’lar arası transaction desteği vermemeye karar verildi. Uygulama katmanında gerekli değişiklikleri en aza indiren bir colocation stratejisi seçildi. Bu sayede ürün mantığının büyük bölümüyle uyumlu bir Postgres alt kümesini desteklemek mümkün oldu. Ayrıca shard edilmiş Postgres ile shard edilmemiş Postgres arasında geriye dönük uyumluluğu korumak kolaydı. Bilinmeyen değişkenlerle karşılaşıldığında shard edilmemiş Postgres’e kolayca geri dönülebiliyordu.

Yatay sharding’e giden yol

  • Yatay sharding’in benimsenmesi: Yatay sharding, tek bir tabloyu ya da tablo grubunu bölerek veriyi birden çok fiziksel veritabanı instance’ına dağıtma sürecidir. Bu süreç sayesinde uygulama katmanında yatay olarak shard edilmiş tablolar, fiziksel katmanda herhangi bir sayıda shard’ı destekleyebilir hale geldi. Fiziksel shard bölme işlemi basitçe yürütülerek her zaman ek ölçekleme yapılabiliyordu; bu işlemler arka planda, minimum downtime ve uygulama seviyesinde değişiklik olmadan şeffaf biçimde gerçekleşiyordu. Bu yetenek sayesinde Figma, veritabanı ölçeklenmesinde kalan darboğazların önüne geçebildi ve son büyük ölçeklenme zorluklarından birini ortadan kaldırdı. Dikey bölme otoyol hızına çıkmayı sağladıysa, yatay sharding hız sınırını kaldırıp uçmayı mümkün kıldı.
  • Yatay sharding’in karmaşıklığı: Yatay sharding, önceki ölçeklenme çalışmalarından bir kademe daha karmaşıktır. Tablolar birden fazla fiziksel veritabanına bölündüğünde, ACID SQL veritabanlarında doğal kabul edilen birçok güvenilirlik ve tutarlılık özelliği kaybedilir. Örneğin bazı SQL sorguları desteklenmesi verimsiz ya da imkânsız hale gelebilir ve uygulama kodunun, sorguları mümkün olduğunca doğru shard’a verimli şekilde yönlendirebilmek için yeterli bilgiyi sağlaması amacıyla güncellenmesi gerekir. Şema değişikliklerinin, tüm shard’ların senkronize kalmasını sağlayacak şekilde koordine edilmesi gerekir; foreign key’ler ve küresel olarak benzersiz index’ler artık Postgres tarafından zorlanamaz. Transaction’lar birden fazla shard’a yayılabildiğinden, Postgres artık transaction’ı tek başına garanti edemez. Böylece bazı veritabanlarına yapılan yazmalar başarılı olurken diğerleri başarısız olabilir. Ürün mantığının bu tür “kısmi commit hataları” karşısında dayanıklı olacak şekilde dikkatle tasarlanması gerekir (örneğin bir ekibi iki organizasyon arasında taşırken verinin yalnızca yarısının eksik kaldığını düşünün!).
  • Yatay sharding’e yönelik çok yıllı çaba: Tam yatay sharding’e ulaşmanın çok yıllı bir çaba olacağı biliniyordu. Projenin riskini mümkün olduğunca azaltırken kademeli değer üretmek gerekiyordu. İlk hedef, üretimde nispeten basit ama çok yüksek trafikli bir tabloyu mümkün olduğunca hızlı shard etmekti. Bu, yalnızca yatay sharding’in uygulanabilirliğini kanıtlamakla kalmayacak, aynı zamanda en yoğun yük altındaki veritabanları için hareket alanını da uzatacaktı. Ardından daha karmaşık tablo grupları shard edilirken ek özellikler geliştirilebilirdi. Mümkün olan en basit özellik seti bile yine de önemli miktarda iş gerektiriyordu. Baştan sona ekip, ilk tabloyu shard etmek için yaklaşık dokuz ay harcadı.

Benzersiz yaklaşımımız

  • Colocation'lar (Colos): İlgili tablo grupları, aynı shard anahtarını ve fiziksel shard düzenini paylaşan colocation'lar (sevgiyle “colo” olarak adlandırılıyor) olarak yatay shard'landı. Bu, geliştiricilere yatay shard'lanmış tablolarla etkileşim kurabilecekleri tanıdık bir soyutlama sağladı.
  • Mantıksal sharding: Uygulama katmanındaki “mantıksal sharding” kavramı ile Postgres katmanındaki “fiziksel sharding” kavramı birbirinden ayrıldı. Daha riskli olan dağıtık fiziksel failover'ı çalıştırmadan önce, daha güvenli ve düşük maliyetli mantıksal sharding dağıtımlarını yapmak için view'lar kullanıldı.
  • DBProxy sorgu motoru: Uygulama katmanında oluşturulan SQL sorgularını yakalayan ve sorguları farklı Postgres veritabanlarına dinamik olarak yönlendiren DBProxy servisi kuruldu. DBProxy, karmaşık yatay sharding sorgularını ayrıştırıp çalıştırabilen bir sorgu motoru içeriyor. DBProxy sayesinde dinamik yük dengeleme ve request hedging gibi özellikler hayata geçirilebildi.
  • Gölge uygulama hazır oluşu: Farklı olası shard anahtarları altında gerçek üretim trafiğinin nasıl davranacağını öngörebilen bir “gölge uygulama hazır oluşu” çerçevesi eklendi. Bu, ürün ekiplerine uygulamayı yatay sharding'e hazırlamak için hangi uygulama mantığının yeniden düzenlenmesi veya kaldırılması gerektiğine dair net bir tablo sundu.
  • Tam mantıksal çoğaltma: Her shard'a yalnızca verinin bir alt kümesini kopyalayan “filtrelenmiş mantıksal çoğaltma”yı uygulamaya gerek kalmadı. Bunun yerine, tüm veri kümesi kopyalandı ve ardından yalnızca ilgili shard'a ait veri alt kümesi üzerinde okuma/yazmaya izin verildi.

Sharding'in uygulanması

  • Shard anahtarı seçiminin önemi: Yatay sharding'deki en önemli kararlardan biri hangi shard anahtarının kullanılacağıdır. Yatay sharding, shard anahtarı etrafında veri modeline çeşitli kısıtlar ekler. Örneğin çoğu sorgunun, isteği doğru shard'a yönlendirebilmek için shard anahtarını içermesi gerekir. Foreign key gibi belirli veritabanı kısıtları ise yalnızca foreign key aynı zamanda sharding anahtarı olduğunda çalışır. Shard anahtarının, güvenilirlik sorunlarına yol açabilecek veya ölçeklenebilirliği etkileyebilecek hotspot'ları önlemek için veriyi tüm shard'lar arasında dengeli biçimde dağıtması gerekir.
  • Figma'nın veri modeline özel yaklaşımı: Figma tarayıcıda çalışır ve birçok kullanıcı aynı Figma dosyası üzerinde eşzamanlı olarak iş birliği yapabilir. Bu da dosya metaverisi, organizasyon metaverisi, yorumlar, dosya sürümleri ve daha fazlasını kapsayan nispeten karmaşık bir ilişkisel veri modeliyle desteklendiği anlamına gelir. Mevcut veri modelinde tek ve iyi bir aday olmadığı için tüm tablolar için aynı sharding anahtarını kullanma seçeneği değerlendirildi; ancak bu, birleşik bir sharding anahtarı eklemek için bileşik anahtarlar oluşturmayı, tüm tablo şemalarına sütun eklemeyi, bunları doldurmak için maliyetli backfill işlemleri yürütmeyi ve ardından ürün mantığını ciddi biçimde yeniden düzenlemeyi gerektirecekti. Bunun yerine Figma, kendi benzersiz veri modeline uygun özel bir yaklaşım benimsedi ve UserID, FileID ve OrgID gibi az sayıda shard anahtarı seçti. Figma'daki tabloların neredeyse tamamı bu anahtarlardan biriyle shard'lanabiliyor.
  • Colocation'ların (Colos) devreye alınması: Ürün geliştiricilerine tanıdık bir soyutlama sunmak için colocation kavramı tanıtıldı. Bir colo içindeki tablolar, tek bir shard anahtarıyla sınırlı olduklarında tablolar arası join'leri ve tam transaction'ları destekler. Uygulama kodunun büyük kısmı zaten veritabanıyla bu şekilde etkileşim kurduğundan, uygulama geliştiricilerinin tabloları yatay sharding'e hazırlamak için yapması gereken değişiklikler en aza indirildi.
  • Veri dağılımının eşitliğini sağlama: Shard anahtarları seçildikten sonra, verinin tüm arka uç veritabanlarına dengeli biçimde dağıtılması gerekiyordu. Ne yazık ki seçilen shard anahtarlarının çoğu auto-increment veya Snowflake zaman damgası önekli ID'ler kullanıyordu. Bu durum, verinin büyük kısmının tek bir shard'da toplanacağı ciddi hotspot'lara yol açabilirdi. Daha rastgeleleştirilmiş ID'lere geçiş seçeneği incelendi, ancak bu hem maliyetli hem de uzun süren veri migrasyonları gerektiriyordu. Bunun yerine yönlendirme için shard anahtarının hash'ini kullanmaya karar verildi. Yeterince rastgele bir hash fonksiyonu seçildiğinde verinin eşit dağılımı garanti edilebiliyor. Bunun bir dezavantajı, shard anahtarı üzerindeki range scan'lerin daha verimsiz hale gelmesi; çünkü ardışık anahtarlar farklı veritabanı shard'larına hash'leniyor. Ancak bu sorgu deseni kod tabanında yaygın olmadığından, kabul edilebilir bir ödünleşim olarak görüldü.

“Mantıksal” çözüm

  • Yatay sharding dağıtımının riskini azaltma: Yatay sharding dağıtımının riskini azaltmak için, shard bölme işleminin fiziksel süreci ile uygulama katmanında tabloları hazırlama sürecini birbirinden ayırmak istediler. Bunun için “mantıksal sharding” ile “fiziksel sharding” ayrıştırıldı. Böylece migrasyonun iki parçası ayrılıp bağımsız şekilde uygulanabildi ve risk azaltıldı. Mantıksal sharding, düşük riskli ve oran bazlı rollout'larla servis katmanına güven oluşturdu. Hata bulunduğunda mantıksal sharding'i geri almak basit bir yapılandırma değişikliğiyle mümkündü. Fiziksel shard işlemlerini geri almak da mümkündü, ancak veri tutarlılığını korumak için daha karmaşık koordinasyon gerektiriyordu.
  • Mantıksal sharding sonrası davranış: Bir tablo mantıksal olarak shard'landıktan sonra, tüm okuma ve yazma işlemleri zaten yatay olarak shard'lanmış gibi çalışır. Güvenilirlik, gecikme ve tutarlılık açısından sistem yatay shard'lanmış gibi görünür, ancak veri hâlâ fiziksel olarak tek bir veritabanı sunucusunda bulunur. Mantıksal sharding'in beklendiği gibi çalıştığına güven oluştuğunda ise fiziksel sharding işlemleri gerçekleştirilir. Bu süreç, verinin tek bir veritabanından kopyalanıp birden fazla arka uca shard'lanmasını ve ardından okuma/yazma trafiğinin yeni veritabanları üzerinden yeniden yönlendirilmesini içerir.

Yapabilen bir sorgu motoru

  • Yatay sharding desteği için arka uç yığınının yeniden tasarlanması: Başlangıçta uygulama servisleri doğrudan bağlantı havuzlama katmanı olan PGBouncer ile iletişim kuruyordu. Ancak yatay sharding çok daha karmaşık sorgu ayrıştırma, planlama ve yürütme gerektiriyordu. Bunu desteklemek için DBProxy adlı yeni bir golang servisi inşa edildi. DBProxy, uygulama katmanı ile PGBouncer arasında konumlanıyor. İçinde yük dengeleme, gelişmiş gözlemlenebilirlik, transaction desteği, veritabanı topolojisi yönetimi ve hafif bir sorgu motoru yer alıyor.
  • Sorgu motorunun temel bileşenleri:
    • Sorgu ayrıştırıcı: Uygulamadan gönderilen SQL'i okur ve bunu soyut sözdizimi ağacına (AST) dönüştürür.
    • Mantıksal planlayıcı: AST'yi ayrıştırır ve sorgu planından sorgu türünü (insert, update vb.) ve mantıksal shard kimliğini çıkarır.
    • Fiziksel planlayıcı: Sorguyu mantıksal shard kimliğinden fiziksel veritabanına eşler. Sorguyu uygun fiziksel shard üzerinde çalışacak şekilde yeniden yazar.
  • “Scatter-gather” yaklaşımı: Veritabanı genelinde bir saklambaç oyunu gibi çalışır: sorgu tüm shard'lara gönderilir (dağıtma) ve her birinden yanıtlar toplanır (toplama). Eğlenceli görünse de, karmaşık sorgularla aşırı kullanıldığında veritabanını salyangoz gibi yavaşlatabilir.
  • Yatay shard'lanmış dünyada sorgu uygulaması: Tek shard sorguları, tek bir shard anahtarıyla filtrelenir. Sorgu motorunun yapması gereken yalnızca shard anahtarını çıkarmak ve sorguyu uygun fiziksel veritabanına yönlendirmektir. Yürütme karmaşıklığı Postgres'e “aktarılır”. Ancak sorguda sharding anahtarı yoksa, sorgu motorunun daha karmaşık bir “scatter-gather” işlemi yapması gerekir. Bu durumda sorgu tüm shard'lara fan-out edilir (dağıtma aşaması) ve ardından sonuçlar bir araya getirilir (toplama aşaması).
  • SQL uyumluluğunun sadeleştirilmesi: DBProxy servisi tam SQL uyumluluğunu destekleseydi, Postgres veritabanı sorgu motoruna çok benzer görünürdü. Amaç, API'yi basitleştirerek DBProxy'nin karmaşıklığını en aza indirmek ve desteklenmeyen sorguları yeniden yazmak zorunda kalan uygulama geliştiricilerinin iş yükünü azaltmaktı. Uygun alt kümeyi belirlemek için, tabloların olası sharding şemalarını tanımlayabilen ve mantıksal planlama aşamasını gerçek zamanlı üretim trafiği üzerinde çalıştırabilen bir “gölge planlama” çerçevesi kuruldu. Sorgular ve bunlara karşılık gelen sorgu planları Snowflake veritabanına log'lanarak çevrimdışı analiz yapılabildi. Bu verilerden hareketle, sorgu motorunun en kötü durum karmaşıklığından kaçınırken en yaygın sorguların %90'ını destekleyen bir sorgu dili alt kümesi seçildi. Örneğin tüm range scan ve point query'lere izin verilirken, join'lere yalnızca aynı colo içindeki iki tablo arasında ve shard anahtarı üzerinden yapıldığında izin verildi.

Geleceğe bakış

  • Mantıksal shard'ların kapsüllenmesi: Mantıksal shard'ların nasıl kapsülleneceğine karar vermeleri gerekiyordu. Veriyi ayırmak için ayrı Postgres veritabanları veya Postgres şemaları kullanmayı değerlendirdiler. Ne yazık ki bu yaklaşım, mantıksal olarak shard'lama yapılırken fiziksel veri değişiklikleri gerektiriyordu ve bu da fiziksel shard bölme kadar karmaşıktı.
  • Shard'ların Postgres view'larıyla temsil edilmesi: Bunun yerine, shard'ları Postgres view'ları olarak temsil etmeye karar verdiler. Her tablo için birden fazla view oluşturulabiliyor ve her biri belirli bir shard'ın veri alt kümesine karşılık geliyor. Bu şu biçimdeydi: CREATE VIEW table_shard1 AS SELECT * FROM table WHERE hash(shard_key) >= min_shard_range AND hash(shard_key) < max_shard_range). Tüm okuma ve yazma işlemleri bu view'lar üzerinden yapıldı.
  • Mevcut shard'lanmamış fiziksel veritabanı üzerinde shard'lanmış view'lar oluşturulması: Riskli fiziksel reshard işlemleri yapılmadan önce mantıksal shard'lama gerçekleştirilebildi. Her view'a kendi shard'lanmış connection pooler servisi üzerinden erişildi. Connection pooler, hâlâ shard'lanmamış fiziksel instance'ı işaret ederek sistemi shard'lanmış gibi gösteriyordu. Sorgu motorundaki feature flag'ler sayesinde shard'lanmış okuma ve yazmalar kademeli ve düşük riskli şekilde devreye alındı; trafik tekrar ana tablolara yönlendirilerek her an birkaç saniye içinde geri alınabiliyordu. İlk reshard çalıştırılana kadar ekip, shard'lanmış topolojinin güvenliği konusunda güven kazanmış oldu.
  • View'lara bağımlı olmanın riski: View'lar performans yükü ekler ve bazı durumlarda Postgres query planner'ın sorguları optimize etme biçimini kökten değiştirebilir. Bu yaklaşımı doğrulamak için üretim sorgularının sterilize edilmiş bir query corpus'unu topladılar ve view kullanılan ve kullanılmayan durumlarda yük testi yaptılar. Çoğu durumda view'ların yalnızca minimal performans yükü eklediğini, en kötü durumda bile bunun %10'un altında kaldığını doğruladılar. Ayrıca tüm gerçek zamanlı okuma trafiğini view'lar üzerinden geçirip, view'lı ve view'suz sorguların performansını ve doğruluğunu karşılaştıran bir shadow read framework'ü kurdular. Sonuç olarak, view'ların minimum performans etkisiyle uygulanabilir bir çözüm olduğunu teyit ettiler.

Topoloji sorununu çözme

  • Sorgu yönlendirme için DBProxy'nin topolojiyi anlaması: Tablolar ile fiziksel veritabanlarının topolojisini anlamak gerekiyordu. Mantıksal ve fiziksel shard'lama kavramlarının ayrılması nedeniyle, bu soyutlamaları topoloji içinde ifade etmenin bir yoluna ihtiyaç vardı.
  • Tablo ve shard key eşlemesi: users tablosunu user_id shard key'iyle eşlemenin ve mantıksal shard ID'si (123) için uygun mantıksal ve fiziksel veritabanını belirlemenin bir yoluna ihtiyaç vardı.
  • Dikey partitioning ve hardcode edilmiş yapılandırma dosyalarına bağımlılık: Dikey partitioning'de tabloları ilgili partition'a eşleyen basit, hardcode edilmiş yapılandırma dosyalarına güveniliyordu. Yatay shard'lamaya geçişte ise daha karmaşık bir sistem gerekiyordu.
  • Topolojinin dinamik olarak değişmesi ve DBProxy'nin durumunu hızla güncelleme gereksinimi: Shard bölme sırasında topoloji dinamik olarak değişiyor, bu yüzden isteklerin yanlış veritabanına yönlendirilmesini önlemek için DBProxy'nin durumunu hızla güncellemesi gerekiyordu.
  • Topoloji değişikliklerinin geriye dönük uyumluluğu: Tüm topoloji değişiklikleri geriye dönük uyumlu olmalıydı ve sitenin kritik yolunda herhangi bir kesintiye yol açmamalıydı.
  • Karmaşık yatay shard'lama metadata'sını kapsülleyen veritabanı topolojisinin kurulması: Karmaşık yatay shard'lama metadata'sını kapsülleyen ve 1 saniyenin altında gerçek zamanlı güncellemeler sağlayan bir veritabanı topolojisi kuruldu.
  • Mantıksal ve fiziksel topolojinin ayrılmasıyla veritabanı yönetiminin sadeleştirilmesi: Üretim dışı ortamlarda, üretimle aynı mantıksal topoloji korunurken fiziksel veritabanı sayısı azaltılarak maliyet ve karmaşıklık düşürüldü.
  • Topoloji kütüphanesiyle topoloji içindeki değişmezlerin zorlanması: Her shard ID'sinin tam olarak bir fiziksel veritabanına eşlenmesi gibi topoloji değişmezlerinin zorlanması, yatay shard'lama inşa edilirken sistemin doğruluğunu korumaya yardımcı oldu.

Fiziksel shard'lama işlemi

  • Tablolar shard'lamaya hazır olduktan sonraki son adım: Shard'lanmamış veritabanından shard'lanmış veritabanına fiziksel failover yapılmasıydı. Yatay shard'lama için aynı mantığın büyük kısmı yeniden kullanılabildi, ancak 1:1 veritabanı modelinden 1:N yapısına geçiş gibi dikkat çekici bazı farklar vardı.
  • Failover sürecinin daha dayanıklı hâle getirilmesi gereği: Shard'lama işleminin veritabanının yalnızca bir bölümünde başarılı olabildiği yeni hata modlarına karşı, failover sürecinin daha dayanıklı hâle getirilmesi gerekiyordu.
  • Dikey partitioning sırasında risklerin büyük kısmının zaten ele alınmış olması: Risklerin çoğu dikey partitioning sırasında zaten azaltıldığı için, ilk fiziksel shard'lama işlemine normalde mümkün olacağından çok daha hızlı geçebildiler.

Yatay shard'lama yolculuğunda gelinen nokta

  • Yatay shard'lama için çok yıllı yatırım: Figma, gelecekteki ölçeklenebilirliği için yatay shard'lamaya çok yıllı yatırım gerektiğini fark etti ve ilk yatay shard'lanmış tabloyu Eylül 2023'te devreye aldı.
  • Başarılı failover uygulaması: Veritabanı primary'sinde 10 saniyelik geçici kısmi erişilebilirlik ve replica'larda hiç erişilebilirlik etkisi olmadan başarılı bir failover gerçekleştirildi. Shard'lama sonrasında gecikme veya erişilebilirlikte gerileme yaşanmadı.
  • Karmaşık shard'ların ele alınması: En yüksek yazma oranına sahip veritabanında nispeten basit shard'lar işlendi. Bu yıl ise onlarca tablo ve binlerce kod çağrı noktasına sahip giderek daha karmaşık veritabanılarının shard'lanması planlanıyor.
  • Figma'daki tüm tablolar için yatay shard'lama gereksinimi: Son ölçekleme sınırlarını kaldırmak ve gerçek anlamda olağanüstü durumlara dayanıklılık sağlamak için bu gerekli görülüyor. Tamamen yatay shard'lanmış bir dünya; daha yüksek güvenilirlik, maliyet tasarrufu ve artan geliştirici hızı gibi çeşitli avantajlar sunuyor.
  • Çözülmesi gereken problemler:
    • Yatay shard'lanmış şema güncellemelerinin desteklenmesi
    • Yatay shard'lanmış primary key'ler için küresel olarak benzersiz ID üretimi
    • İş açısından kritik kullanım senaryoları için atomik shard'lar arası transaction'lar
    • Dağıtık, küresel olarak benzersiz indeksler (şu anda yalnızca shard key içeren indekslerde destekleniyor)
    • Yatay shard'lamayla sorunsuz uyumlu ORM modelleriyle geliştirici hızının artırılması
    • Tek tıklamayla shard bölme çalıştırabilen tam otomatik reshard işlemleri
  • Mevcut RDS yatay shard'lama yaklaşımının yeniden değerlendirilmesi: Bu yolculuk 18 ay önce çok sıkışık bir takvim baskısı altında başladı. NewSQL store'ların sürekli gelişmesi ve olgunlaşmasıyla birlikte, mevcut yolda kalmanın mı yoksa açık kaynak ya da yönetilen bir çözüme geçmenin mi daha doğru olduğuna dair trade-off'ları yeniden değerlendirecek kadar zaman kazanılmış durumda.
  • Yatay shard'lama yolculuğundaki heyecan verici ilerleme: Çözülmesi gereken zorluklar hâlâ yolun başında olsa da, kayda değer ilerleme sağlandı. Ekip, yatay shard'lama yığınının çeşitli bölümlerine dair daha fazla derinlemesine analiz paylaşmayı bekliyor. Bu tür projilerle ilgileniyorsanız, iletişime geçmenizi istiyorlar. İşe alım yapıyorlar.

GN⁺ yorumu

  • Figma'nın veritabanı ekibi, yatay shard'lama yoluyla veritabanı ölçeklenebilirliğinin sınırlarını aşmayı hedefledi; bu, bulut tabanlı iş birliği araçlarının büyümesi ve performansını koruması açısından önemli bir adımdı.
  • Yatay shard'lama, veri yönetimi ve sorgu optimizasyonunda yeni zorluklar ortaya çıkarıyor; bu da veritabanı yöneticileri ve geliştiriciler için yeni bilgi ve beceriler gerektiriyor.
  • Yatay shard'lama, veritabanı ölçeklenebilirliğini büyük ölçüde artırsa da, karmaşık sorgu işleme ve veri tutarlılığını koruma konusunda yeni çözümler gerektiriyor.
  • Benzer işlevler sunan açık kaynak projeler arasında, Postgres veritabanlarını yatay olarak ölçeklendirme yetenekleri sağlayan CitusDB bulunuyor.
  • Yatay shard'lama teknolojisini benimserken veri modelinin karmaşıklığı, sorgu performansı, sistem esnekliği ve bakım boyutları dikkate alınmalı; bu da veritabanı ölçeklenebilirliği ile yönetim kolaylığı arasında denge kurmak anlamına geliyor.

1 yorum

 
GN⁺ 2024-03-15
Hacker News yorumu
  • Büyük tablolar ve RDS IOPS sınırı

    • En büyük tablonun birkaç TB boyutunda olduğu ve yakında RDS'nin desteklediği azami IOPS'u aşacağının belirtildiği söyleniyor.
    • PostgreSQL için RDS, 64TB hacimde en fazla 256.000 IOPS'a ulaşıyor.
    • Çoklu AZ yapılandırmasında bu, aylık 70 bin dolarlık bir maliyet yaratıyor.
  • Sharding sonuçları ve maliyet

    • Sonuçta her shard'ın yaklaşık 50.000 IOPS ve 12TB veri desteklediği 5 yönlü bir shard yapısı varsayılıyor.
    • Çoklu AZ yapılandırmasında bu, aylık 100 bin dolarlık bir maliyet yaratıyor.
  • Sharding için harcanan zaman ve maliyet

    • İlk tabloyu shard etmek 9 ay sürdü.
    • Uygulama değişiklikleri de gerektiğinden, 9 ay * ayda 20 iş günü * (3 DB mühendisi + 2 uygulama mühendisi) = 900 iş günü olarak hesaplanıyor.
    • Mühendislerin ortalama yıllık maaşının 100 bin dolar olduğu varsayılırsa, toplam maliyet yaklaşık 400 bin dolar.
  • YugabyteDB ile karşılaştırılan maliyet

    • PostgreSQL uyumlu bir NewSQL olan YugabyteDB'nin, RDS'nin en yüksek performansına ulaşmak için aylık 15 bin dolar maliyet çıkaracağı tahmin ediliyor.
    • Figma, şirket içinde yatay sharding'i uygulamak için yaklaşık 25 kat (400 bin dolar / 15 bin dolar) maliyet harcadı ve hâlâ RDS kullanıyor; bu da yaklaşık 6 katlık (100 bin dolar / 15 bin dolar) bir maliyet anlamına geliyor.
  • Müşteri bazında veritabanı ayırma önerisi

    • Her müşteriyi ayrı bir (mantıksal) veritabanına koymanın daha kolay olabileceği öneriliyor.
    • Farklı müşteriler arasında işlem gerekmediği için, gerçekte olandan daha zor bir problemi çözüyor gibi göründükleri belirtiliyor.
    • PostgreSQL'in (mantıksal) veritabanlarının iyi ölçeklenip ölçeklenmeyeceği belirsiz, ancak ilke olarak imkânsız değil.
  • MySQL'in Vitess'ine benzer bir PG sürümü oluşturmak

    • Sorgu yeniden yazımı ilgi çekici bulunuyor.
    • DB ile uygulama arasına bir katman koyulursa, çeşitli ACL'ler (erişim kontrol listeleri) de mümkün olabilir.
  • FoundationDB'nin değerlendirilmesi

    • Neden FoundationDB'nin denenmediği merak ediliyor.
    • PostgreSQL'in vacuuming (çöp toplama) konusunda sorunlar yaşadığı belirtiliyor.
    • Önceki sürümlerde vacuuming için iki kat alan gerekiyordu, ancak son sürümlerde bunun değişmiş olabileceği söyleniyor.
  • Sharding'e bir hack gibi yaklaşım

    • Düşük seviyeli I/O buffering/caching'i doğrudan yönetmek yerine OS API'lerine güvenmenin daha iyi olduğu ifade ediliyor.
    • DB sharding için benzer tekniklerin/altyapının hâlâ yetersiz olduğu görüşü dile getiriliyor.
  • Citus eklentisinin kullanılmamasına dair soru

    • Zaten olgun bir Postgres eklentisi olan Citus'un makalede anılmadığı belirtiliyor.
    • Citus'u bilmiyor olabilecekleri ya da belirli bir nedenle göz ardı etmiş olabilecekleri söyleniyor.
  • Aurora Limitless kullanma olasılığı

    • Amazon Aurora Limitless'ın kullanılıp kullanılamayacağı soruluyor.
  • NoSQL veritabanlarına dair anlayış

    • NoSQL'in, karmaşık ilişkisel modellere ihtiyaç duymayan yapılandırılmamış verileri barındıran backend'ler için uygun olduğu ifade ediliyor.
    • Postgres bunu jsonb veri tipiyle destekliyor, ancak zaten iyi bir veri modeline sahip oldukları için buna çok ihtiyaç duyulmadığı belirtiliyor.
  • Sharding'in olgunluğu ve NewSQL çözümlerini değerlendirme

    • Sharding daha olgun hâle gelmişken, otomatik sharding ve çok bölgeli destek için NewSQL çözümlerini değerlendirmenin değerli olup olmadığı soruluyor.
    • NewSQL veritabanlarını nasıl işleteceğini öğrenmenin de ek bir maliyet olduğu belirtiliyor.
  • Google'ın Spanner teknolojisi ve Figma'nın değerlendirmesi

    • Google'da Spanner'ın sonsuz yatay sharding ve transaction desteği sunan sihirli bir teknoloji gibi görüldüğü, neredeyse tüm projelerin Spanner'a taşındığı belirtiliyor.
    • Figma'nın Cloud Spanner'ı nasıl değerlendirdiği ve kendi yatay Postgres şemasında gerçekten transaction desteğinden vazgeçip vazgeçmediğiyle ilgili (en azından geçici olarak) merak dile getiriliyor.