Tentang perpindahan dari cluster Redis ke cluster Redis

Tentang perpindahan dari cluster Redis ke cluster Redis

Mengenai produk yang telah berkembang selama lebih dari satu dekade, sama sekali tidak mengherankan jika menemukan teknologi ketinggalan jaman di dalamnya. Namun bagaimana jika dalam enam bulan Anda harus menahan beban 10 kali lebih tinggi, dan biaya jatuh akan meningkat ratusan kali lipat? Dalam hal ini, Anda memerlukan Highload Engineer yang keren. Namun karena tidak adanya pembantu, mereka mempercayakan saya untuk menyelesaikan masalah tersebut. Di bagian pertama artikel saya akan memberi tahu Anda bagaimana kami berpindah dari cluster Redis ke cluster Redis, dan di bagian kedua saya akan memberikan saran tentang cara mulai menggunakan cluster dan apa yang harus diperhatikan saat menggunakannya.

Pemilihan teknologi

Apakah seburuk itu? memisahkan Redis (redis mandiri) dalam konfigurasi 1 master dan N budak? Mengapa saya menyebutnya teknologi usang?

Tidak, Redis tidak seburuk itu... Namun, ada beberapa kekurangan yang tidak bisa diabaikan.

  • Pertama, Redis tidak mendukung mekanisme pemulihan bencana setelah kegagalan utama. Untuk mengatasi masalah ini, kami menggunakan konfigurasi dengan transfer otomatis VIP ke master baru, mengubah peran salah satu budak dan mengalihkan sisanya. Mekanisme ini berhasil, tetapi tidak dapat disebut sebagai solusi yang dapat diandalkan. Pertama, terjadi alarm palsu, dan kedua, alarm tersebut sekali pakai, dan setelah pengoperasian diperlukan tindakan manual untuk mengisi daya pegas.

  • Kedua, hanya memiliki satu master menyebabkan masalah sharding. Kami harus membuat beberapa cluster independen “1 master dan N slave”, kemudian mendistribusikan database secara manual ke mesin-mesin ini dan berharap besok salah satu database tidak akan membengkak sehingga harus dipindahkan ke instance terpisah.

Apa saja pilihannya?

  • Solusi termahal dan terkaya adalah Redis-Enterprise. Ini adalah solusi terpadu dengan dukungan teknis penuh. Terlepas dari kenyataan bahwa ini terlihat ideal dari sudut pandang teknis, itu tidak cocok untuk kami karena alasan ideologis.
  • Cluster Redis. Di luar kotak ada dukungan untuk master failover dan sharding. Antarmukanya hampir tidak berbeda dengan versi biasa. Kelihatannya menjanjikan, kita akan membicarakan kendalanya nanti.
  • Tarantool, Memcache, Aerospike dan lain-lain. Semua alat ini melakukan hal yang hampir sama. Namun masing-masing mempunyai kekurangannya masing-masing. Kami memutuskan untuk tidak menaruh semua telur kami dalam satu keranjang. Kami menggunakan Memcache dan Tarantool untuk tugas-tugas lain, dan, ke depan, saya akan mengatakan bahwa dalam praktik kami ada lebih banyak masalah dengan keduanya.

Kekhususan penggunaan

Mari kita lihat masalah apa saja yang pernah kami selesaikan dengan Redis dan fungsi apa yang kami gunakan:

  • Cache sebelum permintaan ke layanan jarak jauh seperti 2GIS | Golang

    DAPATKAN SET MGET MSET "PILIH DB"

  • Tembolok sebelum MYSQL | PHP

    DAPATKAN SET MGET MSET SCAN "KUNCI BERDASARKAN POLA" "PILIH DB"

  • Penyimpanan utama untuk layanan bekerja dengan sesi dan koordinat pengemudi | Golang

    DAPATKAN SET MGET MSET "PILIH DB" "TAMBAHKAN KUNCI GEO" "DAPATKAN KUNCI GEO" PINDAI

Seperti yang Anda lihat, tidak ada matematika yang lebih tinggi. Lalu apa kesulitannya? Mari kita lihat setiap metode secara terpisah.

metode
Описание
Fitur cluster Redis
keputusan

DAPATKAN
Kunci tulis/baca

