Menghapus data dari database shardable

Artikel tentang cara mengatasi masalah mengoptimalkan proses menghapus file dari sistem yang terbengkalai. Ini tentang proyek untuk berbagi dan bekerja dengan file. Sistem itu startup sekitar 8 tahun yang lalu, kemudian berhasil menembak dan dijual beberapa kali. Proyek ini memiliki 4 pengembang yang bersama dengan proyek dari awal, yang sangat berharga. Dokumentasi, secara tradisional, tidak punya waktu untuk menulis, atau tidak terlalu relevan.

Mengapa Anda membaca ini dan mengapa saya menulis semua ini? Saya ingin berbicara tentang garu yang dengan hati-hati terletak di dalam sistem dan memukul sehingga bintang-bintang keluar dari mata.

Saya ingin mengucapkan terima kasih banyak kepada Hanna_Hlushakova untuk bekerja bersama, membawa proyek sampai akhir dan membantu dalam mempersiapkan artikel. Pada dasarnya, Anda akan menemukan deskripsi masalah dan algoritma untuk menyelesaikannya, yang kami gunakan, tidak ada contoh kode, struktur data, atau hal-hal lain yang diperlukan. Saya tidak tahu apakah pengalaman saya akan membantu Anda menghindari menyapu di rumah, tetapi saya harap Anda mendapatkan sesuatu yang bermanfaat. Mungkin artikel ini akan benar-benar kehilangan waktu berharga yang tidak dapat dibatalkan.



Tentang proyek


Proyek ini adalah salah satu pemimpin di lapangan Gartner, memiliki perusahaan klien dengan lebih dari 300 ribu karyawan di AS dan Eropa, dan beberapa miliar file untuk pemeliharaan.

Teknologi berikut digunakan dalam proyek: Microsoft, C # .net server, database MS SQL, 14 server aktif + 14 dalam mode mirroring data.

Volume database hingga 4 Tb, beban konstan dalam jam kerja adalah sekitar 400 ribu permintaan per menit.

Ada banyak logika bisnis dalam database:
450 meja
1000 prosedur tersimpan
80.000 baris kode SQL
Secara tradisional, mereka tidak punya waktu untuk menulis dokumentasi, atau tidak relevan.

Tentang tugas


Tugasnya adalah untuk menghapus penghapusan file dari penyimpanan yang sudah dihapus oleh klien, dan periode penyimpanan file yang dihapus telah kedaluwarsa, jika mereka ingin dikembalikan. Dalam versi saat ini, menurut perhitungan perusahaan itu sendiri, file yang dihapus 1 tahun yang lalu disimpan di server, meskipun menurut ketentuan bisnis mereka seharusnya disimpan hanya 1 bulan. Karena beberapa file disimpan pada S3, perusahaan membayar untuk data tambahan, dan pelanggan yang menggunakan penyimpanan On-Premises bertanya-tanya mengapa file mengambil lebih banyak ruang daripada yang seharusnya.

Database shardovany untuk klien perusahaan.

Bagaimana cara kerja penghapusan sebelumnya?





Pada server global dengan informasi tentang semua file dalam sistem, rentang 15 ribu pengidentifikasi file terbentuk.

Kemudian, sesuai dengan jadwal, survei server diluncurkan untuk berbagai pengidentifikasi file.
Batas-batas rentang ditransmisikan ke setiap beling.

Shard sebagai respons mengirim file yang ditemukan dari jangkauan.

Server utama menambahkan file yang hilang ke tabel antrian untuk dihapus dalam database-nya.
Kemudian, dari tabel antrian, layanan penghapusan file fisik dari penyimpanan menerima banyak pengidentifikasi untuk dihapus, setelah itu mengirim konfirmasi bahwa itu akan menghapus file dan cek dimulai untuk semua pecahan apakah file-file ini digunakan di sana.
Dengan peningkatan jumlah file, pendekatan ini mulai bekerja sangat lambat, karena ada beberapa miliar file, dan jumlah rentang meningkat secara signifikan. File yang dihapus masih kurang dari 5% dibandingkan dengan jumlah total, masing-masing, sangat tidak efisien untuk menyortir miliaran file untuk menemukan beberapa juta file yang dihapus.

