OpenAI

23 Ekim 2026

Mühendislik

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?

Yazanlar: Teknik ekip üyeleri Jon Lee, Hrachya Hakobyan ve Chaomin Yu

Yükleniyor...

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)

İstemciler

Çevrimiçi depolama platformu

Depolama kaynakları

  • ChatGPT
  • API
  • Codex
  • Dâhilî hizmetler
  • Ve daha fazlası

Habitat

  • Önbelleğe almaÖnbellekler
  • ACL politikalarıYetkilendirme
  • Yerleştirme ve veri yerleşimiVeri yerleşimi
  • ŞifrelemeVeri güvenliği
  • YalıtımÇok kiracılılık
  • Hız sınırlamaİstek biçimlendirme
  • YönlendirmeŞema arama · Veri yerleşimi
  • Azure Cosmos DBÇevrimiçi depolama
  • NanobaseÇevrimiçi depolama
  • ValkeyÖnbellekler
  • Blob depolamaDepolama kaynakları
CDC HizmetleriDeğişiklik Verisi Yakalama
  • Databricks
  • Rockset
  • Kafka
  • Ve daha fazlası

Çok kiracılı mimariyi büyük ölçekte güvenilir kılmak

Ş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 kapsayıcılarına kısa bir giriş

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

Aşama I: Azure Cosmos DB'nin temel yapı taşlarına dayanmak

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ı:

Mantıksal bölüm anahtarı sınırları

İ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

Cosmos DB containerPhysical partitionPK: user-id-28104CapacityMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedConversationsSuccess rateResponses returned in this animation loop—AuthSuccess rateResponses returned in this animation loop—Memory / dreamingSuccess rateResponses returned in this animation loop—

Gürültülü komşular

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

Cosmos DB containerPhysical partitionPKs: user-id-28104, user-id-10384Conversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversationsuser-id-28104Success rateResponses returned in this animation loop—Conversationsuser-id-10384Success rateResponses returned in this animation loop—

Zayıf bölümler

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.

Before split: 10K RU/s capacity

After split: 5K RU/s capacity × 2 partitions

RU/s05K6K10K200200429

Aşama II: İş yükü yalıtımını ve tek kiracılı mimariyi denemek

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ı:

Toplam kullanımda istikrarlı büyümenin olmaması

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

Shared container

100M RU/s capacity · 80% utilized

Load test

1K20M=

0.005%

of headroom

Launch

1M20M=

5%

of headroom

New dedicated container

10K RU/s capacity · no other workloads

Load test

1K10K=

10%

of headroom

Launch

1M10K=

10,000%

of headroom

Kapasite planlaması

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.

Aşama III: Veri taşıma olanağıyla varsayılan olarak çok kiracılı mimariyi kullanmak

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:

Yoğun kullanılan anahtarlara hız sınırlaması

Ö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.

Hizmet Kalitesi (QoS)

İ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.

Sunucusuz mod

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.

Ortak yönetilen hizmetlerle daha yüksek güvenilirlik

Ş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.

Küresel ölçekte performansı iyileştirmek

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.

ComputeStorageIllustrative routes · Longer journeys take more time

İş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:

Kapasite elverdiğinde verileri kullanıcılara yakın tutmak

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.

Yalnızca en küçük ve gecikmeye en duyarlı veri kümelerini yaygın biçimde çoğaltmak

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.

Diğer tüm veriler için entegre önbelleklemeden yararlanmak

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.

Rust ile vekil katmanın ek yükünü azaltmak

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

roughly 120 ms → roughly 10 ms

12x improvement

Milliseconds020406080100120140160Zaman123
  1. critical data replicated into nearby geos
  2. in-region caching launched
  3. rust rewrite launched

Ö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.

Değişiklik verisi yakalamayı ölçeklendirmek

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.

Geleceğe bakış

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⁠.

Yazar

OpenAI