MGET MSET
Menulis/membaca beberapa kunci
Kuncinya akan berada di node yang berbeda. Perpustakaan yang sudah jadi hanya dapat melakukan multi-operasi dalam satu node
Ganti MGET dengan alur operasi N GET

PILIH DB
Pilih basis yang akan kita gunakan
Tidak mendukung banyak database
Masukkan semuanya ke dalam satu database. Tambahkan awalan ke kunci

SCAN
Telusuri semua kunci di database
Karena kami memiliki satu database, menelusuri semua kunci di cluster terlalu mahal
Pertahankan invarian dalam satu kunci dan lakukan HSCAN pada kunci ini. Atau menolak sepenuhnya

GEO
Operasi dengan geokey
Geokey tidak dipecah

KUNCI BERDASARKAN POLA
Mencari kunci berdasarkan pola
Karena kami memiliki satu database, kami akan mencari di semua kunci di cluster. Terlalu mahal
Tolak atau pertahankan invarian, seperti dalam kasus SCAN

Redis vs Redis-cluster

Apa ruginya dan apa keuntungannya saat beralih ke cluster?

  • Kekurangan: kami kehilangan fungsionalitas beberapa database.
    • Jika kita ingin menyimpan data yang secara logika tidak berhubungan dalam satu cluster, kita harus membuat kruk dalam bentuk awalan.
    • Kami kehilangan semua operasi "dasar", seperti SCAN, DBSIZE, CLEAR DB, dll.
    • Multi-operasi menjadi jauh lebih sulit untuk diterapkan karena mungkin memerlukan akses ke beberapa node.
  • Plus:
    • Toleransi kesalahan dalam bentuk master failover.
    • Sharding di sisi Redis.
    • Transfer data antar node secara atom dan tanpa downtime.
    • Menambah dan mendistribusikan ulang kapasitas dan beban tanpa waktu henti.

Saya akan menyimpulkan bahwa jika Anda tidak perlu memberikan toleransi kesalahan tingkat tinggi, maka berpindah ke sebuah cluster tidak layak dilakukan, karena ini bisa menjadi tugas yang tidak sepele. Tetapi jika pada awalnya Anda memilih antara versi terpisah dan versi cluster, maka Anda harus memilih cluster, karena tidak lebih buruk dan, terlebih lagi, akan menyelamatkan Anda dari beberapa sakit kepala.

Bersiap untuk bergerak

Mari kita mulai dengan persyaratan untuk pindah:

  • Ini harus mulus. Penghentian total layanan selama 5 menit tidak cocok untuk kami.
  • Ini harus seaman dan bertahap mungkin. Saya ingin memiliki kendali atas situasi ini. Kami tidak ingin membuang semuanya sekaligus dan berdoa untuk tombol rollback.
  • Kehilangan data minimal saat berpindah. Kami memahami bahwa akan sangat sulit untuk berpindah secara atom, jadi kami mengizinkan beberapa desinkronisasi antara data di Redis reguler dan cluster.

Pemeliharaan klaster

Sebelum melakukan perpindahan, kita harus memikirkan apakah kita dapat mendukung cluster tersebut:

  • Grafik. Kami menggunakan Prometheus dan Grafana untuk membuat grafik beban CPU, penggunaan memori, jumlah klien, jumlah operasi GET, SET, AUTH, dll.
  • Keahlian. Bayangkan besok Anda akan mempunyai kelompok besar yang menjadi tanggung jawab Anda. Jika rusak, tidak seorang pun kecuali Anda yang dapat memperbaikinya. Jika dia mulai melambat, semua orang akan berlari ke arah Anda. Jika Anda perlu menambah sumber daya atau mendistribusikan ulang beban, kembalilah kepada Anda. Agar tidak menjadi abu-abu pada usia 25, disarankan untuk menyediakan kasus-kasus ini dan memeriksa terlebih dahulu bagaimana teknologi akan berperilaku dalam tindakan tertentu. Mari kita bicarakan hal ini lebih detail di bagian “Keahlian”.
  • Pemantauan dan peringatan. Saat sebuah cluster rusak, Anda ingin menjadi orang pertama yang mengetahuinya. Di sini kami membatasi diri pada pemberitahuan bahwa semua node mengembalikan informasi yang sama tentang status cluster (ya, itu terjadi secara berbeda). Dan masalah lainnya dapat diketahui lebih cepat melalui peringatan dari layanan klien Redis.