Misalnya, biasanya setelah pengguna menghapus file, itu harus disimpan selama 1 bulan, jika perlu dipulihkan. Setelah periode ini, file harus dihapus oleh program dari repositori. Dengan jumlah file saat ini, jumlah rentang dan kecepatan bypass rentang, akan membutuhkan waktu 1 tahun bagi server untuk sepenuhnya memotong semua rentang.
Jelas bahwa tempat itu tidak dibebaskan, dan ini menyebabkan ketidakpuasan pengguna, karena server mereka menyimpan file berkali-kali lebih banyak daripada yang seharusnya dilaporkan. Perusahaan jasa itu sendiri membayar tempat tambahan pada S3, yang merupakan kerugian langsung untuk itu.

Hanya pada S3 saat pekerjaan dimulai, 2 Petabyte file yang dihapus disimpan, dan ini hanya di cloud. Selain itu, ada klien yang file-nya disimpan di server khusus mereka, yang memiliki masalah yang sama: ruang server ditempati oleh file yang dihapus oleh pengguna tetapi tidak dihapus dari server.

Apa yang Anda putuskan untuk lakukan?


Kami memutuskan untuk melacak peristiwa penghapusan:

  • klien menghapus file dan kemudian kedaluwarsa.
  • pengguna langsung menghapus file tanpa kemungkinan pemulihan.

Saat menghapus file dari database yang terbengkalai, kami memutuskan untuk menggunakan pendekatan optimis dan menghapus salah satu pemeriksaan untuk digunakan. Kami tahu bahwa 99% file hanya digunakan dalam satu shard. Kami memutuskan untuk segera menambahkan file ke antrean penghapusan, dan jangan memeriksa sisa pecahan untuk penggunaan file ini, karena pemeriksaan akan dilakukan lagi ketika penghapusan dari toko mengkonfirmasi layanan.

Selain itu, mereka meninggalkan PEKERJAAN saat ini yang memeriksa file yang dihapus oleh rentang untuk menambahkan file yang dihapus sebelum rilis versi baru.

Segala sesuatu yang dihapus pada beling dikumpulkan dalam sebuah tabel dan kemudian ditransfer ke server tunggal, dengan informasi tentang semua file.

Di server ini, ia dikirim ke tabel antrian hapus.

Dalam tabel untuk dihapus sebelum dihapus, diperiksa bahwa file tersebut tidak digunakan pada semua pecahan. Bagian cek ini ada di sini sebelum kode diubah, dan mereka memutuskan untuk tidak menyentuhnya.

Apa yang perlu Anda ubah dalam kode?


Pada masing-masing pecahan, sebuah tabel ditambahkan ke mana pengidentifikasi file yang dihapus harus ditulis.

Kami menemukan semua prosedur untuk menghapus file dari database, hanya ada 2. Setelah pengguna menghapus file, file tersebut masih berada di database untuk beberapa waktu.

Dalam prosedur untuk menghapus file dari database, kami menambahkan entri ke tabel lokal ini dengan file yang dihapus.

Di server global dengan file, mereka membuat PEKERJAAN yang mengunduh daftar file dari database shard. Hanya dengan memanggil prosedur dari basis data shardable, itu membuat DELETE di dalam dan menampilkan daftar file dalam OUTPUT. Dalam MS SQL Server tarik - tarik dari server jauh lebih cepat daripada memasukkan ke server jauh. Semua ini dilakukan dalam blok.
File-file ini kemudian ditambahkan ke tabel antrian hapus di server global.
Tabel dengan pengidentifikasi shard ditambahkan ke tabel antrian untuk mengetahui dari mana datangnya acara hapus.

Bagaimana semua orang mengujinya?


Ada 3 lingkungan:

Dev adalah lingkungan pengembangan. Kode diambil dari cabang pengembangan gith. Dimungkinkan untuk menggunakan versi kode yang berbeda pada IIS dan membuat beberapa versi orkestrasi. Ini akan terhubung ke lingkungan dev dari klien di dalam vpn. Sampai saat ini, ketidaknyamanan itu hanya dengan database, karena semua perubahan pada database dapat merusak pekerjaan bagian lain dari sistem. Kemudian basis dibuat lokal. Kode yang sudah berjalan dapat dituangkan ke server dev dengan basis data agar tidak merusak pekerjaan semua orang. Pada lingkungan dev, ada 3 pecahan, bukannya 12, yang ada di prod, tetapi ini biasanya cukup untuk menguji interaksi.

