NewSQL = NoSQL+ACID

NewSQL = NoSQL+ACID
Sehingga baru-baru ini, Odnoklassniki menyimpan kira-kira 50 TB data yang diproses dalam masa nyata dalam SQL Server. Untuk volum sedemikian, hampir mustahil untuk menyediakan akses yang cepat dan boleh dipercayai, malah pusat data yang toleran kegagalan menggunakan SQL DBMS. Biasanya, dalam kes sedemikian, salah satu storan NoSQL digunakan, tetapi tidak semuanya boleh dipindahkan ke NoSQL: sesetengah entiti memerlukan jaminan transaksi ACID.

Ini membawa kami kepada penggunaan storan NewSQL, iaitu, DBMS yang menyediakan toleransi kesalahan, skalabiliti dan prestasi sistem NoSQL, tetapi pada masa yang sama mengekalkan jaminan ACID yang biasa kepada sistem klasik. Terdapat beberapa sistem perindustrian yang berfungsi kelas baharu ini, jadi kami sendiri melaksanakan sistem sedemikian dan memasukkannya ke dalam operasi komersial.

Bagaimana ia berfungsi dan apa yang berlaku - baca di bawah potongan.

Hari ini, penonton bulanan Odnoklassniki adalah lebih daripada 70 juta pelawat unik. Kami Kami berada dalam lima teratas rangkaian sosial terbesar di dunia, dan antara dua puluh tapak di mana pengguna menghabiskan paling banyak masa. Infrastruktur OK mengendalikan beban yang sangat tinggi: lebih daripada sejuta permintaan HTTP/saat setiap hadapan. Sebahagian daripada armada pelayan lebih daripada 8000 keping terletak berdekatan antara satu sama lain - di empat pusat data Moscow, yang memungkinkan untuk memastikan kependaman rangkaian kurang daripada 1 ms antara mereka.

Kami telah menggunakan Cassandra sejak 2010, bermula dengan versi 0.6. Hari ini terdapat beberapa dozen kluster beroperasi. Kelompok terpantas memproses lebih daripada 4 juta operasi sesaat, dan yang terbesar menyimpan 260 TB.

Walau bagaimanapun, ini semua adalah kluster NoSQL biasa yang digunakan untuk penyimpanan lemah diselaraskan data. Kami mahu menggantikan storan konsisten utama, Microsoft SQL Server, yang telah digunakan sejak penubuhan Odnoklassniki. Storan tersebut terdiri daripada lebih daripada 300 mesin SQL Server Edisi Standard, yang mengandungi 50 TB data - entiti perniagaan. Data ini diubah suai sebagai sebahagian daripada transaksi ACID dan memerlukan konsistensi yang tinggi.

Untuk mengedarkan data merentas nod SQL Server, kami menggunakan kedua-dua menegak dan mendatar pembahagian (sharding). Dari segi sejarah, kami menggunakan skema perkongsian data ringkas: setiap entiti dikaitkan dengan token - fungsi ID entiti. Entiti dengan token yang sama diletakkan pada pelayan SQL yang sama. Hubungan induk-perincian telah dilaksanakan supaya token rekod utama dan anak sentiasa sepadan dan terletak pada pelayan yang sama. Dalam rangkaian sosial, hampir semua rekod dijana bagi pihak pengguna - yang bermaksud bahawa semua data pengguna dalam satu subsistem berfungsi disimpan pada satu pelayan. Iaitu, transaksi perniagaan hampir selalu melibatkan jadual dari satu pelayan SQL, yang memungkinkan untuk memastikan konsistensi data menggunakan transaksi ACID tempatan, tanpa perlu menggunakan lambat dan tidak boleh dipercayai urus niaga ACID yang diedarkan.

Terima kasih kepada sharding dan untuk mempercepatkan SQL:

  • Kami tidak menggunakan kekangan kunci Asing, kerana apabila sharding ID entiti mungkin terdapat pada pelayan lain.
  • Kami tidak menggunakan prosedur tersimpan dan pencetus kerana beban tambahan pada CPU DBMS.
  • Kami tidak menggunakan JOIN kerana semua perkara di atas dan banyak bacaan rawak dari cakera.
  • Di luar transaksi, kami menggunakan tahap pengasingan Read Uncommitted untuk mengurangkan kebuntuan.
  • Kami hanya melakukan transaksi pendek (secara purata lebih pendek daripada 100 ms).
  • Kami tidak menggunakan KEMASKINI dan PADAM berbilang baris kerana bilangan kebuntuan yang banyak - kami mengemas kini hanya satu rekod pada satu masa.
  • Kami sentiasa melakukan pertanyaan hanya pada indeks - pertanyaan dengan pelan imbasan jadual penuh untuk kami bermakna melebihkan pangkalan data dan menyebabkannya gagal.

