Cassandra. Bagaimana tidak mati jika Anda hanya mengenal Oracle

Hei Habr.

Nama saya Misha Butrimov, saya ingin bercerita sedikit tentang Cassandra. Kisah saya akan berguna bagi mereka yang belum pernah menemukan database NoSQL - cerita ini memiliki banyak fitur implementasi dan kendala yang perlu Anda ketahui. Dan jika Anda belum pernah melihat apa pun selain Oracle atau database relasional lainnya, hal-hal ini akan menyelamatkan hidup Anda.

Apa bagusnya Cassandra? Ini adalah database NoSQL yang dirancang tanpa satu titik kegagalan pun dan dapat diskalakan dengan baik. Jika Anda perlu menambahkan beberapa terabyte untuk beberapa database, Anda cukup menambahkan node ke ring. Perluas ke pusat data lain? Tambahkan node ke cluster. Tingkatkan RPS yang diproses? Tambahkan node ke cluster. Ia juga bekerja dalam arah yang berlawanan.

Cassandra. Bagaimana tidak mati jika Anda hanya mengenal Oracle

Apa lagi yang dia kuasai? Ini tentang menangani banyak permintaan. Tapi berapa banyak? 10, 20, 30, 40 ribu permintaan per detik tidaklah banyak. 100 ribu permintaan per detik untuk merekam - juga. Ada perusahaan yang mengatakan mereka menyimpan 2 juta permintaan per detik. Mereka mungkin harus mempercayainya.

Dan pada prinsipnya, Cassandra memiliki satu perbedaan besar dari data relasional - data tersebut tidak mirip sama sekali. Dan ini sangat penting untuk diingat.

Tidak semua hal yang tampak sama berfungsi dengan cara yang sama

Suatu ketika seorang kolega mendatangi saya dan bertanya: “Ini adalah bahasa kueri CQL Cassandra, dan ia memiliki pernyataan pilih, ada di mana, ada dan. Saya menulis surat dan tidak berhasil. Mengapa?". Memperlakukan Cassandra seperti database relasional adalah cara sempurna untuk melakukan bunuh diri dengan kekerasan. Dan saya tidak mempromosikannya, itu dilarang di Rusia. Anda hanya akan merancang sesuatu yang salah.

Misalnya, seorang pelanggan mendatangi kami dan berkata: “Mari kita buat database untuk serial TV, atau database untuk direktori resep. Kami akan memiliki hidangan makanan di sana atau daftar serial TV dan aktor di dalamnya.” Kami berkata dengan gembira: “Ayo pergi!” Kirimkan saja dua byte, beberapa tanda dan selesai, semuanya akan bekerja dengan sangat cepat dan andal. Dan semuanya baik-baik saja sampai pelanggan datang dan mengatakan bahwa ibu rumah tangga juga memecahkan masalah sebaliknya: mereka memiliki daftar produk, dan mereka ingin tahu hidangan apa yang ingin mereka masak. Matilah Kau.

Hal ini karena Cassandra adalah database hibrid: ia secara bersamaan memberikan nilai kunci dan menyimpan data dalam kolom yang luas. Di Java atau Kotlin, bisa digambarkan seperti ini:

Map<RowKey, SortedMap<ColumnKey, ColumnValue>>

Artinya, peta yang juga berisi peta yang diurutkan. Kunci pertama pada peta ini adalah kunci Baris atau kunci Partisi - kunci partisi. Kunci kedua yang merupakan kunci peta yang sudah diurutkan adalah kunci Clustering.

Untuk mengilustrasikan distribusi database, mari kita menggambar tiga node. Sekarang Anda perlu memahami cara menguraikan data menjadi node. Karena kalau kita menjejalkan semuanya menjadi satu (omong-omong, bisa ada seribu, dua ribu, lima - sebanyak yang Anda suka), ini bukan soal distribusi. Oleh karena itu, diperlukan fungsi matematika yang dapat mengembalikan suatu bilangan. Hanya angka, int panjang yang akan berada dalam kisaran tertentu. Dan kita akan memiliki satu node yang bertanggung jawab untuk satu rentang, node kedua untuk rentang kedua, node ke-n untuk rentang ke-n.

Cassandra. Bagaimana tidak mati jika Anda hanya mengenal Oracle

Nomor ini diambil menggunakan fungsi hash, yang diterapkan pada apa yang kita sebut kunci Partisi. Ini adalah kolom yang ditentukan dalam direktif Kunci utama, dan ini adalah kolom yang akan menjadi kunci pertama dan paling dasar dari peta. Ini menentukan node mana yang akan menerima data mana. Sebuah tabel dibuat di Cassandra dengan sintaks yang hampir sama seperti di SQL:

