Kami mengalami masalah dalam menangani lalu lintas selama jam sibuk ke server database kami. Kami sedang mencari cara untuk meningkatkan perangkat keras (lihat pertanyaan ini tentang sisi itu ) tetapi kami juga ingin bekerja pada konfigurasi penyatuan dan penyetelan server.
Aplikasi yang sedang kami kerjakan adalah game multiplayer berbasis giliran untuk smartphone, di mana backend terdiri dari Rails dengan unicorn dan PostgreSQL 9.1 sebagai databasenya. Saat ini kami memiliki 600.000 pengguna terdaftar dan karena status permainan disimpan dalam database, beberapa ribu penulisan dilakukan setiap beberapa detik. Kami telah menganalisis file log dari PostgreSQL menggunakan PgBadger dan selama jam-jam kritis kami mendapatkan banyak
FATAL: remaining connection slots are reserved for non-replication superuser connections
Solusi naif untuk mengatasi masalah ini adalah dengan meningkatkan max_connections (yang saat ini 100) di postgresql.conf . Saya telah membaca http://wiki.postgresql.org/wiki/Number_Of_Database_Connections yang menunjukkan bahwa ini mungkin bukan hal yang tepat untuk dilakukan. Dalam artikel tersebut disebut mencari sweet spot antara max_connections dan ukuran kumpulan .
Apa yang bisa dilakukan untuk menemukan sweet spot ini? Apakah ada alat yang bagus untuk mengukur kinerja I / O untuk nilai berbeda dari max_connections dan ukuran kumpulan ?
Pengaturan kami saat ini adalah 4 server permainan, masing-masing memiliki 16 pekerja unicorn dan ukuran kumpulan 5.
Berikut adalah pengaturan postgres non-standar yang kami gunakan:
version | PostgreSQL 9.1.5 on x86_64-unknown-linux-gnu,compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit
checkpoint_completion_target | 0.9
checkpoint_segments | 60
checkpoint_timeout | 6min
client_encoding | UTF8
effective_cache_size | 2GB
lc_collate | en_US.UTF-8
lc_ctype | en_US.UTF-8
log_destination | csvlog
log_directory | pg_log
log_filename | postgresql-%Y-%m-%d_%H%M%S.log
log_line_prefix | %t
log_min_duration_statement | 200ms
log_rotation_age | 1d
log_rotation_size | 10MB
logging_collector | on
max_connections | 100
max_stack_depth | 2MB
server_encoding | UTF8
shared_buffers | 1GB
ssl | on
TimeZone | localtime
wal_buffers | 16MB
work_mem | 8MB
sumber
synchronous_commit = off
ataucommit_delay
?INSERT
s? Seperti apa skema Anda - apakah dipartisi? Apaexplain analyze
beberapa pertanyaan sampel? Seberapa sering pos pemeriksaan Anda dan berapa lama waktu yang dibutuhkan? (lihat opsi pencatatan pos pemeriksaan). Dan serius, apa versi PostgreSQL Anda ? (Pembaruan: Tampaknya Anda mencantumkan perangkat keras di sini: dba.stackexchange.com/questions/28061/… )synchronous_commit = off
Jawaban:
Jawaban singkat di sini adalah "percobaan dan kesalahan yang dipandu oleh metrik pemantauan dan kinerja".
Ada beberapa aturan umum yang dapat membantu Anda menemukan area samar yang harus Anda mulai, tetapi mereka sangat umum. Pedoman umum "jumlah CPU plus jumlah disk yang independen" sering dikutip, tetapi ini hanyalah titik awal yang sangat kasar.
Yang benar-benar perlu Anda lakukan adalah mendapatkan metrik kinerja yang kuat untuk aplikasi Anda. Mulai merekam statistik.
Tidak banyak cara untuk mengintegrasikan alat untuk ini. Ada beberapa hal seperti
check_postgres
skrip nagios , pencatatan konter kinerja sistem Cacti, pengumpul statistik PostgreSQL, dll ... tetapi tidak banyak yang menyatukan semuanya. Sayangnya, Anda harus melakukannya sendiri. Untuk sisi PostgreSQL, lihat pemantauan di manual PostgreSQL. Ada beberapa opsi pihak ketiga, seperti Postgres Enterprise Monitor EnterpriseDB .Untuk metrik tingkat aplikasi yang disebutkan di sini, Anda ingin merekamnya dalam struktur data bersama atau dalam DB eksternal yang tidak tahan lama seperti Redis dan menggabungkannya baik saat Anda merekamnya atau sebelum Anda menulisnya ke PostgreSQL DB Anda. Mencoba masuk langsung ke Pg akan mendistorsi pengukuran Anda dengan overhead yang dibuat dengan mencatat pengukuran dan memperburuk masalah.
Opsi paling sederhana mungkin adalah singleton di setiap server aplikasi yang Anda gunakan untuk merekam statistik aplikasi. Anda mungkin ingin terus memperbarui min, maks, n, total, dan rata-rata; dengan begitu Anda tidak perlu menyimpan setiap titik stat, hanya agregat. Singleton ini dapat menulis statistik agregatnya ke Pg setiap x menit, tingkat yang cukup rendah sehingga dampak kinerja akan minimal.
Dimulai dari:
Apa latensi permintaan? Dengan kata lain, berapa lama waktu yang dibutuhkan aplikasi dari menerima permintaan dari klien hingga menanggapi klien. Catat ini secara agregat selama periode waktu tertentu, bukan sebagai catatan individual. Kelompokkan menurut jenis permintaan; katakan, demi halaman.
Apa penundaan akses basis data untuk setiap permintaan atau jenis permintaan yang dijalankan aplikasi? Berapa lama dari meminta informasi / menyimpan informasi sampai DB selesai dan dapat melanjutkan ke tugas berikutnya? Sekali lagi, gabungkan statistik ini dalam aplikasi dan hanya tuliskan informasi agregat ke DB.
Seperti apa throughput Anda? Dalam setiap x menit tertentu, berapa banyak kueri dari setiap kelas utama yang dijalankan aplikasi Anda dilayani oleh DB?
Untuk rentang waktu yang sama yaitu x menit, ada berapa banyak permintaan klien?
Menyampling setiap beberapa detik dan menjumlahkan melalui windows x menit yang sama dalam DB, berapa banyak koneksi DB yang ada? Berapa banyak dari mereka yang menganggur? Berapa banyak yang aktif? Di sisipan? Pembaruan? memilih? menghapus? Berapa banyak transaksi yang terjadi selama periode itu? Lihat dokumentasi pengumpul statistik
Sekali lagi mengambil sampel dan menggabungkan dalam interval waktu yang sama, seperti apa metrik kinerja sistem host? Berapa banyak membaca dan berapa banyak menulis disk IOs / detik? Megabita per detik disk membaca dan menulis? Pemanfaatan CPU? Rata-rata beban? Penggunaan RAM?
Anda sekarang dapat mulai belajar tentang kinerja aplikasi Anda dengan mengkorelasikan data, membuat grafik, dll. Anda akan mulai melihat pola, mulai menemukan kemacetan.
Anda mungkin mengetahui bahwa sistem Anda macet
INSERT
danUPDATE
s pada tingkat transaksi yang tinggi, meskipun I / O disk yang cukup rendah dalam megabyte per detik. Ini akan menjadi petunjuk bahwa Anda perlu meningkatkan kinerja flush disk Anda dengan pengontrol caching RAID write-back yang didukung baterai atau beberapa SSD yang dilindungi oleh daya berkualitas tinggi. Anda juga dapat menggunakansynchronous_commit = off
jika OK untuk kehilangan beberapa transaksi pada server crash, dan / atau acommit_delay
, untuk mengambil beberapa beban sinkronisasi.Ketika Anda membuat grafik transaksi Anda per detik terhadap jumlah koneksi bersamaan dan mengoreksi untuk berbagai tingkat permintaan aplikasi melihat, Anda akan bisa mendapatkan ide yang lebih baik di mana sweet spot throughput Anda berada.
Jika Anda tidak memiliki penyimpanan pembilasan cepat (BBU RAID atau SSD tahan lama), Anda tidak akan menginginkan lebih dari sejumlah kecil koneksi yang aktif menulis, mungkin paling banyak 2x jumlah disk yang Anda miliki, mungkin lebih sedikit tergantung pada pengaturan RAID , kinerja disk, dll. Dalam hal ini bahkan tidak layak coba-coba; cukup tingkatkan subsistem penyimpanan Anda menjadi satu dengan flush disk cepat .
Lihat
pg_test_fsync
alat yang akan membantu Anda menentukan apakah ini masalah bagi Anda. Sebagian besar paket PostgreSQL menginstal alat ini sebagai bagian dari contrib, jadi Anda tidak perlu mengkompilasinya. Jika Anda mendapatkan kurang dari beberapa ribu ops / detik,pg_test_fsync
Anda harus segera meningkatkan sistem penyimpanan Anda. Laptop saya yang dilengkapi SSD mendapat 5000-7000. Workstation saya bekerja dengan array RAID 10-disk 4 disk dengan disk 7200rpm SATA dan write-through (non-write-caching) mendapat sekitar 80 ops / detikf_datasync
, turun hingga 20 ops / detik untukfsync()
; itu ratusan kali lebih lambat . Bandingkan: laptop dengan ssd vs workstation dengan RAID 10 ( write-through -caching). SSD laptop ini murah dan saya tidak percaya untuk menghapus cache tulisnya pada kehilangan daya; Saya menyimpan cadangan yang baik dan tidak akan menggunakannya untuk data yang saya pedulikan. SSD berkualitas baik berkinerja baik jika tidak lebih baik dan tahan lama.Dalam hal aplikasi Anda, saya sangat menyarankan Anda untuk melihat ke dalam:
UNLOGGED
tabel untuk data yang Anda bisa kehilangan. Gabungkan secara berkala ke dalam tabel yang dicatat. Misalnya, pertahankan game-in-progress dalam tabel yang tidak dicatat, dan tulis skornya ke tabel awet biasa.commit_delay
(kurang berguna dengan penyimpanan pembilasan cepat - petunjuk)synchronous_commit
transaksi yang Anda sanggup kehilangan (kurang berguna dengan penyimpanan yang cepat - petunjuk)LISTEN
danNOTIFY
untuk melakukan pembatalan cache menggunakan pemicu pada tabel PostgreSQL.Jika ragu: http://www.postgresql.org/support/professional_support/
sumber