Langkah-langkah ini membolehkan kami memerah prestasi hampir maksimum daripada pelayan SQL. Namun, masalah menjadi semakin banyak. Mari lihat mereka.

Masalah dengan SQL

  • Memandangkan kami menggunakan serpihan tulisan sendiri, penambahan serpihan baharu dilakukan secara manual oleh pentadbir. Selama ini, replika data boleh skala tidak melayani permintaan.
  • Apabila bilangan rekod dalam jadual bertambah, kelajuan pemasukan dan pengubahsuaian berkurangan; apabila menambah indeks pada jadual sedia ada, kelajuan menurun dengan satu faktor; penciptaan dan penciptaan semula indeks berlaku dengan masa henti.
  • Mempunyai sejumlah kecil Windows untuk SQL Server dalam pengeluaran menyukarkan pengurusan infrastruktur

Tetapi masalah utama ialah

toleransi kesalahan

Pelayan SQL klasik mempunyai toleransi kesalahan yang lemah. Katakan anda hanya mempunyai satu pelayan pangkalan data, dan ia gagal setiap tiga tahun sekali. Pada masa ini tapak itu tidak berfungsi selama 20 minit, yang boleh diterima. Jika anda mempunyai 64 pelayan, maka laman web itu turun sekali setiap tiga minggu. Dan jika anda mempunyai 200 pelayan, maka tapak itu tidak berfungsi setiap minggu. Ini masalah.

Apakah yang boleh dilakukan untuk meningkatkan toleransi kesalahan pelayan SQL? Wikipedia menjemput kita untuk membina kluster yang sangat tersedia: di mana sekiranya berlaku kegagalan mana-mana komponen terdapat satu sandaran.

Ini memerlukan armada peralatan mahal: banyak duplikasi, gentian optik, storan dikongsi, dan kemasukan rizab tidak berfungsi dengan pasti: kira-kira 10% penukaran berakhir dengan kegagalan nod sandaran seperti kereta api di belakang nod utama.

Tetapi kelemahan utama kluster yang sangat tersedia sedemikian ialah ketersediaan sifar jika pusat data di mana ia berada gagal. Odnoklassniki mempunyai empat pusat data, dan kami perlu memastikan operasi sekiranya berlaku kegagalan sepenuhnya dalam salah satu daripadanya.

Untuk ini kita boleh gunakan Multi-Master replikasi terbina dalam SQL Server. Penyelesaian ini jauh lebih mahal kerana kos perisian dan mengalami masalah yang terkenal dengan replikasi - kelewatan transaksi yang tidak dapat diramalkan dengan replikasi segerak dan kelewatan dalam menggunakan replikasi (dan, akibatnya, kehilangan pengubahsuaian) dengan replikasi tak segerak. Yang tersirat penyelesaian konflik manual menjadikan pilihan ini tidak terpakai sepenuhnya kepada kami.

Semua masalah ini memerlukan penyelesaian radikal, dan kami mula menganalisisnya secara terperinci. Di sini kita perlu membiasakan diri dengan apa yang dilakukan oleh SQL Server - transaksi.

Transaksi mudah

Mari kita pertimbangkan transaksi paling mudah, dari sudut pandangan pengaturcara SQL yang digunakan: menambahkan foto pada album. Album dan gambar disimpan dalam pinggan yang berbeza. Album ini mempunyai kaunter foto awam. Kemudian transaksi sedemikian dibahagikan kepada langkah-langkah berikut:

  1. Kami mengunci album dengan kunci.
  2. Buat entri dalam jadual foto.
  3. Jika foto itu mempunyai status awam, kemudian tambahkan kaunter foto awam pada album, kemas kini rekod dan lakukan transaksi.

Atau dalam pseudokod:

TX.start("Albums", id);
Album album = albums.lock(id);
Photo photo = photos.create(…);

