Haber Akışı Sistem Tasarımı: Yazmada Fan-out ve Okumada Fan-out

Bir haber akışı nasıl tasarlanır: yazmada ve okumada fan-out, büyük akışların çoğunun kullandığı hibrit, akış önbellekleri, sıralama, sayfalama ve bir mimari diyagram.

· Kurucu ve geliştirici

Yayımlandı:

Haber Akışı Sistem Tasarımı: Yazmada Fan-out ve Okumada Fan-out

Ana akış, her sosyal üründe en çok okunan sayfa ve kurulması en pahalı sayfalardan biridir. Her kullanıcı yüzlerce hesabı takip eder, her hesap kendi hızında paylaşım yapar ve akışın, biri uygulamayı her açtığında sıralanmış olarak birkaç yüz milisaniyenin altında gelmesi gerekir.

Temel tasarım sorusunun iki klasik yanıtı var: yazmada fan-out ve okumada fan-out. Her büyük akış sonunda ikisinin bir karışımına varır. Bu yazı ikisini sayılarla karşılaştırıyor, hibriti gösteriyor ve tam okuma ve yazma yollarının diyagramıyla bitiyor.

Gereksinimler

  • Kullanıcı, takip ettiği hesapların son gönderilerini sıralanmış ya da zaman sırasına göre görür.
  • Akışı açmak 99. yüzdelikte bir saniyenin epey altında sürer.
  • Yeni bir gönderi takipçilerin akışlarında saniyeler içinde görünür.
  • Kopya ya da boşluk olmadan sonsuz kaydırma.
  • Bir hesabın on milyonlarca takipçisi olduğunda da çalışmaya devam eder.

Okumalar baskındır. Twitter'ın mimarisini anlatan bu yazıya göre Twitter 2013'te saniyede yaklaşık 6.000 tweet yazmasına karşılık saniyede yaklaşık 300.000 zaman akışı okuması sunduğunu bildirmişti. Önce okumalar için tasarlayın.

Kaba hesaplar

Varsayım Değer
Günlük aktif kullanıcı 10 milyon
Kullanıcı başına günlük akış açma 10, yani ortalama yaklaşık 1.160 okuma/sn
Günlük yeni gönderi 1 milyon, yaklaşık 12 gönderi/sn
Yazar başına ortalama takipçi 200, yani yaklaşık 2.300 fan-out yazma/sn
Önbellekteki akış boyutu 8 baytlık 800 gönderi ID'si, tüm kullanıcılar için yaklaşık 64 GB

Ortalamalar zararsız görünür. Uç değerler öyle değildir: 20 milyon takipçisi olan tek bir yazar tek bir gönderiyle 20 milyon fan-out yazması yaratır; bu, diğer herkes için bir günlük fan-out işinin onda biridir. Aşağıdaki tasarımın başa çıkması gereken şey bu uç değerdir.

Yazmada fan-out (push)

Biri paylaşım yaptığında bir arka plan işi takipçilerini bulur ve gönderi ID'sini her takipçinin önbellekteki akışının en üstüne ekler. Akışı okumak artık tek bir aramadır: kendi listenizdeki en yeni ID'leri alın ve gönderileri getirin.

  • Güçlü yanı: okumalar hızlı ve öngörülebilirdir.
  • Bedeli: bir gönderi, yazarın takipçi sayısı kadar yazma yaratır. 30 milyon takipçili bir hesap tek bir gönderiyi 30 milyon önbellek yazmasına çevirir ve bu takipçiler gönderiyi geç görür. Aynı yazı en büyük hesapların gönderilerinin tüm takipçilere ulaşmasının dakikalar sürdüğünü anlatır.
  • İsraf: bu hafta uygulamayı açmayacak kullanıcıların akışlarına da yazarsınız.

Önbellekteki her akışı kısa tutun. Twitter o dönemde ana zaman akışlarını Redis'te 800 girdiyle sınırlamıştı; daha eski gönderiler biri o kadar aşağı kaydırdığında veritabanından gelir.

Okumada fan-out (pull)