Relokasi

Bagaimana kita akan bergerak:

  • Pertama-tama, Anda perlu menyiapkan perpustakaan untuk bekerja dengan cluster. Kami menggunakan go-redis sebagai dasar untuk versi Go dan mengubahnya sedikit agar sesuai dengan keinginan kami. Kami menerapkan Multi-metode melalui saluran pipa, dan juga sedikit memperbaiki aturan untuk permintaan berulang. Versi PHP memiliki lebih banyak masalah, tapi kami akhirnya memilih php-redis. Mereka baru-baru ini memperkenalkan dukungan cluster dan menurut kami itu terlihat bagus.
  • Selanjutnya Anda perlu men-deploy cluster itu sendiri. Ini dilakukan secara harfiah dalam dua perintah berdasarkan file konfigurasi. Kami akan membahas pengaturannya lebih detail di bawah ini.
  • Untuk perpindahan bertahap kami menggunakan mode kering. Karena kami memiliki dua versi perpustakaan dengan antarmuka yang sama (satu untuk versi reguler, yang lain untuk cluster), tidak ada biaya untuk membuat pembungkus yang akan bekerja dengan versi terpisah dan secara paralel menduplikasi semua permintaan ke cluster, bandingkan tanggapan dan tulis perbedaan di log (dalam kasus kami di NewRelic). Jadi, meskipun versi cluster rusak saat peluncuran, produksi kami tidak akan terpengaruh.
  • Setelah meluncurkan cluster dalam mode kering, kita dapat dengan tenang melihat grafik perbedaan respons. Jika tingkat kesalahan perlahan tapi pasti bergerak menuju konstanta kecil, maka semuanya baik-baik saja. Mengapa masih terdapat perbedaan? Karena perekaman dalam versi terpisah terjadi sedikit lebih awal daripada di cluster, dan karena microlag, data mungkin berbeda. Yang tersisa hanyalah melihat log perbedaan, dan jika semuanya disebabkan oleh non-atomisitas catatan, maka kita dapat melanjutkan.
  • Sekarang Anda dapat mengganti mode kering ke arah yang berlawanan. Kami akan menulis dan membaca dari cluster, dan menduplikasinya ke dalam versi terpisah. Untuk apa? Selama minggu depan saya ingin mengamati pekerjaan cluster. Jika tiba-tiba ternyata ada masalah pada beban puncak, atau kami tidak memperhitungkan sesuatu, kami selalu melakukan rollback darurat ke kode lama dan data saat ini berkat mode kering.
  • Yang tersisa hanyalah menonaktifkan mode kering dan membongkar versi terpisah.

Keahlian

Pertama, secara singkat tentang desain cluster.

Pertama-tama, Redis adalah penyimpanan nilai kunci. String sewenang-wenang digunakan sebagai kunci. Angka, string, dan keseluruhan struktur dapat digunakan sebagai nilai. Ada banyak sekali yang terakhir, tetapi untuk memahami struktur umum hal ini tidak penting bagi kami.
Tingkat abstraksi berikutnya setelah kunci adalah slot (SLOTS). Setiap kunci milik salah satu dari 16 slot. Bisa ada sejumlah kunci di dalam setiap slot. Jadi, semua kunci dibagi menjadi 383 himpunan terpisah.
Tentang perpindahan dari cluster Redis ke cluster Redis

Selanjutnya, harus ada N node master di cluster. Setiap node dapat dianggap sebagai instance Redis terpisah yang mengetahui segalanya tentang node lain dalam cluster. Setiap node master berisi sejumlah slot. Setiap slot hanya dimiliki oleh satu node master. Semua slot perlu didistribusikan antar node. Jika beberapa slot tidak dialokasikan, maka kunci yang disimpan di dalamnya tidak akan dapat diakses. Masuk akal untuk menjalankan setiap node master pada mesin logis atau fisik yang terpisah. Perlu juga diingat bahwa setiap node hanya berjalan pada satu inti, dan jika Anda ingin menjalankan beberapa instance Redis pada mesin logis yang sama, pastikan instance tersebut berjalan pada inti yang berbeda (kami belum mencobanya, namun secara teori ini akan berhasil) . Pada dasarnya, node master menyediakan sharding reguler, dan lebih banyak node master memungkinkan permintaan tulis dan baca untuk diskalakan.