if (photo.status == PUBLIC ) {
    album.incPublicPhotosCount();
}
album.update();

TX.commit();

Kami melihat bahawa senario yang paling biasa untuk transaksi perniagaan adalah membaca data dari pangkalan data ke dalam memori pelayan aplikasi, menukar sesuatu dan menyimpan nilai baru kembali ke pangkalan data. Biasanya dalam transaksi sedemikian kami mengemas kini beberapa entiti, beberapa jadual.

Apabila melaksanakan transaksi, pengubahsuaian serentak data yang sama daripada sistem lain mungkin berlaku. Sebagai contoh, Antispam mungkin memutuskan bahawa pengguna entah bagaimana mencurigakan dan oleh itu semua foto pengguna seharusnya tidak lagi terbuka, mereka perlu dihantar untuk penyederhanaan, yang bermaksud menukar status photo.status kepada beberapa nilai lain dan mematikan pembilang yang sepadan. Jelas sekali, jika operasi ini berlaku tanpa jaminan keatoman penggunaan dan pengasingan pengubahsuaian bersaing, seperti dalam ASID, maka hasilnya tidak akan seperti yang diperlukan - sama ada pembilang foto akan menunjukkan nilai yang salah, atau tidak semua foto akan dihantar untuk penyederhanaan.

Banyak kod serupa, memanipulasi pelbagai entiti perniagaan dalam satu transaksi, telah ditulis sepanjang kewujudan Odnoklassniki. Berdasarkan pengalaman migrasi ke NoSQL dari Konsistensi Akhirnya Kami tahu bahawa cabaran terbesar (dan pelaburan masa) datang daripada membangunkan kod untuk mengekalkan konsistensi data. Oleh itu, kami menganggap keperluan utama untuk storan baharu adalah peruntukan bagi transaksi ACID sebenar untuk logik aplikasi.

Keperluan lain yang tidak kurang pentingnya ialah:

  • Jika pusat data gagal, kedua-dua membaca dan menulis ke storan baharu mesti tersedia.
  • Mengekalkan kelajuan pembangunan semasa. Iaitu, apabila bekerja dengan repositori baru, jumlah kod harus lebih kurang sama; tidak perlu menambah apa-apa ke repositori, membangunkan algoritma untuk menyelesaikan konflik, mengekalkan indeks sekunder, dll.
  • Kelajuan storan baharu mestilah agak tinggi, semasa membaca data dan semasa memproses urus niaga, yang secara berkesan bermakna penyelesaian akademik yang ketat, universal tetapi perlahan, seperti, sebagai contoh, tidak berkenaan. komitmen dua fasa.
  • Penskalaan on-the-fly automatik.
  • Menggunakan pelayan murah biasa, tanpa perlu membeli perkakasan eksotik.
  • Kemungkinan pembangunan storan oleh pemaju syarikat. Dalam erti kata lain, keutamaan diberikan kepada penyelesaian proprietari atau sumber terbuka, sebaik-baiknya dalam Java.

Keputusan, keputusan

Menganalisis kemungkinan penyelesaian, kami sampai kepada dua pilihan seni bina yang mungkin:

Yang pertama ialah mengambil mana-mana pelayan SQL dan melaksanakan toleransi kesalahan yang diperlukan, mekanisme penskalaan, kelompok failover, penyelesaian konflik dan transaksi ACID yang diedarkan, boleh dipercayai dan pantas. Kami menilai pilihan ini sebagai sangat tidak remeh dan intensif buruh.

Pilihan kedua ialah mengambil storan NoSQL siap sedia dengan penskalaan yang dilaksanakan, kluster failover, penyelesaian konflik, dan melaksanakan transaksi dan SQL sendiri. Pada pandangan pertama, walaupun tugas melaksanakan SQL, apatah lagi transaksi ACID, kelihatan seperti tugas yang akan mengambil masa bertahun-tahun. Tetapi kemudian kami menyedari bahawa set ciri SQL yang kami gunakan dalam amalan adalah jauh dari ANSI SQL Cassandra CQL jauh dari ANSI SQL. Melihat lebih dekat pada CQL, kami menyedari bahawa ia agak hampir dengan apa yang kami perlukan.

Cassandra dan CQL

Jadi, apa yang menarik tentang Cassandra, apakah keupayaan yang ada padanya?

