| May 20, 2021

2 MIN READ

Written by Ashnik Team

Penalaan halus Postgres untuk mencapai 5,000 Pertanyaan sesaat!

Saya ingin berkongsi pengalaman saya baru-baru ini dengan salah satu pelanggan Ashnik. Pelanggan ini ialah sebuah ISV/SI global yang telah membangunkan aplikasi kritikal perniagaan yang digunakan oleh berjuta pelanggan. Fungsi aplikasi ini memerlukan bilangan transaksi pemprosesan yang sangat tinggi semasa waktu puncak. Pelanggan ini telah memutuskan untuk mengguna EDB Prostgres dan bukannya teknologi pangkalan data proprietari, maka ianya memberi tekanan kepada kami untuk memberi pencapaian yang diinginkan. Kami telah banyak melakukan kerja-kerja rundingan untuk rekabentuk dan fasa ukuran. Selepas begitu banyak semakan dan kelulusan, kami mengatur kedudukan EDB Postgres pada pelayan-pelayan yang disasarkan.

Status dan tetapan pra-penyelesaian

Kami telah mengatur kedudukan tiga nod kluster EDB dengan EDB EFM untuk HA dan toleransi kesalahan. Kami juga telah menetapkan Pgpool bagi pengumpulan sambungan (connection pooling) dan keseimbangan beban (load balancing). Kami menjangkakan banyak transaksi (SELECT, INSERT dan UPDATES) dan serentak di dalam pelayan pangkalan data. Kami dayakan serialize_accept pada pgpool bagi mencegah “thundering herd problem”, yang mana boleh didapati selanjutnya dalam link serialize_accept.

Tambahan lagi, parameter-parameter berikut telah ditetapkan pada pgpool untuk mengekalkan pengumpulan sambungan: 

1. client_idle_limit – 120 (Memutuskan sesi sambungan pangkalan data selepas 120 saat berlalu sejak pertanyaan terakhir)
2. child_life_time – 0 (Kami tidak mendayakan parameter in kerana kami telah mendayakan serialize_accept)
3. connection_life_time – 60 (Mematikan sambungan cache pangkalan data 60 saat selepas pelanggan memutuskan sambungan)
4. child_max_connections – 10 (Setiap proses kecil pgpool boleh menangani 20 sambungan sebelum ia memulakan proses kecil yang baru)

Senibina Pangkalan Data bagi persekitaran Ujian Prestasi:

Kami mulakan dengan saranan tetapan bagi parameter-parameter pangkalan data seperti shared_buffers, work_mem, temp_file_limit, dan sebagainya dan selepas beberapa minggu ujian, kami menala halus beberapa parameter daripada nilai-nilai asalnya. Konfigurasi tetapan-tetapan lain pada pangkalan data dan peringkat OS telah dilakukan untuk beban kerja yang dijangkakan dan kami bersedia untuk ujian PT (Performance Test).

Cabarannya

Fungsi perniagaan aplikasi ini memerlukan bilangan transaksi perniagaan yang sangat tinggi yang bermaksud ianya memerlukan bilangan sambungan serentak yang tinggi, datang dari beberapa perkhidmatan mikro (microservice) ke pangkalan data. Untuk tujuan ini, kami menyarankan penggunaan pgpool bagi pengumpulan sambungan serta bagi keseimbangan beban sambungan pada pangkalan data yang datang dari perkhidmatan mikro ini. Pada awalnya, pasukan seni bina aplikasi ISV menganggarkan bahawa untuk mencapai transaksi perniagaan yang diingini, ianya akan memerlukan sehingga 10,000 sambungan serentak pada peringkat pangkalan data. Bilangan ini (10,000 sambungan serentak) adalah amat tinggi tetapi kami mulakan usaha bersama pasukan aplikasi dan infra untuk mencapai prestasi tersebut.