Pementasan - lingkungannya sama dengan prod menurut versi kode (hampir sama, karena jarang, tetapi ada perubahan langsung pada prod oleh administrator). Salinan kode dari cabang master. Terkadang beberapa perbedaan dengan kode pada prod tertangkap dalam database, tetapi secara umum keduanya identik. Ada juga 3 pecahan pada Pementasan serta pada gadis. Tidak ada beban pada pementasan maupun pada dev. Di sini Anda dapat menjalankan tes integrasi sepenuhnya, karena kode cocok dengan prod. Semua tes harus lulus, ini adalah prasyarat sebelum pergi ke penempatan.

Perf lab, tempat pengujian dilakukan di bawah beban. Beban dibuat menggunakan jmeter, 10 kali lebih sedikit dari pada prod, dan hanya ada satu beling, yang terkadang menciptakan ketidaknyamanan. Data penjualan diambil, kemudian dianonimkan dan digunakan di laboratorium perf. Semua server dengan konfigurasi yang sama seperti pada prod.

Bebannya 10 kali lebih sedikit, karena diasumsikan bahwa ini adalah perkiraan beban yang datang ke prod untuk 1 shard. Kelemahannya adalah bahwa basis global sangat kurang dimanfaatkan, tidak seperti penjualan. Dan, jika perubahan terutama menyangkut basis data global dengan file, maka Anda dapat mengandalkan hanya pada hasil tes - pada prod ini mungkin tidak berfungsi seperti itu. Meskipun perf lab tidak sesuai dengan beban dengan prod, kemampuan untuk menguji di bawah beban sudah membantu untuk menangkap banyak kesalahan sebelum disebarkan ke prod.

Ada juga server cadangan di mana Anda dapat melihat data dari penjualan untuk menangkap beberapa kasus. Secara umum, perusahaan beroperasi di bawah lisensi yang melarang pengembang memberikan akses ke data penjualan, dan akses administrasi dan tim dukungan (Operasi), sehingga Anda perlu meminta bantuan administrator database. Data penjualan membuat pengujian sangat mudah, karena beberapa kasus hanya muncul pada data prod dan sangat berguna untuk mempelajari data dalam sistem nyata untuk memahami cara kerja sistem bagi pengguna.

Selama tes di laboratorium perf, ternyata beban menghapus file dari penyimpanan tidak disadari dari kata sama sekali. Saat menerapkan pengujian beban, kami memilih permintaan yang lebih populer dari perangkat lunak klien, beberapa di antaranya tidak dimasukkan dalam pembersihan penyimpanan. Karena ini adalah basis data, ternyata melakukan pengujian yang disederhanakan untuk semua objek yang diubah dengan panggilan prosedur yang diubah pada data yang berbeda secara manual. (pada opsi yang saya tahu).
Selain itu, dalam tes integrasi dan perf, penekanan utama ditempatkan pada jenis penyimpanan file yang paling populer.

Fitur tambahan dari lab perf, yang tidak segera ditemukan, adalah ketidakcocokan jumlah data dalam beberapa tabel pada prod dan perf. Dalam arti bahwa semua PEKERJAAN penjualan bekerja pada perf, yang menghasilkan data, tetapi tidak selalu ada sesuatu yang memproses data yang dihasilkan dalam tabel. Dan, misalnya, tabel-antrian untuk penghapusan pada perf jauh lebih besar daripada pada prod - 20 juta rekaman pada perf dan 200 ribu rekaman pada pro

Proses penyebaran


Proses penyebaran cukup standar. Tidak ada perubahan dalam kode aplikasi untuk tugas ini, semua perubahan hanya ada di database. DBA selalu dimasukkan ke dalam basis data, proses ini tidak otomatis. 2 versi skrip disiapkan - untuk menerapkan perubahan dan untuk mengembalikan perubahan, dan instruksi untuk DBA ditulis. 2 versi skrip selalu dibuat, dan mereka harus diuji untuk rollback dan rollback perubahan. Dan skrip yang sama ini digunakan untuk menerapkan perubahan pada laboratorium pementasan dan kinerja sebelum meluncurkan pengujian integrasi dan pemuatan.

Apa yang terjadi setelah penempatan?


Dalam 5 jam pertama setelah penyebaran, 1 juta peristiwa datang bahwa perangkat lunak klien menerima kesalahan saat mencoba mengunduh file. Acara "file rusak". Ini berarti bahwa klien sedang mencoba mengunduh file, tetapi file itu tidak ditemukan di repositori. Biasanya peristiwa ini tidak sama sekali, atau mereka diukur dengan 1 - 2 ribu per hari.