CREATE TABLE users (
	user_id uu id,
	name text,
	year int,
	salary float,
	PRIMARY KEY(user_id)

)

Kunci utama dalam hal ini terdiri dari satu kolom, dan juga merupakan kunci partisi.

Bagaimana kinerja pengguna kami? Beberapa akan pergi ke satu node, beberapa ke node lain, dan beberapa ke node ketiga. Hasilnya adalah tabel hash biasa, juga dikenal sebagai peta, juga dikenal sebagai kamus dengan Python, atau struktur nilai Kunci sederhana yang darinya kita dapat membaca semua nilai, membaca dan menulis dengan kunci.

Cassandra. Bagaimana tidak mati jika Anda hanya mengenal Oracle

Pilih: kapan izinkan pemfilteran berubah menjadi pemindaian penuh, atau apa yang tidak boleh dilakukan

Mari kita tulis beberapa pernyataan pilihan: select * from users where, userid = . Ternyata seperti di Oracle: kita menulis pilih, tentukan kondisi dan semuanya berfungsi, pengguna mendapatkannya. Namun jika memilih, misalnya pengguna dengan tahun lahir tertentu, Cassandra mengeluh tidak bisa memenuhi permintaan tersebut. Karena dia tidak tahu apa-apa tentang bagaimana kami mendistribusikan data tentang tahun lahir - dia hanya memiliki satu kolom yang diindikasikan sebagai kunci. Lalu dia berkata, “Oke, saya masih bisa memenuhi permintaan ini. Tambahkan izinkan pemfilteran." Kami menambahkan arahan, semuanya berfungsi. Dan saat ini sesuatu yang buruk terjadi.

Saat kami menjalankan data pengujian, semuanya baik-baik saja. Dan ketika Anda menjalankan kueri dalam produksi, di mana kami memiliki, misalnya, 4 juta catatan, maka semuanya tidak baik bagi kami. Karena izinkan pemfilteran adalah arahan yang memungkinkan Cassandra mengumpulkan semua data dari tabel ini dari semua node, semua pusat data (jika ada banyak di cluster ini), dan baru kemudian memfilternya. Ini adalah analog dari Pemindaian Penuh, dan hampir tidak ada orang yang menyukainya.

Jika kami hanya membutuhkan pengguna berdasarkan ID, kami akan baik-baik saja dengan ini. Namun terkadang kita perlu menulis pertanyaan lain dan menerapkan batasan lain pada pilihan. Oleh karena itu, kita ingat: ini semua adalah peta yang memiliki kunci partisi, tetapi di dalamnya terdapat peta yang diurutkan.

Dan dia juga memiliki kunci yang kami sebut Kunci Clustering. Kunci ini, yang, pada gilirannya, terdiri dari kolom-kolom yang kita pilih, dengan bantuan Cassandra memahami bagaimana datanya diurutkan secara fisik dan akan ditempatkan di setiap node. Artinya, untuk beberapa kunci Partisi, kunci Clustering akan memberi tahu Anda cara memasukkan data ke dalam pohon ini, tempat apa yang akan diambilnya di sana.

Ini benar-benar sebuah pohon, komparator dipanggil di sana, yang mana kita meneruskan sekumpulan kolom tertentu dalam bentuk objek, dan itu juga ditentukan sebagai daftar kolom.

