1 milyarı aşkın ChatGPT kullanıcısı için çevrimiçi depolamayı hızla ölçeklendirmek (Bölüm II)
Benzeri görülmemiş büyümeyi yönetmek için uygulama depolama platformumuz Habitat'ta Azure Cosmos DB'yi nasıl optimize ettik?
Tüm OpenAI ürünleri, verilere hızlı ve güvenilir erişim gerektiriyor. Bunu depolama platformumuz Habitat sağlıyor. Habitat'ın, 40 coğrafi bölgedeki 1 milyarı aşkın kullanıcıya milisaniyeler içinde yanıt vermesi gerekiyor. Altyapımız olağanüstü bir zorlukla karşı karşıyaydı: hızla artan büyümeyi ve yeni kullanım senaryolarını desteklerken güvenilirliği, performansı ve ürün geliştiricilerinin hızını artırmaya devam etmek. Bu zorluğu aşmak için çevrimiçi depolama platformumuzun tasarımını ve işletimini yeniden düşünmemiz gerekti. Seçenekler arasındaki ödünleşimleri sürekli değerlendirdik ve şu sırayı izledik: önce kritik ürün trafiği için yeterince güvenilir olmak, sonra dünya genelindeki kullanıcılar için yeterince hızlanmak ve son olarak devasa ölçekte etkin biçimde çalışmak.
Bu iki bölümlük seri, Habitat'ı basit bir istemci kütüphanesi ve veritabanından, 500 petabaytı aşkın veriyi sunan küresel dağıtık bir depolama platformuna nasıl dönüştürdüğümüzü anlatıyor. Bölüm I, Habitat'ın bir Python istemcisinden hizmete dönüşmesine odaklanıyordu. Ayrıca, Python tabanlı bir hizmeti birçok kişinin pratikte mümkün gördüğünün çok ötesine taşımamızı sağlayan teknikleri ele alıyordu.
Serinin ikinci bölümü olan bu yazıda, altyapıdaki depolama bileşeni Azure Cosmos DB'yi nasıl ölçeklendirdiğimizi anlatıyoruz. Azure ekibiyle yakın iş birliği sayesinde, birlikte yönetilen kapsayıcılara dayalı, uygulanabilir bir çok kiracılı mimariye ulaştık. Bu yaklaşım, devasa küresel ölçekte mükemmel okuma performansı sağlıyor.
Şekil 01 · Habitat nedir?
Çevrimiçi depolama platformu
Habitat, OpenAI ürünlerinin ihtiyaç duyduğu bilgilere hızla ve güvenilir biçimde erişebilmesi için geliştirdiğimiz çevrimiçi depolama platformudur.
- İstek
- Yanıt
- Değişiklikler (CDC)
Şirketler büyüdükçe altyapı ekipleri genellikle tek kiracılı sistemlerden çok kiracılı sistemlere geçiyor. Her ürün alanından sorumlu ekibin kendi sistemini yönettiği tek kiracılı mimari, arızaların etki alanını daraltıyor; net sorumluluk sınırları ve iş yükü yalıtımı sağlıyor. Ekipler ve ürün alanları çoğaldıkça bu yapıyı işletmek pahalılaşıyor. Tek kiracılı mimari, her ürün ekibini kapasite planlamasından sorumlu tutuyor ve çoğu zaman gereğinden çok fazla kaynak ayrılmasına yol açıyor.
Çok kiracılı mimari ise kontrolü, kaynak tahsisinde daha bilgili ve deneyimli merkezi bir veritabanı ekibine veriyor. Ancak çok kiracılı mimari de kendi sorunlarını yaratıyor. Örneğin gürültülü komşu sorununda bir kiracı, kaynakların olağandışı derecede büyük bir kısmını tüketerek diğer kiracıları olumsuz etkiliyor.
Habitat'ta büyük ölçekte güvenilir ve verimli bir depolama sistemi tasarlamak için tüm bu ödünleşimleri tartmamız gerekti. Bugün Habitat, birçok OpenAI ürünü için çok kiracılı bir veritabanı katmanı. Ancak yolculuğumuzda başladığımız noktaya geri döndük: önce tek bir çok kiracılı Azure Cosmos DB kapsayıcısı kullandık, ardından altyapıda tek kiracılı kapsayıcılar ayırdık ve sonunda varsayılan olarak yeniden çok kiracılı kapsayıcıya geçtik. Habitat'taki çok kiracılı mimari yolculuğumuzun henüz başındayız. Çok çeşitli kullanım senaryolarını destekliyoruz; ancak mümkün olduğunca Azure Cosmos DB'nin yerleşik temel yapı taşlarından yararlanarak bu alandaki yatırımı erteleyebildik.
Azure Cosmos DB yolculuğumuza geçmeden önce bazı temel bilgiler:
Bir Azure Cosmos DB hesabı, bir kapsayıcı kümesi ve çoğaltma ilkesi tanımlar
Her kapsayıcıya, saniyede istek birimi (RU/s) cinsinden belirli bir işlem kapasitesi ayrılır
Her kapsayıcıdaki veriler, belirtilen mantıksal bölüm anahtarına göre parçalanarak saklanır; mantıksal bölüm anahtarı başına depolama ve işlem kapasitesi sınırları belgelenmiştir
Azure Cosmos DB, mantıksal bölüm anahtarlarını altyapıdaki daha az sayıdaki fiziksel bölüme dağıtır. Depolama bir eşiği aştığında veya ayrılan işlem kapasitesini karşılamak için kapsayıcı daha fazla fiziksel bölüme ihtiyaç duyduğunda, bu bölümleri birden fazla fiziksel bölüme ayırır
Başlangıçta tüm istemci yükünü kabul ediyor, geri basınç sağlamak için mantıksal bölüm anahtarı başına belirtilen 10 bin RU/s sınırına güveniyorduk. İlk başladığımızda her hesapta yalnızca bir varsayılan Azure Cosmos DB kapsayıcısı kullanıyorduk. Bu yeterince iyi çalışıyordu, ancak birkaç nedenle sorunlu olduğu ortaya çıktı:
İlk API tercihlerimiz nedeniyle, mantıksal bölüm anahtarı seçimini doğrudan istemcilere bırakmıştık. Sonuç olarak, farklı ürün kullanım senaryolarında user_id veya workspace_id gibi sık kullanılan bölüm anahtarlarında sık sık çakışmalar yaşıyoruz. Bu kullanım senaryoları aynı mantıksal bölüm anahtarlarında Azure Cosmos DB sınırlarını paylaştığından, bu tasarım belirli bir kullanıcının toplam işlem kapasitesini kısıtlıyordu.
Habitat ve Azure Cosmos DB'ye geçmeden önce Postgres'i ölçeklendirirken sık karşılaştığımız bir sorun şuydu: orantısız derecede yüksek yük oluşturan tek bir kiracıya ait, çok yoğun kullanılan bir organizasyon veya anahtardan gelen çok sayıda istek, tüm veritabanını devre dışı bırakabiliyordu. Bu anahtarları önbelleğe almak ve önbellekte bulunamayan veriler için süreli kilitler eklemek üzere ekipçe ciddi emek harcadık. Böylece önbellek kaçırmalarının oluşturduğu yükün alttaki veritabanını aşırı yüklemesini önledik.
Figure 02a · Logical partition key limits
Different clients, the same partition key
Belgelenen veri boyutu ve işlem kapasitesi sınırları mantıksal bölüm anahtarları için geçerli olsa da sınırlar aslında fiziksel bölümde uygulanıyor. Pratikte bu, mantıksal bölümlerin 10.000 RU/s düzeyine ulaşamadığı anlamına geliyor. Bunun yerine, fiziksel bölümün sınırlarını aynı fiziksel bölümde bulunan diğer tüm mantıksal bölüm anahtarlarıyla paylaşıyorlar.
Bu durum, gürültülü komşuların birbiriyle ilgisiz birçok mantıksal bölüm anahtarını etkilemesine yol açıyordu. Niş ürün özelliklerinin verileri üzerinde çalışan iş yükleri, temel oturum açma ve kayıt akışlarını aksatabiliyordu.
Figure 02b · Noisy neighbors
Different users, the same physical partition
Bir fiziksel bölümün işlem kapasitesi sınırı da Azure Cosmos DB kapsayıcısına atanan toplam işlem kapasitesine göre değişiyor. Kapsayıcıya ayrılan işlem kapasitesi, kapsayıcının fiziksel bölümleri arasında yaklaşık olarak eşit dağıtılıyor.
Veri hacmi büyüdükçe fiziksel bölümler bölünüyor ve toplam bölüm sayısı artıyor; ancak ayrılan toplam işlem kapasitesi değişmiyor. Sonuçta veri boyutu büyüdükçe bölüm başına fiilî işlem kapasitesi sınırı azalıyor.
Depolama ihtiyacı en yüksek, blob benzeri kullanım senaryolarımızda bu bir arıza durumuna yol açıyor: istek hızları ve kullanım sabit kalsa bile yalnızca depolama hacminin büyümesi, etkin iş yüklerinin işlem kapasitesini azaltıyor.
Figure 02C · Weak partitions
The limit falls below demand
A partition splits when it reaches its storage limit. Each child receives half the throughput capacity.
Ayrı kapsayıcılar, bu bölüm anahtarı sınırlarını ve gürültülü komşu sorunlarını kısmen çözmeye yardımcı oluyor. Ayrı kapsayıcılar kullanıldığında her birine bağımsız fiziksel bölümler atanabiliyor. Böylece yalnızca aynı kapsayıcıdaki farklı iş yükleri gürültülü komşu olabiliyor veya bölüm anahtarı uzayında çakışabiliyor. Öte yandan, yeni kapsayıcılar oluşturmanın da bir yükü var: her kapsayıcı için ayrı kapasite planlaması gerekiyor. Bu yüzden kapsayıcıları yalnızca anlamlı hizmet veya kullanım senaryosu sınırlarında oluşturmak istiyoruz.
Güçlü yalıtım gerektiren en kritik yeni kullanım senaryolarında ayrı Azure Cosmos DB kapsayıcıları kullanmaya başladık. Buna, her kapsayıcıya ayrılan toplam işlem kapasitesini fiziksel bölüm sayısıyla uyumlu tutarak zayıf bölümleri yöneten bir betik de ekledik. Böylece karşılaştığımız sorunların neredeyse tamamını önledik.
Ancak başlangıçta varsayılan bir kapsayıcı kullandığımız için, eski kritik kullanım senaryolarının birçoğu maalesef veri taşıması yapılmadan oradan ayrılamıyordu. Hâlâ paylaşılan varsayılan kapsayıcıdaki verilere bağımlı olan kritik hizmetleri korumak için ekiplere sık sık yeni hizmetler veya büyük ürün özellikleri için ayrı kapsayıcılar oluşturmalarını öneriyorduk. Ölçeğimiz büyüdükçe varsayılan kapsayıcı üzerindeki baskı ve üretim ortamındaki olaylar arttı. Sırf varsayılan kapsayıcıyı ek yükten korumak için her yeni hizmete veya büyük ürün özelliğine kapsayıcı ayırmaya başladık.
Bu yaklaşım, bizi site genelindeki birçok kesintiden kurtardı; sorunların etkisini özellik veya hizmet düzeyindeki aksaklıklarla sınırladı. Ancak yeni kapsayıcılar oluşturmanın getirdiği yük sonunda bizi zorlamaya başladı:
Eski paylaşılan varsayılan kapsayıcıda, yeni bir kullanım senaryosunun 0 QPS'den 1 milyon QPS'ye çıkması toplam kullanımı pek değiştirmiyordu. Ancak yalıtılmış bir kapsayıcıda yeni bir kullanım senaryosunun 0'dan 1 milyon QPS'ye çıkması, yalnızca şirket içi denemelerden kaynaklanan başlangıç yükünün 1.000 katına ulaşması anlamına gelebiliyordu.
Özel kapsayıcılarla birlikte ekiplerin, kullanıma sunma sırasında beklenen işlem kapasitesini önceden ayırmayı unutmaması gerekiyordu. Ürün ekipleri çoğu zaman özelliklerini üretime alırken önceden ölçeklendirmeyi unutuyordu. Biz de kullanıma sunma gününde ciddi olay müdahale odalarında kapsayıcıları son anda büyütmeye çalışıyorduk.
Çok kiracılı sistemlerde farklı iş yüklerini bir arada çalıştırmanın temel avantajlarından birini, bu kapsayıcı stratejisinde daha iyi yalıtım uğruna kaybediyorduk.
Figure 03 · Lack of stable aggregate growth
The same workload, different headroom
1K RU/s during load testing → 1M RU/s at launch
Zamanla, özel kapsayıcıların kullanımını izlemek de trafiğin ne zaman değişeceği veya artacağı konusunda derin ürün bilgisi gerektirmeye başladı.
Büyüme eğilimlerine göre her kapsayıcıya ayrılan işlem kapasitesini artıran basit bir kontrol düzlemi betiği sağlayabiliyoruz. Ancak toplam kullanımda istikrarlı büyüme olmayınca, doğru ölçeklendirme için OpenAI'daki neredeyse tüm ürün ekiplerinin kapasite planlamasına katılması gerekiyordu.
Her hizmetten sorumlu ekibin Azure Cosmos DB kaynak tahsisine gösterdiği özen büyük ölçüde değiştiğinden, bu yaklaşım organizasyon büyüdükçe işlemez hâle geldi.
Organizasyon büyüdükçe bu operasyonel sorunları yönetmek zorlaştı. Planlamayı yapan tek bir merkezi ekip olmayınca birçok ekip yetersiz planlama yaptı. Sonuç olarak yeniden çok kiracılı bir çözüme yöneldik. İlk çok kiracılı mimarimizdeki sorunları ortak kullanıma dayalı bir tasarımla çözmek için Azure ekibiyle yakın çalıştık:
Önce en yoğun kullanılan anahtarları sınırlamak, gürültülü komşuların bir fiziksel bölümün tüm işlem kapasitesini tüketmesini önlüyor. Böylece tek bir yoğun anahtarın site genelini etkileyebildiği gürültülü komşu etkisi azalıyor.
İstekleri katmanlara ayıran QoS de benzer şekilde, toplu veri ekleme veya dışa aktarma gibi çevrimdışı iş yüklerinin bir fiziksel bölümün tüm işlem kapasitesini kullanmasını önlüyor. Bu iş yüklerinin isteklerine düşük öncelik atanınca önce onlar sınırlandırılıyor. Böylece son kullanıcılara hizmet veren daha yüksek öncelikli etkileşimli isteklerin sınırlandırılması önleniyor.
Azure Cosmos DB'de, ayrılmış kapasite modunda yaşadığımız zayıf bölüm sorununu çözebilecek bir sunucusuz mod zaten vardı. Ancak önemli bir dezavantajı vardı: yalnızca depolama kullanımına göre ölçekleniyor ve fiziksel bölüm başına RU kullanımını 5 bin RU/s ile sınırlıyordu. Bu, zayıf bölüm sorununu çözecek ama yoğun RU kullanan senaryoları ölçeklendirmemizi engelleyecekti.
Azure Cosmos DB ekibinin bizim için geliştirdiği yeni sunucusuz mod, her fiziksel bölümün 10 bin RU/s'ye kadar ölçeklenmesini sağladı. Depolama kullanımına dayalı bölünmelere ek olarak RU kullanımına dayalı bölünmeler de getirildi. Böylece kapsayıcıları elle izleyip büyütmemize gerek kalmadı.
Bu değişikliklerle yeniden tek bir paylaşılan kapsayıcı kullanmaya geçebildik. İş yükleri arasındaki yalıtım korunurken, ürün ekiplerinin başlangıçta ve sonrasında kapasite planlama yükü önemli ölçüde hafifledi. O zamandan bu yana geçen aylarda, ürün geliştirme hızlanmasına rağmen kaynak tahsisi veya gürültülü komşu kaynaklı hiçbir olay yaşamadık.
Şirketler OpenAI'ın ölçeğine ulaştığında, yönetilen hizmetler daha az “yönetilen” hâle geliyor. Birçok iş yükü, bulut sağlayıcısının altyapısındaki alışılmış sınırların dışına çıkıyor. OpenAI, Azure Cosmos DB'nin en büyük kullanıcılarından biri hâline gelince sistemi başarıyla işletmek için farklı bir yaklaşım gerekti: ortak testler, ortak panolar, doğrudan mühendislik iletişim kanalları ve yalnızca bizim ölçeğimizde ortaya çıkan arıza durumlarına ilişkin ortak sorumluluk. Bugün en büyük Azure Cosmos DB hesabımız onlarca petabayt veri depoluyor ve 20 milyon QPS'nin üzerinde hizmet veriyor. Bildiğimiz kadarıyla Azure Cosmos DB'yi bu ölçekte kullanan tek şirketiz.
2024'ün sonlarında yaşanan bölgesel bir kesinti, bu iş birliğinin neden gerekli olduğunu açıkça gösterdi. O sırada en büyük Azure Cosmos DB hesaplarımızdan birinin birincil Azure bölgesinde elektrik kesintisi yaşandı. Ardından yürütülen yük devretme sürecinde, en büyük hesaplarımızın ikincil bölgeye geçmesinin birkaç saat süreceğini fark ettik. Bunu ne bizim ekibimiz ne de Azure Cosmos DB ekibi bizim ölçeğimizde test etmişti.
Yaklaşık bir ay sonra bu hesapları ilk bölgeye geri taşırken başka bir ciddi kesintiyi tetikledik. İlk bölgeye aynı anda yönelen bağlantı akını, bölgenin Azure Cosmos DB ağ geçidini aşırı yükledi. Ağ geçidi modundaki Azure Cosmos DB istemcisinin yük devretmeyi ele alışındaki bir özellik yüzünden, fiziksel bölümlerin yalnızca bir kısmı ilk bölgeye dönmüş olmasına rağmen tüm istemciler hemen o bölgeye bağlanıp istek göndermeye başladı.
Her kesintide hem OpenAI hem de Azure olay yönetimi süreçlerini işletti; çeşitli kök nedenler belirlendi ve düzeltmeler devreye alındı. Ancak bu kesintiler, bizim ekibimiz ile Azure Cosmos DB ekibinin işletim ve test yöntemleri arasındaki daha büyük, sistemik bir sorunun belirtileriydi. Başlangıçta yönetilen hizmetlerden yararlanmak, hızlı hareket etmemizi ve iş hedeflerine odaklanmamızı sağladı. Ölçek büyüdüğünde yönetilen hizmetler daha az yönetilir hâle geliyor; tasarımdan operasyona kadar her düzeyde hizmet sağlayıcısıyla derin entegrasyon gerektiriyor.
Bugün Habitat ve Azure mühendislik ekipleri, hizmet katmanlarımızdan Azure Cosmos DB'nin fiziksel depolama katmanlarına kadar Habitat'ın her katmanını birlikte izliyor. Üretim ortamıyla aynı büyüklükte, ancak üretim dışı bir Azure Cosmos DB hesabı işletiyor ve değişiklikleri bu hesapta test ediyoruz. SDK'ları birlikte test edip geliştiriyor, Azure Cosmos DB hesaplarımızın ölçeklendirilmesi ve boyutlandırılması için en iyi uygulamaları belirliyoruz. Teams üzerinden birbirimizin mühendislerine doğrudan erişebiliyor, hatta destek kademelerinden geçmeden birbirimize doğrudan nöbetçi çağrısı gönderebiliyoruz.
Son bir yılda Azure Cosmos DB'nin kontrol düzlemi ve ağ geçidinin ölçeklenebilirliğini iyileştirmek için kapsamlı bir ortak çalışma yürütüldü. Azure Cosmos DB meta veri bölümünü korumak amacıyla ağ geçidine yük koruması ve çeşitli Azure Cosmos DB meta verilerini önbelleğe alma özellikleri eklendi. Bağlantı havuzları ve bağlantıların daha fazla yeniden kullanımıyla Python habitat-service süreçlerimizin oluşturduğu baskı azaltıldı. İş yükleri mümkün olduğunca aynı konuma yerleştirildi ve kritik iş yükleri, farklı VPC'ler aracılığıyla çevrimdışı iş yüklerinden yalıtıldı.
Bu düzeyde ortak mühendislik çalışması, son bir yılda Azure Cosmos DB kararlılığımız açısından kritik önem taşıdı. Yeterince büyük veya kritik her sistem böyle bir ekip çalışmasını gerektirir: sorumluluk alanları arasındaki duvarları kaldırmak ve organizasyon sınırlarının ötesinde çalışmak.
Bölüm I'de belirttiğimiz gibi, temel felsefemiz şu: önce çalışmasını sağla, sonra hızlandır, ardından maliyetini düşür. Önce güvenilirlik, sonra performans, ardından verimlilik. Habitat, OpenAI için kritik bir altyapıya dönüşmüştü; bu yüzden ilk öncelik onu güvenilir hâle getirmekti. 2025'te sistem kararlı hâle gelirken ve OpenAI küresel olarak büyürken, kullanıcılar ve ürün ekipleri için sıradaki kısıt gecikme oldu.
İşlem ve depolama kapasitesi genellikle farklı bölgelerde bulunduğundan, bölgeler arası istekler kaçınılmazdı.
Figure 04 · Improving performance at a global scale
Global traffic
Compute and storage capacity were often located in different regions, making cross-region requests unavoidable.
İşlem ve depolama kaynaklarının coğrafi konumları yalnızca örnek amaçlıdır.
Gecikme, verinin depolandığı ve isteğin karşılandığı konuma göre büyük ölçüde değişiyordu. Ürün geliştiricileri, Habitat isteklerini hızlandırmak için istemci tarafında ek önbellekleme yapıyor, istekleri toplu gönderiyor, veritabanı okuma ve yazmalarını en aza indiriyor ve mümkün olan işleri kritik yürütme yolundan çıkarıyordu. Bu yaklaşım, veritabanı sorunlarına daha dayanıklı bazı ilginç ürün tasarımları ortaya çıkarsa da ürünleri karmaşıklaştırıyor ve geliştirme döngülerini yavaşlatıyordu. Böylece Habitat'ın, veritabanını anlama zorunluluğu olmadan hızlı ürün geliştirmeyi destekleme hedefine ulaşılamıyordu.
2026'da buna yoğun biçimde odaklandık ve Habitat isteklerinin %90'ından fazlasını oluşturan okumaların performansını optimize etmek için katmanlı bir strateji geliştirdik:
Veri yerleşimi gereksinimleri olan kullanıcılar için dünyanın farklı Azure bölgelerinde birden fazla Azure Cosmos DB hesabımız var. Katı veri yerleşimi gereksinimleri olmayan kullanıcılar için de verileri yakınlarında tutmak, gecikmeyi azaltarak deneyimi iyileştiriyor.
Ancak yerleşim, fiziksel bulut kapasitesiyle sınırlı olduğundan, bunu pratikte veri yerleşimi gereksinimleri dışındaki kullanım senaryolarında yaygın olarak uygulayamıyoruz. Veri kümelerimiz o kadar büyük ki birçok bölge, kullanıcı trafiğindeki payına karşılık gelen devasa depolama ihtiyacını karşılayamıyor.
Veri merkezi kapasitesi, elektrik veya soğutma olanakları sınırlı bölgelerde bazen doğrudan bir seçim yapmak zorunda kalıyoruz: aynı konumda depolamaya kapasite ayırıp Habitat gecikmesini azaltmak ya da bu kapasiteyi ek hizmet sunma işlem kaynakları için kullanıp depolama isteklerini daha uzağa yönlendirmek.
Sonuç olarak yerleşim kararları, ürün açısından çoğu zaman iki unsur arasında denge kurmayı gerektiriyor: A) farklı ürünler ve kullanıcı grupları için gecikmeyi optimize etmek, B) ham depolama ve işlem kapasitesi.
Her istekte gereken kimlik doğrulama meta verileri gibi gecikmenin en kritik olduğu iş yüklerinde, birçok ikincil bölgeye çoğaltılan Azure Cosmos DB hesapları kullanarak işlem kaynakları ile Habitat arasındaki gidiş-dönüş süresini (RTT) azaltıyoruz. Bazı hesaplar, trafik sunduğumuz 40 Azure bölgesinin tamamına; diğerleri ise her kıtada en az bir bölgeye çoğaltılıyor.
Veri kümelerini farklı çoğaltma topolojilerine sahip hesaplar arasında taşıyabilmek için Habitat'a, istemcilerin fark etmeden kullanabildiği bir veri taşıma ve yönlendirme katmanını planladığımızdan erken eklemek zorunda kaldık.
Ancak bu yaklaşım da sonuçta kapasiteyle sınırlı olduğundan, yalnızca özenle seçilmiş birkaç veri kümesinde kullanılıyor.
Habitat iş yükleri büyük ölçüde okuma ağırlıklı; uygulamalar sürekli ayarları, durumu ve diğer özellikleri getiriyor. Trafiğin orantısız derecede büyük bir kısmı, sık erişilen türlerden oluşan nispeten küçük bir çalışma kümesinden kaynaklanıyor. Bu, sistemi dağıtık önbellekleme için özellikle uygun kılıyor. Önbellekleme tek bölgeli altyapıda performansı artırırken, bölgeler arası çalışmada kazanımlar katlanıyor; çünkü bölgeler arası gecikmeyi “gizlemek” için kullanılabiliyor.
Habitat'a dağıtık, yandan erişimli (lookaside) bir önbellekleme katmanı entegre ettik. Bu katman, yakın zamanda erişilen nesnelerin ve aralarındaki bağlantıların bir kopyasını, altyapımızda kullanıcı isteklerinin işlendiği konumlara yakın Valkey sunucularında saklıyor. Bu tür önbellekler genellikle isabet oranı ile veri eskiliği arasında denge kuran bir yaşam süresi (TTL) kullanır. Kısa TTL'ler veri eskiliğini azaltır, ancak öğeler önbellekten hızla silinip daha sık yeniden getirilmek zorunda kaldığından önbelleklemenin faydasını sınırlar. Daha uzun TTL'ler isabet oranını artırır, ancak eski verileri uzun süre sunarak kötü kullanıcı deneyimlerine ve öngörülemeyen ürün davranışlarına yol açar.
Başka bir yaklaşım, uygulama aynı temel veriye yazarken açıkça önbellek geçersizleştirme işlemleri yürütmektir. Bu, önbellekteki verilerin güncelliğini büyük ölçüde artırır, ancak doğru uygulanması zor olabilir. Ayrıca kısmi arızalar gibi, önbelleğin güncelliğini yitirmesine neden olan çeşitli uç durumlara da açıktır. Çok bölgeli dağıtımlarda, bölgeler arası ağların daha az güvenilir olması ve önbelleklemenin alttaki depolamanın çoğaltılmasıyla yarışması bu sorunları büyütür. Bunu TTL'lerle tamamlamak, verinin en fazla ne kadar eski olabileceğini sınırlar; ancak yukarıda açıklanan temel TTL ödünleşimi devam eder.
Meta'nın TAO'su gibi sistemlerin izinden giderek daha gelişmiş bir geçersizleştirme yaklaşımı benimsedik. Habitat'ın entegre önbelleği, Azure Cosmos DB değişiklik akışı üzerinden değişiklik verisi yakalamayı (CDC) kullanarak geçersizleştirmeleri saniyeler içinde küresel ölçekte yayıyor. Böylece veri eskiliğini düşük tutarken yüksek isabet oranları sağlıyor. Altyapımızdaki bir hizmet, bu değişiklik akışını tüketiyor ve temel veriler güncellendiğinde yerel önbelleklerde geçersizleştirme yapıyor. Böylece bir sonraki okumada veri önbellekte bulunamıyor ve önbellek, verinin en güncel sürümüyle dolduruluyor.
Kodu, ilk kullanılan Python'dan daha yüksek performans sunan Rust ile yeniden yazarak Habitat hizmetinin kendi ek yükünü de kaldırdık ve gecikmeyi önemli ölçüde azalttık.
Bu değişiklikler birlikte, küresel genel okuma p50 gecikmemizi yaklaşık 120 ms'den 10 ms'ye indirdi. Bu yılın başında performansa odaklanmaya başlamamızdan bu yana 12 kat iyileşme sağladık.
Figure 05 · Improving performance at a global scale
p50 latency for reads
Three major design changes improved read latency
Önbellekleme medyan gecikmeyi büyük ölçüde azaltsa da en yavaş isteklerde hâlâ önbellekte olmayan verilerin temel depolamadan, çoğunlukla uzak bölgelerden getirilmesi gerekiyor. Yeni kapasite devreye girdikçe ve depolama verimliliğini artırdıkça, daha temel bir sorunu çözmeyi planlıyoruz: verileri en baştan erişilecekleri konuma daha yakın yerleştirmek.
Veritabanı değişikliklerini sonraki sistemlere aktaran güvenilir ve ölçeklenebilir CDC, yalnızca Habitat'ın önbellekleme stratejisi için değil, daha fazlası için kritik bir bileşen. Binlerce kapsayıcı ve milyonlarca kapsayıcı bölümünde saniyede yakalanan milyonlarca değişiklik, yüzden fazla Kafka konusundan geçiyor. Bu akış; sonunda tutarlı hâle gelen ikincil dizinleri, veri taşıma hatlarını, çevrimdışı analitiği ve diğer gerçek zamanlı ürün özelliklerini de besliyor. Temel altyapımız küresel ölçekte büyüdükçe satır değişikliklerini dinlemek giderek karmaşıklaştı. Bir istemci, kendi türündeki satırlar her değiştiğinde çalışacak bir geri çağırma işlevi kaydetmek istiyorsa önce verilerinin hangi Cosmos hesaplarında ve kapsayıcılarında olduğunu, ilgili bölgelerde bu kapsayıcıları hangi CDC hizmet dağıtımının dinlediğini belirlemeli. Ayrıca CDC çalışan filosunu, Kafka'yı ve kendi tüketicisini uygun şekilde ölçeklendirmeli. CDC platformumuz, tüm bu ayrıntıları ürün geliştiricilerinden gizlemeyi amaçlıyor. Bunun yerine istemciler, satırları değiştiğinde çağrılmasını istedikleri işlevi basit bir arayüzden kaydediyor; tüm altyapı bağlantılarını ve ölçeklendirmeyi biz yönetiyoruz.
Dahili bir kontrol düzlemi, gerekli tüm kapsayıcılardaki değişikliklerin yakalanmasını sürekli denetliyor, hangi Cosmos bölgelerinden okuma yapılacağını seçiyor ve işi birden fazla coğrafi bölgedeki binlerce çalışan arasında verimli biçimde dağıtıyor. Replika bölgelerin ve düşük öncelikli akış okumalarının kullanılması, gecikmeye duyarlı Habitat trafiğini arka plandaki yakalama iş yüklerinden koruyor. Bu büyüklükteki bir filoda çalışan süreçlerin çökmesi, kapsayıcı sorunları, süreli kilit deposu hataları, geçersiz yapılandırmalar ve hedef sistem arızaları sürekli yaşanıyor. CDC çalışanlarının yaşam döngüsünü ve süreli kilit yönetimini sağlamlaştırdık, akışlar arasındaki arızaları yalıttık, yapılandırma değişiklikleri ve dağıtımlar için koruma mekanizmaları kurduk. Kalıcı teslim hatalarının kuyruk başını tıkamasını önlemek için teslim edilemeyen ileti kuyruklarını kullanıyoruz. Okuyucuları alternatif Cosmos bölgelerine geçirerek bölgesel kesintilere dayanabiliyoruz. Ölçeğimiz nedeniyle Azure'un CDC SDK'sında bile değişiklik yapmamız gerekti. Kontrol noktalarını bellekte biriktirip yalnızca belirli aralıklarla kalıcı depolamaya yazarak kontrol noktası mekanizmasını daha verimli hâle getirdik.
Habitat'ın kendi içinde Azure Cosmos DB kullanımı karmaşık olsa da temel vaadi hep aynıydı: altyapı ayrıntılarını ürün geliştiricilerinden gizleyerek ürün geliştirmeyi hızlandırmak. CDC platformumuzda da durum farklı değil.
Küçük bir ekip; depolama API'sini bilinçli olarak dar kapsamlı tutarak, Python hizmetini ölçeklendirmeye devam ederek ve en acil mühendislik sorunlarına öncelik vererek hızla büyüyen bir depolama platformunu destekleyebildi. Önce kritik ürün trafiğinin güvenilirliğine, ardından dünya genelindeki kullanıcılar için okuma performansına ve son olarak büyük ölçekte operasyonel verimliliğe odaklandık. Bu yaklaşım, güvenilirliği, performansı ve ürün geliştirme hızını artırırken hızlı büyümeyi ve yeni kullanım senaryolarını mümkün kıldı.
Habitat'ı ve sohbet depolamasını sıradaki bir milyar kullanıcı için ölçeklendirmek istiyorsak, verilerimizi altyapımız genelinde çok daha büyük ölçekte çoğaltmanın zorluğunu aşmalıyız. Buna hazırlık olarak, hacimli Habitat veri türleri için optimize edilmiş, eksabayt ölçeğinde özel bir çevrimiçi depolama sistemini şirket içinde geliştiriyoruz. Geliştirme aşamasındaki bu sistem, Rockset'in RocksDB Cloud çekirdeğini Raft tabanlı çoğaltmayla birleştiriyor. Azure Cosmos DB ile aynı belge modelini uyguluyor; ancak daha düşük bir tepe QPS karşılığında gereken flash depolama kapasitesini azaltmak için ayrıştırılmış depolama ve fiziksel çoğaltma kullanıyor.
En üst seviye ölçekte bu tür veri altyapısı çalışmalarında yer almak isterseniz açık pozisyonlarımıza göz atın.