Saya harus mengatakan segera bahwa diperlukan setidaknya 1 minggu untuk menemukan penyebab kegagalan pada tim yang terdiri dari 3 orang dan kadang-kadang 5 orang (termasuk saya).

Kami mengumpulkan seluruh daftar file tempat acara "File Corrupted" datang.

Terlepas dari kenyataan bahwa ada lebih dari 1 juta peristiwa dan semuanya berasal dari pengguna yang berbeda, perusahaan yang berbeda, hanya ada 250 file unik dalam daftar ini.

DBA pada server cadangan dinaikkan untuk menyelidiki cadangan database pada saat kejadian tiba. Ada beberapa tabel di pangkalan proyek dengan semua jenis log yang membantu dalam analisis. Bahkan ketika menghapus informasi dari database, log ditambahkan ke apa yang telah dihapus dan oleh peristiwa apa. Pada prod, catatan tersebut disimpan selama 1 minggu, kemudian digabungkan ke server arsip.

Demikian juga tabel dengan log yang banyak membantu dalam menganalisis apa yang terjadi:
Log lengkap dengan acara klien disimpan di setiap beling

Di server global:

  • Log permintaan untuk mengunduh semua file oleh pengguna
  • Log mengunggah file ke sistem dari pengguna
  • Log peristiwa FileCorrupt
  • Log file untuk membatalkan penghapusan dari penyimpanan
  • Log file yang dihapus dari database

Selain itu, ELK dengan log aplikasi juga tersedia.

Kami berhasil mengulangi kesalahan pada lingkungan dev, yang mengkonfirmasi kebenaran asumsi tersebut. Pada awalnya, tidak ada yang menganggap hipotesis ini serius, karena sangat sulit untuk percaya bahwa begitu banyak faktor bertepatan pada waktu yang sama dan begitu banyak pengguna yang datang pada waktu khusus ini.

Apa yang salah?


Ternyata sistem tersebut memiliki sekitar 250 (untuk perbandingan, miliaran file dalam sistem) file super mega duper super. 250 ya!

File-file ini masih sangat tua. Pada saat file-file ini diunggah ke sistem, sistem lain untuk menghasilkan kunci file ke penyimpanan digunakan.

Ternyata untuk jenis kunci ini, metode penghapusan fisik dari penyimpanan fisik berperilaku berbeda dari file lain.

Di kelas dengan penghapusan, ada blok kode dengan kondisi khusus untuk file dengan kunci lama. Sistem, pada saat penghapusan, sebelum diperiksa bahwa file tidak ada di pecahan, memindahkan file lama ini ke lokasi lain. Yah, itu tidak berhasil.

Dan ternyata pada saat file dipindahkan (dan saya akan mengingatkannya sangat populer), jika salah satu pengguna mencoba memberinya hak pengguna baru, perangkat lunak klien pergi ke penyimpanan untuk file ini, tetapi file tersebut tidak berada di tempat yang tepat. Sejak dipindahkan, jadi tidak berhasil. Dan perangkat lunak klien mengirim pesan bahwa file tersebut rusak. Dalam database, itu ditandai sebagai rusak. Dan semua informasi dihapus dari database (well, hampir semua).

Sementara itu, rutin pemeriksaan beling kami menemukan bahwa file tersebut sedang digunakan. Dan mengirimkan respons yang Anda perlukan untuk mengembalikannya. Tetapi semua info sudah dihapus dari database, dan tidak mungkin mengembalikannya.

Lucu ya

Yaitu, ketika file dihapus, pengguna berada dalam periode waktu ketika file dipindahkan, pecahan diperiksa, dan pada saat itulah pengguna mengirim permintaan untuk mengunduh.

Ini dia - mainkan dalam aksi, saat pertandingan paling luar biasa yang cocok dengan Anda.



Setelah pulih dari keterkejutan dan mengembalikan semuanya, kami memastikan bahwa file dari pengguna masih hidup, karena dipulihkan dari disk klien lain.

Secara alami, semuanya baik-baik saja dalam pengujian, karena selama pengujian file yang lebih baru dihapus dengan tipe kunci baru yang digunakan dalam 5 tahun terakhir. File tersebut tidak ditransfer ke lokasi penyimpanan lain untuk waktu penghapusan.

Optimisme kami berkurang, dan kami memutuskan untuk tidak mengambil jalan yang paling optimis.

