Memuat pengoptimalan pada proyek Highload dengan ElasticSearch

Halo, Habr! Nama saya Maxim Vasiliev, saya bekerja sebagai analis dan manajer proyek di FINCH. Hari ini saya ingin memberi tahu Anda caranya, menggunakan ElasticSearch, kami dapat memproses 15 juta kueri dalam 6 menit dan mengoptimalkan beban harian di situs salah satu klien kami. Sayangnya, kami harus melakukannya tanpa nama, karena kami memiliki NDA, kami berharap bahwa isi artikel tidak akan terpengaruh. Ayo pergi.

Bagaimana proyek ini diatur


Di backend kami, kami menciptakan layanan yang memastikan kinerja situs dan aplikasi seluler klien kami. Struktur umum dapat dilihat pada diagram:

gambar

Dalam proses, kami memproses sejumlah besar transaksi: pembelian, pembayaran, operasi dengan saldo pengguna, di mana kami menyimpan banyak log, dan juga mengimpor dan mengekspor data ini ke sistem eksternal.

Ada juga proses terbalik ketika kami menerima data dari klien dan mengirimkannya ke pengguna. Selain itu, masih ada proses untuk bekerja dengan pembayaran dan program bonus.

Latar belakang pendek


Awalnya, kami menggunakan PostgreSQL sebagai satu-satunya gudang data. Keuntungan standar untuk DBMS: ketersediaan transaksi, bahasa yang dikembangkan dari pengambilan sampel data, alat yang luas untuk integrasi; ditambah dengan kinerja yang baik, orang yang puas telah lama memenuhi kebutuhan kita.

Kami benar-benar menyimpan semua data di Postgres: dari transaksi hingga berita. Tetapi jumlah pengguna meningkat, dan dengan itu jumlah permintaan.

Untuk memahami, jumlah sesi tahunan pada 2017 di situs desktop saja adalah 131 juta. Pada 2018, 125 juta 2019 lagi 130 juta. Tambahkan 100-200 juta lagi dari versi seluler situs dan aplikasi seluler, dan Anda akan mendapatkan sejumlah besar permintaan.

Dengan pertumbuhan proyek, Postgres berhenti untuk mengatasi beban, kami tidak punya waktu - sejumlah besar berbagai pertanyaan muncul, di mana kami tidak dapat membuat sejumlah indeks.

Kami menyadari bahwa ada kebutuhan untuk gudang data lain yang akan menyediakan kebutuhan kami dan mengambil beban PostgreSQL. Elasticsearch dan MongoDB dianggap sebagai opsi yang memungkinkan. Yang terakhir hilang pada poin-poin berikut:

  1. Kecepatan pengindeksan lambat dengan peningkatan volume data dalam indeks. Kecepatan elastis tidak tergantung pada jumlah data.
  2. Tidak ada pencarian teks lengkap

Jadi kami memilih Elastis untuk diri kami sendiri dan bersiap untuk transisi.

Beralih ke Elastis


1. Kami memulai transisi dengan layanan pencarian titik penjualan. Klien kami memiliki total sekitar 70.000 poin penjualan, dan memerlukan beberapa jenis pencarian di situs dan dalam aplikasi:

  • Pencarian teks dengan nama kota
  • Pencarian geografis dalam radius tertentu dari beberapa titik. Misalnya, jika pengguna ingin melihat titik penjualan mana yang paling dekat dengan rumahnya.
  • Cari berdasarkan kotak yang diberikan - pengguna menggambar kotak di peta, dan dia ditunjukkan semua titik dalam radius ini.
  • Cari filter tambahan. Poin penjualan berbeda satu sama lain dalam bermacam-macam

Berbicara tentang organisasi, maka di Postgres kami memiliki sumber data baik di peta dan di berita, dan di Snapshots elastis dibuat dari data asli. Faktanya adalah bahwa awalnya Postgres tidak dapat mengatasi pencarian dengan semua kriteria. Tidak hanya ada banyak indeks, mereka juga bisa berpotongan, sehingga penjadwal Postgres tersesat dan tidak mengerti indeks mana yang akan digunakan untuk itu.

2. Baris berikutnya adalah bagian berita. Setiap hari, publikasi muncul di situs sehingga pengguna tidak tersesat dalam arus informasi, data harus diurutkan sebelum dikeluarkan. Untuk ini, Anda perlu pencarian: di situs Anda dapat mencari berdasarkan teks, dan pada saat yang sama menghubungkan filter tambahan, karena mereka juga dibuat melalui Elastis.

3. Kemudian kami memindahkan pemrosesan transaksi. Pengguna dapat membeli produk tertentu di situs dan berpartisipasi dalam pengundian hadiah. Setelah pembelian seperti itu, kami memproses sejumlah besar data, terutama pada akhir pekan dan hari libur. Sebagai perbandingan, jika pada hari-hari biasa jumlah pembelian berkisar antara 1,5-2 juta, maka pada hari libur angkanya dapat mencapai 53 juta.

Pada saat yang sama, data perlu diproses dalam waktu minimum - pengguna tidak suka menunggu hasil selama beberapa hari. Anda tidak akan mencapai tenggat waktu tersebut melalui Postgres - kami sering mendapatkan kunci, dan sementara kami memproses semua permintaan, pengguna tidak dapat memeriksa apakah mereka menerima hadiah atau tidak. Ini tidak terlalu menyenangkan untuk bisnis, jadi kami memindahkan pemrosesan ke Elasticsearch.