Pertama, di sini anda boleh membuat jadual yang menyokong pelbagai jenis data; anda boleh melakukan PILIH atau KEMASKINI pada kunci utama.

CREATE TABLE photos (id bigint KEY, owner bigint,…);
SELECT * FROM photos WHERE id=?;
UPDATE photos SET … WHERE id=?;

Untuk memastikan ketekalan data replika, Cassandra menggunakan pendekatan kuorum. Dalam kes yang paling mudah, ini bermakna apabila tiga replika baris yang sama diletakkan pada nod berlainan kelompok, penulisan dianggap berjaya jika majoriti nod (iaitu, dua daripada tiga) mengesahkan kejayaan operasi tulis ini . Data baris dianggap konsisten jika, semasa membaca, majoriti nod telah ditinjau dan mengesahkannya. Oleh itu, dengan tiga replika, ketekalan data yang lengkap dan segera dijamin jika satu nod gagal. Pendekatan ini membolehkan kami melaksanakan skim yang lebih dipercayai: sentiasa menghantar permintaan kepada ketiga-tiga replika, menunggu jawapan daripada dua replika terpantas. Maklum balas lewat replika ketiga dibuang dalam kes ini. Nod yang lewat bertindak balas mungkin mengalami masalah serius - brek, kutipan sampah dalam JVM, tuntutan semula memori terus dalam kernel Linux, kegagalan perkakasan, pemotongan sambungan daripada rangkaian. Walau bagaimanapun, ini tidak menjejaskan operasi atau data pelanggan dalam apa jua cara.

Pendekatan apabila kita menghubungi tiga nod dan menerima respons daripada dua dipanggil spekulasi: permintaan untuk replika tambahan dihantar walaupun sebelum ia "jatuh".

Satu lagi faedah Cassandra ialah Batchlog, mekanisme yang memastikan kumpulan perubahan yang anda buat sama ada digunakan sepenuhnya atau tidak digunakan langsung. Ini membolehkan kita menyelesaikan A dalam ASID - keatoman di luar kotak.

Perkara yang paling hampir dengan urus niaga di Cassandra adalah apa yang dipanggil β€œtransaksi ringan". Tetapi mereka jauh dari transaksi ACID "sebenar": sebenarnya, ini adalah peluang untuk dilakukan CAS pada data daripada hanya satu rekod, menggunakan konsensus menggunakan protokol Paxos yang berwajaran tinggi. Oleh itu, kelajuan transaksi sedemikian adalah rendah.

Apa yang kami hilang dalam Cassandra

Jadi, kami terpaksa melaksanakan transaksi ACID sebenar dalam Cassandra. Menggunakannya, kami boleh melaksanakan dua ciri mudah DBMS klasik yang lain dengan mudah: indeks pantas yang konsisten, yang membolehkan kami melakukan pemilihan data bukan sahaja dengan kunci utama, dan penjana biasa ID peningkatan automatik monoton.

Kon

Oleh itu DBMS baharu telah dilahirkan Kon, yang terdiri daripada tiga jenis nod pelayan:

  • Penyimpanan – (hampir) pelayan Cassandra standard yang bertanggungjawab untuk menyimpan data pada cakera tempatan. Apabila beban dan volum data bertambah, kuantitinya boleh ditingkatkan dengan mudah kepada puluhan dan ratusan.
  • Penyelaras transaksi - memastikan pelaksanaan transaksi.
  • Pelanggan ialah pelayan aplikasi yang melaksanakan operasi perniagaan dan memulakan transaksi. Terdapat beribu-ribu pelanggan sedemikian.

NewSQL = NoSQL+ACID

Pelayan semua jenis adalah sebahagian daripada kluster biasa, gunakan protokol mesej Cassandra dalaman untuk berkomunikasi antara satu sama lain dan gosip untuk bertukar-tukar maklumat kluster. Dengan Degupan Jantung, pelayan belajar tentang kegagalan bersama, mengekalkan satu skema data - jadual, struktur dan replikasinya; skim pembahagian, topologi kluster, dsb.

Pelanggan

NewSQL = NoSQL+ACID