Setelah semua kunci didistribusikan di antara slot, dan slot tersebar di antara node master, sejumlah node budak dapat ditambahkan ke setiap node master. Dalam setiap link master-slave, replikasi normal akan berfungsi. Budak diperlukan untuk menskalakan permintaan baca dan untuk failover jika terjadi kegagalan master.
Tentang perpindahan dari cluster Redis ke cluster Redis

Sekarang mari kita bicara tentang operasi yang bisa dilakukan dengan lebih baik.

Kami akan mengakses sistem melalui Redis-CLI. Karena Redis tidak memiliki satu titik masuk, Anda dapat melakukan operasi berikut pada node mana pun. Pada setiap titik saya secara terpisah memperhatikan kemungkinan melakukan operasi di bawah beban.

  • Hal pertama dan terpenting yang kita perlukan adalah pengoperasian node cluster. Ini mengembalikan status cluster, menunjukkan daftar node, perannya, distribusi slot, dll. Informasi lebih lanjut dapat diperoleh dengan menggunakan info cluster dan slot cluster.
  • Alangkah baiknya jika bisa menambah dan menghapus node. Untuk tujuan ini terdapat operasi cluster meet dan cluster forget. Harap dicatat bahwa lupa cluster harus diterapkan pada SETIAP node, baik master maupun replika. Dan cluster meet hanya perlu dipanggil pada satu node saja. Perbedaan ini dapat membingungkan, jadi yang terbaik adalah mempelajarinya sebelum Anda meluncurkan cluster Anda. Menambahkan node dilakukan dengan aman dalam pertempuran dan tidak mempengaruhi pengoperasian cluster dengan cara apa pun (yang logis). Jika Anda akan menghapus sebuah node dari cluster, Anda harus memastikan tidak ada slot yang tersisa di sana (jika tidak, Anda berisiko kehilangan akses ke semua kunci pada node ini). Selain itu, jangan menghapus master yang memiliki budak, jika tidak, pemungutan suara yang tidak perlu untuk master baru akan dilakukan. Jika node sudah tidak memiliki slot, maka ini adalah masalah kecil, tapi mengapa kita memerlukan pilihan tambahan jika kita bisa menghapus budaknya terlebih dahulu.
  • Jika Anda perlu menukar posisi master dan slave secara paksa, maka perintah failover cluster akan berhasil. Saat memanggilnya dalam pertempuran, Anda perlu memahami bahwa master tidak akan tersedia selama operasi. Biasanya peralihan terjadi dalam waktu kurang dari satu detik, tetapi tidak bersifat atomik. Anda dapat memperkirakan bahwa beberapa permintaan ke master akan gagal selama waktu ini.
  • Sebelum menghapus sebuah node dari cluster, tidak boleh ada slot yang tersisa di sana. Lebih baik mendistribusikannya kembali menggunakan perintah cluster reshard. Slot akan ditransfer dari satu master ke master lainnya. Keseluruhan operasi mungkin memakan waktu beberapa menit, tergantung pada volume data yang ditransfer, namun proses transfer aman dan tidak mempengaruhi pengoperasian cluster dengan cara apa pun. Dengan demikian, semua data dapat ditransfer dari satu node ke node lainnya secara langsung saat dimuat, dan tanpa mengkhawatirkan ketersediaannya. Namun, ada juga kehalusannya. Pertama, transfer data dikaitkan dengan beban tertentu pada node penerima dan pengirim. Jika node penerima sudah banyak memuat prosesor, maka Anda tidak boleh memuatnya dengan menerima data baru. Kedua, segera setelah tidak ada satu slot pun yang tersisa pada master pengirim, semua budaknya akan segera menuju ke master tempat slot tersebut ditransfer. Dan masalahnya adalah semua budak ini ingin menyinkronkan data sekaligus. Dan Anda akan beruntung jika sinkronisasinya sebagian daripada sinkronisasi lengkap. Pertimbangkan hal ini dan gabungkan operasi transfer slot dan penonaktifan/transfer budak. Atau berharap Anda memiliki margin keamanan yang cukup.
  • Apa yang harus Anda lakukan jika, selama transfer, Anda menemukan slot Anda hilang di suatu tempat? Saya harap masalah ini tidak memengaruhi Anda, tetapi jika ya, ada operasi perbaikan cluster. Paling tidak, dia akan menyebarkan slot ke seluruh node dalam urutan acak. Saya sarankan memeriksa operasinya dengan terlebih dahulu menghapus node dengan slot terdistribusi dari cluster. Karena data di slot yang tidak terisi sudah tidak tersedia, sudah terlambat untuk mengkhawatirkan masalah ketersediaan slot tersebut. Pada gilirannya, operasi tersebut tidak akan mempengaruhi slot yang didistribusikan.
  • Operasi lain yang bermanfaat adalah monitor. Ini memungkinkan Anda untuk melihat secara real time seluruh daftar permintaan yang masuk ke node. Selain itu, Anda dapat mengambilnya dan mencari tahu apakah ada lalu lintas yang diperlukan.