Periodisitas


Sekarang pembaruan dikonfigurasikan berdasarkan peristiwa, dengan ketentuan berikut:

  1. Titik penjualan. Segera setelah data dari sumber eksternal datang kepada kami, kami segera memulai pembaruan.
  2. Berita. Segera setelah ada berita yang diedit di situs, itu secara otomatis dikirim ke Elastis.

Di sini sekali lagi, perlu disebutkan kelebihan dari Elastis. Di Postgres, saat mengirim permintaan, Anda harus menunggu sampai semua catatan diproses dengan jujur. Anda dapat mengirim 10 ribu catatan ke Elastik, dan segera mulai bekerja, tanpa menunggu hingga catatan didistribusikan di semua Shard. Tentu saja, beberapa Shard atau Replika mungkin tidak melihat data segera, tetapi segera semuanya akan tersedia.

Metode Integrasi


Ada 2 cara untuk berintegrasi dengan Elastis:

  1. Melalui klien asli melalui TCP. Pengemudi asli secara bertahap sekarat: tidak lagi didukung, ia memiliki sintaks yang sangat tidak nyaman. Karenanya, kami praktis tidak menggunakannya dan mencoba untuk sepenuhnya mengabaikannya.
  2. Melalui antarmuka HTTP tempat Anda dapat menggunakan permintaan JSON dan sintaks Lucene. Yang terakhir adalah mesin teks yang menggunakan Elastis. Dalam opsi ini, kami mendapatkan kemampuan untuk Batch melalui permintaan JSON melalui HTTP. Ini adalah opsi yang kami coba gunakan.

Berkat antarmuka HTTP, kami dapat menggunakan perpustakaan yang menyediakan implementasi asinkron dari klien HTTP. Kita dapat mengambil keuntungan dari Batch dan API asinkron, yang pada akhirnya memberikan kinerja tinggi, yang banyak membantu di hari-hari aksi besar (lebih lanjut di bawah ini)

Beberapa angka untuk dibandingkan:

  • Menyimpan pengguna yang menerima hadiah di Postgres dalam 20 aliran tanpa pengelompokan: 460.713 entri dalam 42 detik
  • Klien elastis + reaktif untuk 10 utas + kumpulan untuk 1000 elemen: 596749 mencatat dalam 11 detik
  • Klien elastis + reaktif untuk 10 utas + kumpulan untuk 1000 elemen: 23801684 catatan dalam 4 menit

Sekarang kami telah menulis manajer permintaan HTTP yang membangun JSON sebagai Batch / bukan Batch dan mengirimkannya melalui klien HTTP apa pun, terlepas dari pustaka. Anda juga dapat memilih untuk mengirim permintaan secara sinkron atau asinkron.

Dalam beberapa integrasi, kami masih menggunakan klien transportasi resmi, tetapi ini hanya masalah refactoring yang akan datang. Pada saat yang sama, klien khusus yang dibangun berdasarkan Spring WebClient digunakan untuk diproses.

gambar

Promosi besar


Setahun sekali, kampanye besar untuk pengguna dilakukan di proyek - ini adalah Highload yang sama, karena saat ini kami bekerja dengan puluhan juta pengguna pada saat yang sama.

Biasanya beban puncak terjadi selama liburan, tetapi tingkat promosi ini sangat berbeda. Tahun sebelumnya, pada hari promosi, kami menjual 27.580.890 unit barang. Data diproses selama lebih dari setengah jam, yang menyebabkan ketidaknyamanan bagi pengguna. Pengguna menerima hadiah untuk berpartisipasi, tetapi menjadi jelas bahwa proses tersebut perlu dipercepat.

Pada awal 2019, kami memutuskan bahwa kami membutuhkan ElasticSearch. Selama satu tahun penuh, kami mengatur pemrosesan data yang diterima dalam Elastis dan hasilnya dalam api aplikasi dan situs seluler. Akibatnya, tahun berikutnya selama kampanye kami memproses 15 131 783 catatan dalam 6 menit.

Karena kami memiliki banyak orang yang ingin membeli barang dan berpartisipasi dalam pengundian hadiah dalam promosi, ini adalah tindakan sementara. Sekarang kami mengirim informasi yang relevan ke Elastic, tetapi di masa depan kami berencana untuk mentransfer informasi arsip dari bulan-bulan terakhir ke Postgres sebagai repositori permanen. Agar tidak menyumbat indeks elastis, yang juga memiliki keterbatasan.

Kesimpulan / Kesimpulan


Saat ini, kami telah mentransfer ke Elastic semua layanan yang kami inginkan dan telah dihentikan sementara untuk saat ini. Sekarang kami sedang membangun indeks di Elastic di atas penyimpanan persisten utama di Postgres, yang mengambil beban pengguna.

Di masa mendatang, kami berencana untuk mentransfer layanan jika kami memahami bahwa permintaan data menjadi terlalu beragam dan dicari dengan jumlah kolom yang tidak terbatas. Ini bukan lagi tugas untuk Postgres.

Jika kita memerlukan pencarian teks lengkap di fungsional, atau jika kita memiliki banyak kriteria pencarian yang berbeda, maka kita sudah tahu bahwa ini perlu diterjemahkan ke dalam Elastis.

⌘⌘⌘


Terima kasih sudah membaca. Jika perusahaan Anda juga menggunakan ElasticSearch dan memiliki kasus implementasi sendiri, beri tahu kami. Akan menarik mengetahui apa yang dimiliki orang lain :-)

All Articles