Kerjasama pasukan ini merancang untuk beberapa kitaran Ujian Prestasi (PT) dan Ujian Beban (LT) yang teliti.
Apabila Ujian Prestasi dimulakan, semuanya nampak baik dengan 500-600 sambungan serentak ke pangkalan data. Pertanyaan juga dijalankan dalam tempoh masa yang munasabah (~<100ms). Kemudian, kami sedari bahawa sambungan pangkalan data mula meningkat. Dalam masa 10-15 saat, bilangan sambungan meningkat dari 1,000 ke 2,500 dan dengan cepat meningkat ke sekitar 7,000+ sambungan ke pangkalan data (5000+ aktif, 1000+ sambungan melahu, dan 500+ melahu dalam sambungan transaksi). Purata beban pada pelayan mendadak naik dengan bacaan 3,000, 2,800, 2,700, masing-masing bagi 1,5 dan 15 minit terakhir. Ini adalah bukti bahawa pelayan pangkalan data tidak berupaya untuk mengendali bilangan sambungan sebanyak ini. Apabila ia mencapai melebihi parameter “num_init_children” pada pgpool, kami juga mula mendapat ralat “Sorry, too many clients already”.

Untuk setiap ujian yang dilakukan, kami menganalisa tingkah laku sambungan ini (berapa banyak sambungan yang masuk ke pangkalan data, berapa lama setiap sambungan dipegang dalam pangkalan data, dan apakah terjadi pada sambungan selepas pelanggan memutuskan sambungan). Dari analisa ini, kami mendapati bahawa selepas pelanggan memutuskan sambungan, sambungan akan berada dalam keadaan melahu dan tidak diputuskan (seperti apa yang sepatutnya mengikut parameter “connection_life_time” dalam pgpool, enam puluh saat selepas pelanggan memutuskan sambungan, sambungan cache pangkalan data tersebut sepatutnya diputuskan. Tetapi perkara ini tidak terjadi). Ini menyebabkan lambakan bilangan sambungan data dan dengan cepat tiada lagi sambungan yang tinggal dalam pangkalan data untuk melayani permintaan aplikasi.
Satu lagi pemerhatian yang didapati ialah terdapat terlalu banyak sambungan yang masuk ke pangkalan data dalam tempoh masa yang singkat yang menyebabkan peningkatan dalam bilangan sambungan serentak. Pada peringkat ini adalah penting untuk memahami nuansa sambungan serentak ini.

Apakah sebenarnya ‘sambungan serentak’?

Apabila sambungan dari aplikasi disambungkan ke pangkalan data melalui pgpool, terdapat 4 jenis keadaan sambungan,

1. aktif: Ini menunjukkan bahawa sambung tersebut adalah baik.
2. idle: Ini menunjukkan bahawa sambungan sedang melahu, dan kami harus menjejak sambungan ini berdasarkan pada tempoh masa ia telah melahu.
3. idle in transaction: Ini menunjukkan bahawa ia sedang dalam transaksi tetapi pada masa ini tidak melakukan apa-apa dan mungkin sedang menunggu input dari pengguna seperti transaksi “begin”
4. idle in transaction (aborted): Keadaan ini adalah sama seperti idle in transaction, kecuali satu daripada pernyataan dalam transaksi tersebut telah menyebabkan ralat. Ini juga perlu diperhatikan berdasarkan pada tempoh masa ia telah melahu.

Ingat, dalam kes ini, sambungan active state adalah penting kerana sambungan tersebut sedang berjalan dan menggunakan sumber-sumber yang menyebabkan peningkatan purata beban.

Penyelesaian untuk mencapai hasil yang diingini

Matlamat utama kami adalah untuk mencapai transaksi perniagaan yang diingini dan untuk mencapai matlamat ini, kami perlu meneliti cara untuk menambahbaik sambungan serentak.

Bantuan dari Komuniti!

Kami dapati terlalu banyak sambungan “idle” yang melahu lebih daripada beberapa saat yang tidak diperlukan dan untuk menangani ini, kami telah menetapkan parameter “connection_life_time”. Namun, apa yang telah kami perhatikan semasa beberapa kitaran Ujian Prestasi (PT), parameter ini tidak berfungsi seperti yang dimahukan.

