ElasticSearch ile bir Highload projesinde yük optimizasyonu

Hey Habr! Adım Maxim Vasiliev, FINCH'te analist ve proje yöneticisi olarak çalışıyorum. Bugün size ElasticSearch'ü kullanarak 15 milyon talebi 6 dakikada nasıl işleyebildiğimizi ve müşterilerimizden birinin sitesindeki günlük yükleri nasıl optimize edebildiğimizi anlatmak istiyorum. Ne yazık ki isimsiz yapmak zorunda kalacağız, bir gizlilik anlaşmamız olduğu için makalenin içeriğinin bundan zarar görmeyeceğini umuyoruz. Hadi gidelim.

Proje nasıl çalışıyor?

Arka uçta müşterilerimizin web sitelerinin ve mobil uygulamalarının performansını garantileyen hizmetler yaratıyoruz. Genel yapı şemada görülebilir:

ElasticSearch ile bir Highload projesinde yük optimizasyonu

Çalışma sürecinde çok sayıda işlemi işliyoruz: çok sayıda günlük sakladığımız satın almalar, ödemeler, kullanıcı bakiyeleriyle yapılan işlemler ve bu verileri harici sistemlere içe ve dışa aktarıyoruz.

İstemciden veri alıp kullanıcıya aktardığımızda da ters süreçler yaşanıyor. Ayrıca ödemeler ve bonus programlarıyla çalışmaya yönelik süreçler hala mevcuttur.

Kısa geçmiş

Başlangıçta tek veri deposu olarak PostgreSQL'i kullandık. Bir DBMS için standart avantajları: işlemlerin varlığı, gelişmiş bir veri örnekleme dili, entegrasyon için geniş bir araç yelpazesi; iyi performansla birleştiğinde ihtiyaçlarımızı uzun süre karşıladı.

İşlemlerden haberlere kadar kesinlikle tüm verileri Postgres'te sakladık. Ancak kullanıcı sayısı ve bununla birlikte isteklerin sayısı da arttı.

Anlamak için, 2017'de sadece masaüstü sitedeki yıllık oturum sayısı 131 milyon. 2018'de - 125 milyon. 2019'da yine 130 milyon. Sitenin mobil versiyonundan ve mobil uygulamadan 100-200 milyon daha ekleyin ve siz çok sayıda istek alacak.

Projenin büyümesiyle birlikte Postgres yükle başa çıkmayı bıraktı, zamanımız yoktu - yeterli sayıda dizin oluşturamadığımız çok sayıda farklı sorgu ortaya çıktı.

İhtiyaçlarımızı karşılayacak ve PostgreSQL'in yükünü hafifletecek başka veri depolarına ihtiyaç olduğunu anladık. Elasticsearch ve MongoDB olası seçenekler olarak değerlendirildi. İkincisi aşağıdaki noktalarda kaybetti:

  1. Dizinlerdeki veri miktarı arttıkça dizin oluşturma hızı yavaşlar. Elastic ile hız, veri miktarına bağlı değildir.
  2. Tam metin araması yok

Biz de kendimiz için Elastic'i seçtik ve geçişe hazırlandık.

Elastikliğe Geçiş

1. Satış noktası arama hizmetinden geçişe başladık. Müşterimizin toplam yaklaşık 70 satış noktası vardır ve bu, sitede ve uygulamada çeşitli arama türlerini gerektirir:

  • Şehir adına göre metin arama
  • Belirli bir noktadan belirli bir yarıçap içinde coğrafi arama. Örneğin kullanıcı evine en yakın satış noktalarının hangileri olduğunu görmek istiyorsa.
  • Belirli bir kareye göre arama yapın - kullanıcı haritaya bir kare çizer ve bu yarıçaptaki tüm noktalar ona gösterilir.
  • Ek filtrelere göre arama yapın. Satış noktaları ürün çeşitliliği bakımından birbirinden farklıdır