CREATE TABLE users_by_year_salary_id (
	user_id uuid,
	name text,
	year int,
	salary float,
	PRIMARY KEY((year), salary, user_id)

Perhatikan arahan kunci Primer; argumen pertamanya (dalam kasus kami, tahun) selalu merupakan kunci Partisi. Bisa terdiri dari satu kolom atau lebih, tidak masalah. Jika ada beberapa kolom, maka perlu dihilangkan lagi dalam tanda kurung agar praprosesor bahasa memahami bahwa ini adalah Primary key, dan di belakangnya semua kolom lainnya adalah Clustering key. Dalam hal ini, mereka akan ditransmisikan dalam pembanding sesuai urutan kemunculannya. Artinya, kolom pertama lebih signifikan, kolom kedua kurang signifikan, dan seterusnya. Cara kita menulis, misalnya, sama dengan bidang untuk kelas data: kita membuat daftar bidang, dan untuk bidang tersebut kita menulis bidang mana yang lebih besar dan mana yang lebih kecil. Di Cassandra, secara relatif, ini adalah bidang kelas data, yang akan diterapkan persamaan yang ditulis untuknya.

Kami menetapkan penyortiran dan menerapkan batasan

Perlu Anda ingat bahwa urutan pengurutan (menurun, menaik, apa pun) diatur pada saat yang sama ketika kunci dibuat, dan tidak dapat diubah nanti. Secara fisik menentukan bagaimana data akan diurutkan dan bagaimana data akan disimpan. Jika Anda perlu mengubah kunci Clustering atau urutan pengurutan, Anda harus membuat tabel baru dan mentransfer data ke dalamnya. Ini tidak akan berhasil dengan yang sudah ada.

Cassandra. Bagaimana tidak mati jika Anda hanya mengenal Oracle

Kami mengisi tabel kami dengan pengguna dan melihat bahwa mereka masuk ke dalam ring, pertama berdasarkan tahun lahir, dan kemudian di dalam setiap node berdasarkan gaji dan ID pengguna. Sekarang kita bisa memilih dengan menerapkan pembatasan.

Pekerjaan kami muncul lagi where, and, dan kami mendapatkan pengguna, dan semuanya baik-baik saja lagi. Tetapi jika kita mencoba menggunakan hanya sebagian dari kunci Clustering, dan yang kurang signifikan, maka Cassandra akan langsung mengeluh bahwa ia tidak dapat menemukan tempat di peta kita di mana objek ini, yang memiliki bidang-bidang ini untuk pembanding nol, dan yang ini itu baru saja diatur, - dimana dia berbohong. Saya harus mengambil kembali semua data dari node ini dan memfilternya. Dan ini analog dengan Pemindaian Penuh dalam sebuah node, ini buruk.

Jika ada situasi yang tidak jelas, buatlah tabel baru

Jika kita ingin dapat menargetkan pengguna berdasarkan ID, usia, atau gaji, apa yang harus kita lakukan? Tidak ada apa-apa. Cukup gunakan dua tabel. Jika Anda perlu menjangkau pengguna dengan tiga cara berbeda, akan ada tiga tabel. Lewatlah sudah hari-hari ketika kita menghemat ruang pada sekrup. Ini adalah sumber daya termurah. Biayanya jauh lebih sedikit dibandingkan waktu respons, yang dapat merugikan pengguna. Jauh lebih menyenangkan bagi pengguna untuk menerima sesuatu dalam hitungan detik daripada dalam 10 menit.

Kami menukar ruang yang tidak perlu dan mendenormalisasi data demi kemampuan untuk melakukan penskalaan dengan baik dan beroperasi dengan andal. Faktanya, sebuah cluster yang terdiri dari tiga pusat data, yang masing-masing memiliki lima node, dengan tingkat pelestarian data yang dapat diterima (bila tidak ada yang hilang), mampu bertahan sepenuhnya jika satu pusat data mati. Dan dua node lagi di masing-masing dua node sisanya. Dan baru setelah itu masalahnya dimulai. Ini adalah redundansi yang cukup bagus, ini sepadan dengan beberapa drive dan prosesor SSD tambahan. Oleh karena itu, untuk menggunakan Cassandra, yang tidak pernah merupakan SQL, yang tidak memiliki hubungan, kunci asing, Anda perlu mengetahui aturan sederhana.

Kami merancang semuanya sesuai permintaan Anda. Hal utama bukanlah datanya, tetapi bagaimana aplikasi akan bekerja dengannya. Jika perlu menerima data berbeda dengan cara berbeda atau data yang sama dengan cara berbeda, kita harus mengaturnya dengan cara yang nyaman untuk aplikasi. Jika tidak, kami akan gagal dalam Pemindaian Penuh dan Cassandra tidak akan memberi kami keuntungan apa pun.

Mendenormalisasi data adalah hal yang biasa. Kami melupakan formulir normal, kami tidak lagi memiliki database relasional. Jika kita meletakkan sesuatu 100 kali, maka benda itu akan tergeletak 100 kali. Itu masih lebih murah daripada berhenti.

Kami memilih kunci untuk mempartisi agar didistribusikan secara normal. Kami tidak ingin hash kunci kami berada dalam satu rentang yang sempit. Artinya, tahun lahir pada contoh di atas adalah contoh yang buruk. Lebih tepatnya, baik jika pengguna kita terdistribusi secara normal berdasarkan tahun lahir, dan buruk jika kita berbicara tentang siswa kelas 5 - partisi di sana tidak akan terlalu baik.

Penyortiran dipilih satu kali pada tahap pembuatan Kunci Clustering. Jika perlu diubah, kita harus memperbarui tabel kita dengan kunci yang berbeda.

Dan yang paling penting: jika kita perlu mengambil data yang sama dengan 100 cara berbeda, maka kita akan memiliki 100 tabel berbeda.

Sumber: www.habr.com

Tambah komentar