Biri paylaşım yaptığında hiçbir şey yapmayın. Bir kullanıcı akışı açtığında takip ettiği her hesabın son gönderilerini getirin, birleştirin ve sıralayın.

  • Güçlü yanı: yazmalar ucuzdur ve büyük hesaplar ek maliyet yaratmaz.
  • Bedeli: her akış okuması yüzlerce yazara dokunur. Saniyede 300.000 okumada bu, büyük ölçüde tekrarlanan iş için çok sayıda sorgu demektir.

Hibrit

Çoğu büyük akış ikisini birleştirir:

  • Sıradan hesapların gönderilerini takipçilerin önbellekteki akışlarına itin.
  • Belirli bir takipçi eşiğinin üzerindeki hesaplar için fan-out'u atlayın ve onların son gönderilerini okuma anında çekin.
  • Okuma anında önbellekteki akışı çekilen gönderilerle birleştirin, sonra sıralayın.

Eşik bir yasa değil, bir ayar düğmesidir. Onu fan-out yazmalarının maliyetinin ek okumaların maliyetini aşmaya başladığı yere koyun ve takipçi dağılımınız değiştikçe yeniden gözden geçirin. Hiçbir büyük hesabı takip etmeyen kullanıcılar çekme yolunun bedelini hiç ödemez.

Sıralama

Kronolojik bir akış zamana göre sıralar. Sıralanmış bir akış üç adımda çalışır: aday gönderileri toplayın (yukarıdaki birleşik liste, varsa öneriler de), her adayı yenilik, kullanıcının yazarla ne sıklıkla etkileşime girdiği ve gönderideki etkileşim gibi sinyallerle puanlayın, ardından filtreleyin (engellenen hesaplar, zaten görülen gönderiler, birbirine çok benzeyenler).

Sıralamayı fan-out yolunun dışında tutun. Fan-out adayları saklar; sıralama en yeni sinyallerle okuma anında yapılır. Böylece sıralama modelindeki bir değişiklik, önbellekteki akışların yeniden doldurulmasını gerektirmez.

Silmeler, engellemeler ve gizli hesaplar

Akışlar ID tutar; bu yüzden bir gönderiyi silmek gönderi deposuna tek bir yazmadır; akış servisi artık çözümlenemeyen ID'leri atar. Engellemeler ve gizliye geçen hesaplar da okuma anında aynı filtreyi ister, çünkü bir ID'yi milyonlarca önbellekteki akıştan çıkarmak yavaştır ve hataya açıktır.

Sayfalama