Daripada pemacu standard, mod Fat Client digunakan. Nod sedemikian tidak menyimpan data, tetapi boleh bertindak sebagai penyelaras untuk pelaksanaan permintaan, iaitu, Klien itu sendiri bertindak sebagai penyelaras permintaannya: ia menanyakan replika storan dan menyelesaikan konflik. Ini bukan sahaja lebih dipercayai dan lebih pantas daripada pemacu standard, yang memerlukan komunikasi dengan penyelaras jauh, tetapi juga membolehkan anda mengawal penghantaran permintaan. Di luar transaksi yang dibuka pada pelanggan, permintaan dihantar ke repositori. Jika pelanggan telah membuka transaksi, maka semua permintaan dalam transaksi dihantar kepada penyelaras transaksi.
NewSQL = NoSQL+ACID

C*One Transaction Coordinator

Penyelaras adalah sesuatu yang kami laksanakan untuk C*One dari awal. Ia bertanggungjawab untuk mengurus urus niaga, kunci dan susunan urus niaga digunakan.

Untuk setiap transaksi yang diservis, penyelaras menjana cap masa: setiap transaksi berikutnya adalah lebih besar daripada transaksi sebelumnya. Memandangkan sistem penyelesaian konflik Cassandra adalah berdasarkan cap masa (daripada dua rekod yang bercanggah, yang mempunyai cap masa terkini dianggap semasa), konflik akan sentiasa diselesaikan memihak kepada transaksi berikutnya. Demikian kami laksanakan Jam tangan Lamport - cara murah untuk menyelesaikan konflik dalam sistem teragih.

Kunci

Untuk memastikan pengasingan, kami memutuskan untuk menggunakan kaedah paling mudah - kunci pesimis berdasarkan kunci utama rekod. Dalam erti kata lain, dalam transaksi, rekod mesti dikunci terlebih dahulu, baru dibaca, diubah suai dan disimpan. Hanya selepas komit yang berjaya, rekod boleh dibuka kuncinya supaya transaksi yang bersaing boleh menggunakannya.

Melaksanakan penguncian sedemikian adalah mudah dalam persekitaran yang tidak diedarkan. Dalam sistem teragih, terdapat dua pilihan utama: sama ada melaksanakan penguncian teragih pada kluster, atau mengedarkan transaksi supaya transaksi yang melibatkan rekod yang sama sentiasa diservis oleh penyelaras yang sama.

Memandangkan dalam kes kami, data telah diedarkan di kalangan kumpulan transaksi tempatan dalam SQL, ia telah memutuskan untuk menetapkan kumpulan transaksi tempatan kepada penyelaras: seorang penyelaras melakukan semua transaksi dengan token dari 0 hingga 9, yang kedua - dengan token dari 10 hingga 19, dan sebagainya. Akibatnya, setiap kejadian penyelaras menjadi tuan kepada kumpulan transaksi.

Kemudian kunci boleh dilaksanakan dalam bentuk HashMap cetek dalam ingatan penyelaras.

Kegagalan penyelaras

Memandangkan seorang penyelaras secara eksklusif melayani sekumpulan transaksi, adalah sangat penting untuk menentukan dengan cepat fakta kegagalannya supaya percubaan kedua untuk melaksanakan transaksi akan tamat masa. Untuk menjadikannya pantas dan boleh dipercayai, kami menggunakan protokol degupan dengar kuorum yang disambungkan sepenuhnya:

Setiap pusat data menjadi tuan rumah sekurang-kurangnya dua nod penyelaras. Secara berkala, setiap penyelaras menghantar mesej degupan jantung kepada penyelaras yang lain dan memberitahu mereka tentang fungsinya, serta mesej degupan jantung yang diterima daripada penyelaras dalam kelompok kali terakhir.

NewSQL = NoSQL+ACID

Menerima maklumat yang serupa daripada orang lain sebagai sebahagian daripada mesej degupan jantung mereka, setiap penyelaras memutuskan sendiri nod kelompok mana yang berfungsi dan yang tidak, berpandukan prinsip kuorum: jika nod X telah menerima maklumat daripada majoriti nod dalam kelompok tentang nod biasa penerimaan mesej daripada nod Y, kemudian , Y berfungsi. Dan sebaliknya, sebaik sahaja majoriti melaporkan mesej yang hilang dari nod Y, maka Y telah menolak. Adalah aneh bahawa jika kuorum memaklumkan nod X bahawa ia tidak lagi menerima mesej daripadanya, maka nod X sendiri akan menganggap dirinya telah gagal.