Organizasyondan bahsedecek olursak Postgres'te hem harita hem de haberler için bir veri kaynağımız var ve Elastic Snapshot'lar orijinal verilerden alınıyor. Gerçek şu ki, Postgres başlangıçta tüm kriterlere göre aramayla baş edemedi. Çok sayıda dizin olması bir yana, bunlar örtüşebiliyordu, dolayısıyla Postgres planlayıcısı kaybolmuştu ve hangi dizini kullanacağını anlayamıyordu.

2. Sırada haberler bölümü vardı. Kullanıcının bilgi akışında kaybolmaması için sitede her gün yayınlar yer almaktadır, verilerin yayınlanmadan önce sıralanması gerekmektedir. Aramanın amacı budur: sitede metin eşleşmesine göre arama yapabilir ve aynı zamanda Elastic aracılığıyla yapıldığı için ek filtreler de bağlayabilirsiniz.

3. Daha sonra işlem işlemini gerçekleştirdik. Kullanıcılar site üzerinden belirli bir ürünü satın alarak ödül çekilişine katılabilirler. Bu tür satın alımlardan sonra özellikle hafta sonları ve tatil günlerinde büyük miktarda veri işleriz. Karşılaştırma yapmak gerekirse, normal günlerde satın alma sayısı 1,5-2 milyon arasındaysa, tatil günlerinde bu rakam 53 milyona ulaşabiliyor.

Aynı zamanda, verilerin mümkün olan en kısa sürede işlenmesi gerekir - kullanıcılar sonucu birkaç gün beklemekten hoşlanmazlar. Postgres aracılığıyla bu tür son teslim tarihlerine ulaşmanın bir yolu yok; sık sık kilitler alıyorduk ve biz tüm talepleri işlerken kullanıcılar ödül alıp almadıklarını kontrol edemiyorlardı. Bu iş açısından pek hoş bir durum olmadığından işlemeyi Elasticsearch'e taşıdık.

periyodik olarak tekrarlanma

Artık güncellemeler aşağıdaki koşullara göre olaya dayalı olarak yapılandırılıyor:

  1. Satış noktaları. Harici bir kaynaktan veri alır almaz güncellemeyi hemen başlatırız.
  2. Haberler. Sitede herhangi bir haber düzenlendiği anda otomatik olarak Elastic'e gönderilir.

Burada yine Elastic'in avantajlarından bahsetmekte fayda var. Postgres'te bir istek gönderirken, tüm kayıtların dürüst bir şekilde işlenmesini beklemeniz gerekir. 10 kaydı Elastic'e gönderebilir ve kayıtların tüm Parçalara dağıtılmasını beklemeden hemen çalışmaya başlayabilirsiniz. Elbette bazı Parçalar veya Replikalar verileri hemen göremeyebilir ancak her şey çok yakında kullanıma sunulacaktır.

Entegrasyon yöntemleri

Elastic ile entegrasyonun 2 yolu vardır:

  1. TCP üzerinden yerel bir istemci aracılığıyla. Yerel sürücü yavaş yavaş yok oluyor: artık desteklenmiyor, çok uygunsuz bir sözdizimine sahip. Bu nedenle pratikte kullanmıyoruz ve tamamen terk etmeye çalışıyoruz.
  2. Hem JSON isteklerini hem de Lucene sözdizimini kullanabilen bir HTTP arayüzü aracılığıyla. Sonuncusu Elastic kullanan bir metin motorudur. Bu sürümde, HTTP üzerinden JSON isteklerini toplu olarak işleme olanağına sahibiz. Kullanmaya çalıştığımız seçenek bu.

HTTP arayüzü sayesinde HTTP istemcisinin eşzamansız uygulanmasını sağlayan kütüphaneleri kullanabiliriz. Büyük promosyonun olduğu günlerde çok yardımcı olan yüksek performansla sonuçlanan Batch'ten ve eşzamansız API'den yararlanabiliriz (bununla ilgili daha fazla bilgi aşağıda)