Perlu juga disebutkan prosedur master failover. Singkatnya, itu ada, dan menurut saya, itu berfungsi dengan baik. Namun, jangan berpikir bahwa jika Anda mencabut kabel daya pada mesin dengan node master, Redis akan segera beralih dan klien tidak akan menyadari kehilangannya. Dalam praktik saya, peralihan terjadi dalam beberapa detik. Selama waktu ini, beberapa data tidak akan tersedia: ketidaktersediaan master terdeteksi, node memilih yang baru, slave dialihkan, data disinkronkan. Cara terbaik untuk memastikan sendiri bahwa skema ini berhasil adalah dengan melakukan latihan lokal. Naikkan cluster di laptop Anda, berikan beban minimum, simulasikan kerusakan (misalnya, dengan memblokir port), dan evaluasi kecepatan peralihan. Menurut pendapat saya, hanya setelah bermain dengan cara ini selama satu atau dua hari Anda dapat yakin dengan pengoperasian teknologinya. Ya, atau semoga perangkat lunak yang digunakan separuh Internet mungkin berfungsi.

Konfigurasi

Seringkali, konfigurasi adalah hal pertama yang Anda perlukan untuk mulai bekerja dengan alat tersebut. Dan ketika semuanya berfungsi, Anda bahkan tidak ingin menyentuh konfigurasinya. Dibutuhkan upaya untuk memaksa diri Anda kembali ke pengaturan dan melakukannya dengan hati-hati. Dalam ingatan saya, kami mengalami setidaknya dua kegagalan serius karena kurangnya perhatian terhadap konfigurasi. Berikan perhatian khusus pada poin-poin berikut:

  • timeout 0
    Waktu setelah koneksi yang tidak aktif ditutup (dalam detik). 0 - jangan tutup
    Tidak semua perpustakaan kami dapat menutup koneksi dengan benar. Dengan menonaktifkan pengaturan ini, kami berisiko mencapai batas jumlah klien. Di sisi lain, jika ada masalah seperti itu, pemutusan koneksi yang hilang secara otomatis akan menutupinya, dan kita mungkin tidak menyadarinya. Selain itu, Anda tidak boleh mengaktifkan pengaturan ini saat menggunakan koneksi tetap.
  • Simpan xy & tambahkan saja ya
    Menyimpan snapshot RDB.
    Kami akan membahas masalah RDB/AOF secara rinci di bawah ini.
  • stop-writes-on-bgsave-error no & slave-serve-stale-data yes
    Jika diaktifkan, jika snapshot RDB rusak, master akan berhenti menerima permintaan perubahan. Jika koneksi ke master terputus, budak dapat terus merespons permintaan (ya). Atau akan berhenti merespons (tidak)
    Kami tidak senang dengan situasi di mana Redis berubah menjadi labu.
  • repl-ping-budak-periode 5
    Setelah jangka waktu ini, kita akan mulai khawatir bahwa master telah rusak dan inilah saatnya untuk melakukan prosedur failover.
    Anda harus menemukan keseimbangan secara manual antara positif palsu dan memicu failover. Dalam latihan kami ini adalah 5 detik.
  • repl-backlog-ukuran 1024mb & epl-backlog-ttl 0
    Kita dapat menyimpan data sebanyak ini dalam buffer untuk replika yang gagal. Jika buffer habis, Anda harus melakukan sinkronisasi sepenuhnya.
    Latihan menunjukkan bahwa lebih baik menetapkan nilai yang lebih tinggi. Ada banyak alasan mengapa replika mulai melambat. Jika tertinggal, kemungkinan besar master Anda sudah kesulitan mengatasinya, dan sinkronisasi penuh akan menjadi tantangan terakhir.
  • klien maksimal 10000
    Jumlah maksimum klien satu kali.
    Berdasarkan pengalaman kami, lebih baik menetapkan nilai yang lebih tinggi. Redis menangani 10 ribu koneksi dengan baik. Pastikan ada cukup soket pada sistem.
  • maxmemory-policy volatil-ttl
    Aturan dimana kunci dihapus ketika batas memori yang tersedia tercapai.
    Yang penting di sini bukanlah peraturan itu sendiri, namun pemahaman tentang bagaimana hal ini akan terjadi. Redis patut dipuji karena kemampuannya untuk bekerja secara normal ketika batas memori tercapai.