Mesej degupan jantung dihantar dengan frekuensi tinggi, kira-kira 20 kali sesaat, dengan tempoh 50 ms. Di Java, sukar untuk menjamin respons aplikasi dalam masa 50 ms disebabkan oleh panjang jeda yang setanding yang disebabkan oleh pengumpul sampah. Kami dapat mencapai masa tindak balas ini menggunakan pemungut sampah G1, yang membolehkan kami menentukan sasaran untuk tempoh jeda GC. Walau bagaimanapun, kadangkala, agak jarang, pengumpul berhenti seketika melebihi 50 ms, yang boleh membawa kepada pengesanan kesalahan palsu. Untuk mengelakkan perkara ini daripada berlaku, penyelaras tidak melaporkan kegagalan nod jauh apabila mesej degupan jantung pertama daripadanya hilang, hanya jika beberapa telah hilang berturut-turut. Beginilah cara kami berjaya mengesan kegagalan nod penyelaras pada 200 Cik.

Tetapi tidak cukup untuk memahami dengan cepat nod yang telah berhenti berfungsi. Kita perlu melakukan sesuatu tentang perkara ini.

Tempahan

Skim klasik melibatkan, sekiranya berlaku kegagalan induk, memulakan pilihan raya baharu menggunakan salah satu daripada bergaya sejagat algoritma. Walau bagaimanapun, algoritma sedemikian mempunyai masalah yang terkenal dengan penumpuan masa dan tempoh proses pilihan raya itu sendiri. Kami dapat mengelakkan kelewatan tambahan sedemikian menggunakan skim penggantian penyelaras dalam rangkaian yang disambungkan sepenuhnya:

NewSQL = NoSQL+ACID

Katakan kita mahu melaksanakan transaksi dalam kumpulan 50. Mari tentukan terlebih dahulu skim penggantian, iaitu, nod mana yang akan melaksanakan transaksi dalam kumpulan 50 sekiranya berlaku kegagalan penyelaras utama. Matlamat kami adalah untuk mengekalkan kefungsian sistem sekiranya berlaku kegagalan pusat data. Mari kita tentukan bahawa rizab pertama akan menjadi nod daripada pusat data lain, dan rizab kedua akan menjadi nod daripada yang ketiga. Skim ini dipilih sekali dan tidak berubah sehingga topologi kluster berubah, iaitu, sehingga nod baru memasukinya (yang berlaku sangat jarang). Prosedur untuk memilih master aktif baru jika yang lama gagal akan sentiasa seperti berikut: rizab pertama akan menjadi master aktif, dan jika ia telah berhenti berfungsi, rizab kedua akan menjadi master aktif.

Skim ini lebih dipercayai daripada algoritma sejagat, kerana untuk mengaktifkan master baru sudah cukup untuk menentukan kegagalan yang lama.

Tetapi bagaimanakah pelanggan akan memahami tuan mana yang sedang bekerja sekarang? Adalah mustahil untuk menghantar maklumat kepada beribu-ribu pelanggan dalam 50 ms. Situasi mungkin berlaku apabila pelanggan menghantar permintaan untuk membuka transaksi, belum mengetahui bahawa induk ini tidak lagi berfungsi, dan permintaan akan tamat masa. Untuk mengelakkan perkara ini daripada berlaku, pelanggan secara spekulatif menghantar permintaan untuk membuka urus niaga kepada induk kumpulan dan kedua-dua rizabnya sekaligus, tetapi hanya orang yang menjadi induk aktif pada masa ini akan membalas permintaan ini. Pelanggan akan membuat semua komunikasi seterusnya dalam transaksi hanya dengan tuan aktif.

Tempat induk sandaran menerima permintaan untuk urus niaga yang bukan milik mereka ke dalam baris gilir transaksi yang belum lahir, di mana ia disimpan untuk beberapa lama. Jika tuan aktif mati, tuan baharu memproses permintaan untuk membuka urus niaga daripada baris gilirnya dan bertindak balas kepada pelanggan. Jika pelanggan telah membuka transaksi dengan tuan lama, maka respons kedua diabaikan (dan, jelas sekali, transaksi sedemikian tidak akan selesai dan akan diulang oleh pelanggan).

Cara urus niaga berfungsi