Bir akışı asla offset ile sayfalamayın. Kullanıcı kaydırırken yeni gönderiler en üste gelir, bu yüzden "2. sayfa" kayar ve kopyalar gösterir. Konumu kodlayan bir cursor döndürün (örneğin sunulan son öğenin ID'si ya da puanı) ve "bu cursor'dan sonraki öğeleri" isteyin. Sıralanmış akışlarda, sonraki sayfaların ilkiyle tutarlı kalması için sıralanmış listeyi oturum boyunca kısa bir süre saklayın.

Mimari diyagram

Bir gönderi servisi gönderileri saklar ve olay yayınlar. Fan-out işçileri sosyal grafiği okur ve yazarın bir milyondan fazla takipçisi olup olmadığına bakar. Yoksa gönderi ID'sini takipçi akış önbelleklerine iter; varsa okuma anında çekilir. Akış servisi ikisini birleştirip sıralar.

13 bileşen · 13 bağlantı

Archboard'da aç
Diyagram içeriği
  • User
  • Post service
  • Posts store
  • Post events
  • Fan-out workers
  • Social graph
  • Author over 1M followers?
  • Feed cache
  • Pulled at read time
  • Feed service
  • Ranking
  • Media CDN
  • POST /posts
  • post.created
  • followers
  • no: push post ID
  • yes
  • GET /feed
  • cached timeline
  • big accounts
  • images and video
Hibrit bir haber akışı. Çoğu yazarın gönderileri her takipçinin önbellekteki akışına itilir; çok büyük takipçi kitlesi olan hesapların gönderileri okuma anında çekilir, önbellekteki akışla birleştirilir ve sayfa dönmeden önce sıralanır.

Nasıl okunur:

  • Yazma yolu (üstte): gönderi servisi gönderiyi saklar ve bir olay yayınlar. Fan-out işçileri sosyal grafiği okur ve yazarın takipçi sayısına bakar.
  • Karar: çoğu yazar için işçiler gönderi ID'sini her takipçinin akış önbelleğine iter. Eşiğin üzerindeki hesaplar için hiçbir şey itilmez; onların gönderileri okuma anında çekilir.
  • Okuma yolu (altta): akış servisi kullanıcının önbellekteki akışını ve büyük hesapların gönderi deposundaki son gönderilerini okur, birleştirir ve sıralamaya gönderir.
  • Medya bir CDN üzerinden gider, akış servisinden hiç geçmez.
  • Markdown bloğu pratik kuralları tasarımın yanında tutar.

Diyagrama neler koymalı

  • İki yol, net biçimde ayrılmış. Yazmaların ve okumaların ölçekleme sorunları farklıdır.
  • Fan-out eşiği. Sonradan değişse bile sayıyı kararın üzerine yazın.
  • Neyin nerede saklandığı. Akış önbellekleri gönderileri değil gönderi ID'lerini tutar; içerik gönderi deposundadır.
  • Sıralamanın nerede yapıldığı. Okuyan, bunun okuma anında çalıştığını görmeli.

Bu tasarımın ortasında duran önbellek kendi diyagramını hak ediyor; önbellek stratejileri yazısına bakın. Olay güdümlü mimari yazısı olay ve tüketici tarafını anlatır; sistem tasarımı diyagramı örneği de aynı kuralları farklı bir sistemde gösterir.

Archboard'da oluşturun

  1. Google ya da GitHub ile giriş yapın ve bir diyagram oluşturun.
  2. C4 Modeli paketinden bir Kişi, ardından gönderi servisi, fan-out işçileri, akış servisi ve sıralama için Konteyner düğümleri ekleyin.
  3. Gönderi deposu ve sosyal grafik için C4 Modeli paketinden Veritabanı düğümleri, gönderi olayları ve akış önbellekleri için Veri paketinden Kafka ve Redis, Bulut paketinden de bir CDN ekleyin.
  4. Takipçi eşiği için Akış Şeması paketinden bir Karar ve bir Başla / Bitir ekleyin.
  5. Yazma yolunu üstte, okuma yolunu altta çizin ve pratik kurallarınızı içeren, Temel paketinden bir Markdown bloğu ekleyin.

Örnek 13 diyagram düğümü kullanıyor ve Free planın sınırları içinde kalıyor.

SSS

Yazmada fan-out mu daha iyi, okumada fan-out mu? Tek başına hiçbiri. Yazmada fan-out hızlı okumalar sağlar ama dev takipçi kitlesi olan hesaplarda patlar; okumada fan-out yazması ucuzdur ama okuması yavaştır. Büyük akışlar hibrit kullanır.

Akış önbelleği ne saklamalı? Gönderi ID'leri, en yeni önce, kullanıcı başına birkaç yüzle sınırlı. Gönderi içeriğini ayrı getirin; böylece düzenlemeler ve silmeler her akışın yeniden yazılmasını gerektirmez.

Bir ünlünün paylaşımını nasıl ele alırım? Belirli bir takipçi eşiğinin üzerindeki hesaplar için fan-out'u atlayın ve takipçiler akışı açtığında onların son gönderilerini çekin.

Akış sayfalaması nasıl çalışmalı? Sayfa numaraları ya da offset'lerle değil, sunulan son öğeye dayanan bir cursor ile; böylece kullanıcı kaydırırken yeni gönderiler kopyalara yol açmaz.

Sıralama nerede yapılır? Okuma anında, birleşik aday listesi üzerinde. Onu fan-out'un dışında tutmak, önbellekteki akışları yeniden oluşturmadan sıralamayı değiştirebilmeniz demektir.

Ücretsiz başlayın — tek kullanıcı, kredi kartı gerekmez.

İlgili yazılar

← Blog'a dön

Bir dakikada canvas açın

Google veya GitHub ile giriş yapın. Tek koltuk ücretsiz; ekip katılınca planı yükseltin.