Kami mengutarakan kebimbangan ini kepada komuniti Pgpool dan seperti yang dijangka dari komuniti ini, kami menerima respons pantas daripada salah seorang daripada komuniti yang telah mencuba senario yang sama. Selepas beberapa percubaan, kami menerima respons bahawa parameter connection_life_time tidak berfungsi jika serialize_accept didayakan. Komuniti dengan segera mengeluarkan satu patch bagi semua versi pgpool baru dan lama untuk membaiki masalah ini.

Kami bawakan patch ini pada EDB dan EDB dengan segera menghasilkan pembetulan dan mengeluarkan patch tersebut sebagai satu versi kecil baru pgpool. Kami pasangkan pgpool dengan pembetulan ini pada mesin pelanggan and mengujinya dengan beberapa sambungan dan terbukti berjaya! Isu ini selesai. Kami seterusnya melakukan Ujian Prestasi. Selepas menggunakan pembetulan ini, kami dapati bahawa sambungan cache diputuskan selepas enam puluh saat tidak digunakan dan ini mengurangkan tekanan pada pelayan pangkalan data.

Sejak itu, bagi pengguna pangkalan data utama, kami boleh lihat kurangnya penggunaan semula sambungan cache, kami kurangkan connection_life_time ke 30 saat dan pelayan pangkalan data dengan mudah boleh mengendali lebih banyak sambungan serentak pada pangkalan data. Untuk pengguna lain, kami dapati bahawa sambungan digunakan dalam masa 30 saat dan pengumpulan membantu dalam mengurangkan risiko membuat sambungan baru.

Juga, menala halus seni bina perkhidmatan mikro

Seperti yang telah disebut, terdapat beberapa sumber sambungan yang masuk ke pangkalan data termasuklah sambungan dari beberapa perkhidmatan mikro serta dari aliran data melalui kafka.

Dalam seni bina aplikasi perkhidmatan mikro di mana setiap API / aplikasi yang dijalankan dalam container menyambung ke pangkalan data melalui jdbc, adalah penting untuk menala sambungan ini. Ini adalah kerana tidak terdapat keadaan saiz sambungan aplikasi apabila anda menggunakan perkhidmatan mikro dalam container.

Mengambil kira perkara ini, pasukan aplikasi melakukan talaan pada beberapa parameter pada peringkat aplikasi untuk meminimakan bilangan sambungan ke pangkalan data tanpa menjejaskan prestasi yang diingini apabila memproses jumlah data yang sangat besar.

Rumusan

Dengan kombinasi pembetulan Postgres dan menata halus aplikasi, kami dapat lihat puncak sambungan serentak sebanyak 900-1,100 (yang mana jauh lebih rendah daripada 7,000 sambungan pada awal tadi) ke pangkalan data dan patch telah membantu kami untuk dengan mudah mengurus sambungan ini kerana ia tidak membenarkan sambungan idle untuk berada dalam pangkalan data selamanya jika ia tidak digunakan semula.

Dengan menggunakan pembetulan ini, kami dapati bahawa pelayan pangkalan data dapat mengendalikan sehingga 1,000+ sambungan serentak semasa beban puncak dan memberi kami prestasi yang kami telah jangkakan.

Dari segi transaksi perniagaan, setiap transaksi perniagaan adalah sekitar 30-35 pertanyaan yang masuk ke pangkalan data. Kami boleh mencapai ~ 150 transaksi perniagaan dengan 4,500-5,000 QPS (query per second). Ini adalah apa yang disasarkan oleh pasukan aplikasi ISV.

Ianya adalah satu pengalaman hebat untuk mencari punca pelbagai senario dengan porstgres dan saya amat kagum dengan prestasinya. Saya lebih kagum lagi dengan kepantasan sokongan komuniti! Ini adalah pengalaman sebenar semasa projek ini dengan kehebatan sumber terbuka.