Katakan pelanggan menghantar permintaan kepada penyelaras untuk membuka urus niaga untuk entiti ini dan ini dengan kunci utama ini dan itu. Penyelaras mengunci entiti ini dan meletakkannya dalam jadual kunci dalam ingatan. Jika perlu, penyelaras membaca entiti ini daripada storan dan menyimpan data yang terhasil dalam keadaan transaksi dalam ingatan penyelaras.

NewSQL = NoSQL+ACID

Apabila pelanggan ingin menukar data dalam transaksi, ia menghantar permintaan kepada penyelaras untuk mengubah suai entiti, dan penyelaras meletakkan data baharu dalam jadual status transaksi dalam ingatan. Ini melengkapkan rakaman - tiada rakaman dibuat ke storan.

NewSQL = NoSQL+ACID

Apabila pelanggan meminta data diubah sendiri sebagai sebahagian daripada transaksi aktif, penyelaras bertindak seperti berikut:

  • jika ID sudah berada dalam transaksi, maka data diambil dari memori;
  • jika tiada ID dalam ingatan, maka data yang hilang dibaca dari nod storan, digabungkan dengan yang sudah ada dalam ingatan, dan hasilnya diberikan kepada klien.

Oleh itu, pelanggan boleh membaca perubahannya sendiri, tetapi pelanggan lain tidak melihat perubahan ini, kerana ia hanya disimpan dalam ingatan penyelaras; ia belum lagi berada dalam nod Cassandra.

NewSQL = NoSQL+ACID

Apabila pelanggan menghantar komit, keadaan yang berada dalam ingatan perkhidmatan disimpan oleh penyelaras dalam kelompok log, dan dihantar sebagai kelompok log ke storan Cassandra. Kedai melakukan segala yang diperlukan untuk memastikan pakej ini digunakan secara atom (sepenuhnya), dan mengembalikan respons kepada penyelaras, yang melepaskan kunci dan mengesahkan kejayaan transaksi kepada pelanggan.

NewSQL = NoSQL+ACID

Dan untuk melancarkan semula, penyelaras hanya perlu membebaskan memori yang diduduki oleh keadaan transaksi.

Hasil daripada penambahbaikan di atas, kami melaksanakan prinsip ACID:

  • Atomiti. Ini adalah jaminan bahawa tiada urus niaga akan direkodkan sebahagiannya dalam sistem; sama ada semua suboperasinya akan selesai, atau tiada satu pun akan diselesaikan. Kami mematuhi prinsip ini melalui kumpulan log dalam Cassandra.
  • Konsisten. Setiap transaksi yang berjaya, mengikut definisi, hanya merekodkan hasil yang sah. Jika, selepas membuka urus niaga dan melaksanakan sebahagian daripada operasi, didapati keputusannya tidak sah, pemulangan semula dilakukan.
  • Pengasingan. Apabila urus niaga dilaksanakan, urus niaga serentak tidak boleh menjejaskan hasilnya. Urus niaga bersaing diasingkan menggunakan kunci pesimis pada penyelaras. Untuk bacaan di luar transaksi, prinsip pengasingan dipatuhi pada tahap Read Committed.
  • Kemampanan. Tanpa mengira masalah pada tahap yang lebih rendahβ€”pemadaman sistem, kegagalan perkakasanβ€”perubahan yang dibuat oleh transaksi yang berjaya disiapkan harus kekal dikekalkan apabila operasi disambung semula.

Membaca mengikut indeks

Mari kita ambil jadual ringkas:

CREATE TABLE photos (
id bigint primary key,
owner bigint,
modified timestamp,
…)

Ia mempunyai ID (kunci utama), pemilik dan tarikh pengubahsuaian. Anda perlu membuat permintaan yang sangat mudah - pilih data pada pemilik dengan tarikh perubahan "untuk hari terakhir".

SELECT *
WHERE owner=?
AND modified>?

Agar pertanyaan sedemikian diproses dengan cepat, dalam SQL DBMS klasik anda perlu membina indeks mengikut lajur (pemilik, diubah suai). Kami boleh melakukan ini dengan mudah, kerana kami kini mempunyai jaminan ACID!

Indeks dalam C*One

Terdapat jadual sumber dengan gambar di mana ID rekod adalah kunci utama.

NewSQL = NoSQL+ACID