Masalah RDB dan AOF

Meskipun Redis sendiri menyimpan semua informasi dalam RAM, ada juga mekanisme untuk menyimpan data ke disk. Lebih tepatnya, tiga mekanisme:

  • RDB-snapshot - snapshot lengkap dari semua data. Atur menggunakan konfigurasi SAVE XY dan baca “Simpan snapshot lengkap semua data setiap X detik jika setidaknya tombol Y telah berubah.”
  • File hanya tambahan - daftar operasi sesuai urutan pelaksanaannya. Menambahkan operasi masuk baru ke file setiap X detik atau setiap operasi Y.
  • RDB dan AOF merupakan kombinasi dari dua sebelumnya.

Semua cara mempunyai kelebihan dan kekurangannya masing-masing, saya tidak akan mencantumkan semuanya, saya hanya akan memperhatikan poin-poin yang menurut saya kurang jelas.

Pertama, menyimpan snapshot RDB memerlukan pemanggilan FORK. Jika datanya banyak, hal ini dapat membuat seluruh Redis terhenti selama beberapa milidetik hingga satu detik. Selain itu, sistem perlu mengalokasikan memori untuk snapshot seperti itu, yang menyebabkan kebutuhan untuk menjaga persediaan ganda RAM pada mesin logis: jika 8 GB dialokasikan untuk Redis, maka 16 GB harus tersedia di mesin virtual dengan dia.

Kedua, ada masalah dengan sinkronisasi parsial. Dalam mode AOF, ketika budak tersambung kembali, alih-alih sinkronisasi sebagian, sinkronisasi penuh dapat dilakukan. Mengapa ini terjadi, saya tidak mengerti. Namun perlu diingat hal ini.

Kedua poin ini sudah membuat kita berpikir apakah kita benar-benar membutuhkan data ini di disk jika semuanya sudah diduplikasi oleh budak. Data hanya bisa hilang jika semua budak gagal, dan ini adalah masalah tingkat “kebakaran di DC”. Sebagai kompromi, Anda dapat mengusulkan untuk menyimpan data hanya pada budak, tetapi dalam hal ini Anda perlu memastikan bahwa budak ini tidak akan pernah menjadi master selama pemulihan bencana (untuk ini ada pengaturan prioritas budak di konfigurasi mereka). Bagi kami sendiri, dalam setiap kasus tertentu kami memikirkan apakah perlu menyimpan data ke disk, dan paling sering jawabannya adalah "tidak".

Kesimpulan

Sebagai penutup, saya berharap dapat memberikan gambaran umum tentang cara kerja redis-cluster bagi mereka yang belum pernah mendengarnya sama sekali, dan juga menarik perhatian pada beberapa poin yang tidak jelas bagi mereka yang telah menggunakannya. untuk waktu yang lama.
Terima kasih atas waktu Anda dan, seperti biasa, komentar mengenai topik ini dipersilakan.

Sumber: www.habr.com

Tambah komentar