Retrospektif


Kami memutuskan bahwa kami perlu menambahkan tes untuk berbagai jenis penyimpanan
Tambahkan beban ke laboratorium perf yang menggunakan panggilan saat dihapus dari penyimpanan
Tutup kondisi lomba yang terkenal
Tambahkan pemantauan (meskipun akan ada dalam rencana, tetapi tidak sesuai dengan ruang lingkup asli)

Tentang pemantauan


Mereka memutuskan untuk melakukan pemantauan segera, tetapi kemudian dia menghilang ke latar belakang, karena itu perlu untuk digunakan lebih cepat.

Untuk pemantauan, proyek menggunakan Zabbix, ELK, Grafana, NewRelic, SQL Sentry dan versi uji AppDynamics.

Dari jumlah ini, pada laboratorium pef adalah NewRelic dan SQL Sentry.

Kami sudah mengukur semua metrik sistem dan karenanya, kami ingin mengukur metrik bisnis. Saya memiliki pengalaman mengatur pemantauan melalui Zabbix - kami memutuskan untuk melakukan hal yang sama.

Skema ini sangat sederhana dalam database untuk membuat tabel untuk mengumpulkan metrik yang diperlukan oleh JOB dan prosedur yang akan mengunggah metrik yang dikumpulkan ke Zabbix.

Metrik:

  • Jumlah file dalam antrian untuk dihapus secara global
  • Jumlah file yang antri oleh server
  • Jumlah file yang dikirim ke program uninstall dari repositori
  • Jumlah file yang dihapus
  • Jumlah Acara FileCorrupt
  • Jumlah file yang akan dihapus pada setiap pecahan

Pemantauan dilaksanakan dan disebarkan ke prod secara terpisah, sebelum mereka mulai menerapkan implementasi penghapusan baru.

Solusi baru


Secara umum, kami memutuskan bahwa makan lebih baik daripada tidak tidur, dan membuat rencana baru.

  1. periksa beling yang sama yang tidak ada lagi yang menggunakan file itu, dan hanya transfer file yang tidak digunakan ke server;
  2. ketika mentransfer ke server, kumpulkan semua file dalam tabel dan verifikasi bahwa file tidak digunakan pada pecahan sebelum ditempatkan di tabel antrian dequeue;
  3. saat menggunakan file dan mencarinya di sistem, tandai antrian dequeue di tabel sebagai file yang membutuhkan verifikasi;
  4. kembalikan hanya file yang tidak ada pencarian;
  5. file yang dicari, periksa kembali pecahan;
  6. secara umum, hapus centang pada prosedur yang menghapus file, karena harus bekerja dengan cepat - dan file yang digunakan seharusnya tidak mencapainya secara prinsip;
  7. memperhitungkan dalam prosedur bahwa semuanya terhapus oleh file yang dipukul itu dalam proses penghapusan, dan tidak menghapus informasi tentang itu.

Poin 6 selama penyebaran termasuk penghapusan cek dalam beberapa tahap. Pertama, mereka meninggalkan cek, lalu seminggu kemudian cek pada file karyawan perusahaan dimatikan, setelah 2 minggu, cek dimatikan sepenuhnya.

Apa yang perlu Anda ubah dalam kode?


Sekali lagi, semua perubahan hanya berlaku untuk database.

Skala perubahan adalah yang terbesar di server global:
Tambahkan tabel perantara untuk menambahkan semua file yang diunduh dari pecahan.
Buat PEKERJAAN yang memeriksa file pada tabel perantara yang tidak digunakan pada pecahan.

Dalam antrian file yang dihapus, tambahkan bidang dengan tanggal file terakhir diakses dan tambahkan indeks.

Temukan semua prosedur dengan akses ke file - ternyata 5 prosedur. Tambahkan ke mereka satu blok mengubah tanggal penggunaan terakhir dalam tabel antrian. Tanggal berubah setiap saat, terlepas dari apakah itu diisi atau tidak.

Tambahkan program penghapusan ke prosedur penerbitan file sehingga hanya menampilkan file dengan tanggal penggunaan kosong.

JOB, ( 10 , , , 2 , ) . , , . , , , .

:

, , . — DELETE output NOT EXISTS.

JOB, .

Tes


.
, .

Perf Lab . .


. DBA , - . , .

- JOB , , .


.
, , .

S3 2 . , , .

- , , - .

Source: https://habr.com/ru/post/id427895/


All Articles