Karşılaştırma için bazı sayılar:

  • Postgres ödül kullanıcılarını gruplandırmadan 20 başlıkta kaydetme: 460713 saniyede 42 kayıt
  • 10 iş parçacığı için elastik + reaktif istemci + 1000 öğe için toplu iş: 596749 saniyede 11 kayıt
  • 10 iş parçacığı için elastik + reaktif istemci + 1000 öğe için toplu iş: 23801684 dakikada 4 giriş

Artık JSON'u Batch olarak / Batch değil olarak derleyen ve kütüphaneden bağımsız olarak herhangi bir HTTP istemcisi üzerinden gönderen bir HTTP istek yöneticisi yazdık. Ayrıca istekleri eşzamanlı veya eşzamansız olarak göndermeyi de seçebilirsiniz.

Bazı entegrasyonlarda hala resmi taşıma istemcisini kullanıyoruz, ancak bu yalnızca bir sonraki yeniden düzenleme meselesidir. Bu durumda, işleme için Spring WebClient temelinde oluşturulmuş özel bir istemci kullanılır.

ElasticSearch ile bir Highload projesinde yük optimizasyonu

büyük promosyon

Proje yılda bir kez kullanıcılar için büyük bir promosyona ev sahipliği yapıyor - bu aynı Highload'dur, çünkü şu anda on milyonlarca kullanıcıyla aynı anda çalışıyoruz.

Genellikle tatillerde yüklerin zirveye çıktığı görülür, ancak bu promosyon tamamen farklı bir düzeydedir. Geçtiğimiz yıl promosyon gününde 27 adet ürün satışı gerçekleştirmiştik. Verilerin yarım saatten fazla işlenmesi kullanıcılar açısından sıkıntı yarattı. Kullanıcılar katılım karşılığında ödüller aldı ancak sürecin hızlandırılması gerektiği ortaya çıktı.

2019'un başında ElasticSearch'e ihtiyacımız olduğuna karar verdik. Bir yıl boyunca alınan verilerin Elastic'te işlenmesini ve bunların mobil uygulama ve web sitesinin API'sinde yayınlanmasını organize ettik. Sonuç olarak, bir sonraki yıl kampanya sırasında işleme koyduk 15 dakikada 131 giriş.

Promosyonlarda ürün satın almak ve ödül çekilişine katılmak isteyen çok sayıda insanımız olduğundan bu geçici bir önlemdir. Şimdi Elastic'e güncel bilgiler gönderiyoruz, ancak gelecekte geçmiş aylara ait arşivlenen bilgileri kalıcı bir depolama alanı olarak Postgres'e aktarmayı planlıyoruz. Sınırlamaları da olan Elastik endeksi tıkamamak için.

Sonuç/Sonuçlar

Şu anda istediğimiz tüm hizmetleri Elastic’e aktardık ve şimdilik buna ara verdik. Şimdi, Postgres'teki ana kalıcı depolamanın üzerine, kullanıcı yükünü üstlenen Elastic'te bir dizin oluşturuyoruz.

Gelecekte, veri talebinin çok çeşitli hale geldiğini ve sınırsız sayıda sütunda arandığını anlarsak hizmetleri aktarmayı planlıyoruz. Bu artık Postgres'in görevi değil.

İşlevsel olarak tam metin aramaya ihtiyacımız varsa veya çok sayıda farklı arama kriterimiz varsa, bunun Elastic'e çevrilmesi gerektiğini zaten biliyoruz.

⌘⌘⌘

Okuduğunuz için teşekkürler. Şirketiniz de ElasticSearch kullanıyorsa ve kendi uygulama senaryoları varsa bize bildirin. Başkalarının nasıl olduğunu bilmek ilginç olacak 🙂

Kaynak: habr.com

Yorum ekle