Untuk indeks, C*One mencipta jadual baharu yang merupakan salinan asal. Kuncinya adalah sama dengan ungkapan indeks, dan ia juga termasuk kunci utama rekod daripada jadual sumber:

NewSQL = NoSQL+ACID

Kini pertanyaan untuk "pemilik untuk hari terakhir" boleh ditulis semula sebagai pilihan daripada jadual lain:

SELECT * FROM i1_test
WHERE owner=?
AND modified>?

Ketekalan data dalam foto jadual sumber dan jadual indeks i1 dikekalkan secara automatik oleh penyelaras. Berdasarkan skema data sahaja, apabila perubahan diterima, penyelaras menjana dan menyimpan perubahan bukan sahaja dalam jadual utama, tetapi juga dalam salinan. Tiada tindakan tambahan dilakukan pada jadual indeks, log tidak dibaca dan tiada kunci digunakan. Iaitu, menambah indeks menggunakan hampir tiada sumber dan hampir tidak mempunyai kesan ke atas kelajuan menggunakan pengubahsuaian.

Menggunakan ACID, kami dapat melaksanakan indeks seperti SQL. Ia konsisten, berskala, pantas, boleh digubah dan terbina dalam bahasa pertanyaan CQL. Tiada perubahan pada kod aplikasi diperlukan untuk menyokong indeks. Semuanya semudah dalam SQL. Dan yang paling penting, indeks tidak menjejaskan kelajuan pelaksanaan pengubahsuaian pada jadual transaksi asal.

Apa yang berlaku

Kami membangunkan C*One tiga tahun lalu dan melancarkannya ke dalam operasi komersial.

Apa yang kita dapat akhirnya? Mari kita nilai ini menggunakan contoh subsistem pemprosesan dan penyimpanan foto, salah satu jenis data yang paling penting dalam rangkaian sosial. Kami tidak bercakap tentang badan gambar itu sendiri, tetapi tentang semua jenis maklumat meta. Kini Odnoklassniki mempunyai kira-kira 20 bilion rekod sedemikian, sistem memproses 80 ribu permintaan baca sesaat, sehingga 8 ribu transaksi ACID sesaat yang dikaitkan dengan pengubahsuaian data.

Apabila kami menggunakan SQL dengan faktor replikasi = 1 (tetapi dalam RAID 10), metamaklumat foto disimpan pada gugusan 32 mesin yang sangat tersedia yang menjalankan Microsoft SQL Server (ditambah 11 sandaran). 10 pelayan juga diperuntukkan untuk menyimpan sandaran. Sebanyak 50 buah kereta mahal. Pada masa yang sama, sistem beroperasi pada beban berkadar, tanpa rizab.

Selepas berhijrah ke sistem baharu, kami menerima faktor replikasi = 3 - satu salinan dalam setiap pusat data. Sistem ini terdiri daripada 63 nod storan Cassandra dan 6 mesin penyelaras, untuk sejumlah 69 pelayan. Tetapi mesin ini jauh lebih murah, jumlah kosnya adalah kira-kira 30% daripada kos sistem SQL. Pada masa yang sama, beban disimpan pada 30%.

Dengan pengenalan C*One, kependaman juga berkurangan: dalam SQL, operasi tulis mengambil masa kira-kira 4,5 ms. Dalam C*One - kira-kira 1,6 ms. Tempoh transaksi adalah secara purata kurang daripada 40 ms, komit selesai dalam 2 ms, tempoh baca dan tulis adalah secara purata 2 ms. Persentil ke-99 - hanya 3-3,1 ms, bilangan tamat masa telah berkurangan sebanyak 100 kali ganda - semuanya disebabkan oleh penggunaan spekulasi yang meluas.

Pada masa ini, kebanyakan nod SQL Server telah dinyahaktifkan; produk baharu sedang dibangunkan hanya menggunakan C*One. Kami menyesuaikan C*One untuk berfungsi dalam awan kami satu awan, yang memungkinkan untuk mempercepatkan penggunaan kluster baharu, memudahkan konfigurasi dan mengautomasikan operasi. Tanpa kod sumber, melakukan ini akan menjadi lebih sukar dan menyusahkan.

Sekarang kami sedang berusaha untuk memindahkan kemudahan storan kami yang lain ke awan - tetapi itu adalah cerita yang sama sekali berbeza.

Sumber: www.habr.com

Tambah komen