Lima murid sareng tilu toko nilai konci anu disebarkeun

Atawa kumaha urang nulis klien C ++ perpustakaan pikeun ZooKeeper, etcd jeung Konsul KV

Di dunya sistem anu disebarkeun, aya sababaraha tugas umum: nyimpen inpormasi ngeunaan komposisi klaster, ngatur konfigurasi titik, ngadeteksi titik anu salah, milih pamimpin. jeung anu sanésna. Pikeun ngajawab masalah ieu, sistem disebarkeun husus geus dijieun - jasa koordinasi. Ayeuna urang bakal museurkeun tilu di antarana: ZooKeeper, jsb jeung Konsul. Tina sagala pungsionalitas Konsul anu beunghar, urang bakal difokuskeun Konsul KV.

Lima murid sareng tilu toko nilai konci anu disebarkeun

Intina, sadaya sistem ieu toleran kasalahan, toko nilai konci anu linier. Sanajan model data maranéhanana boga béda anu signifikan, nu urang bahas engké, aranjeunna ngajawab masalah praktis sami. Jelas, unggal aplikasi anu nganggo jasa koordinasi dihijikeun ka salah sahijina, anu tiasa nyababkeun kabutuhan pikeun ngadukung sababaraha sistem dina hiji pusat data anu ngarengsekeun masalah anu sami pikeun aplikasi anu béda.

Gagasan pikeun ngajawab masalah ieu asalna dina agénsi konsultan Australia, sarta eta murag ka kami, tim leutik siswa, pikeun nerapkeun eta, nu naon Kaula bade ngobrol ngeunaan.

Urang junun nyieun perpustakaan nu nyadiakeun panganteur umum pikeun gawé bareng ZooKeeper, etcd na Konsul KV. Perpustakaan ieu ditulis dina C ++, tapi aya rencana pikeun port ka basa séjén.

Modél Data

Pikeun ngembangkeun antarmuka umum pikeun tilu sistem anu béda, anjeun kedah ngartos naon anu umumna sareng kumaha bédana. Hayu urang angka eta kaluar.

Kebon Binatang

Lima murid sareng tilu toko nilai konci anu disebarkeun

Konci-konci disusun kana tangkal jeung disebut titik. Sasuai, pikeun node Anjeun bisa meunangkeun daptar barudak na. Operasi nyieun znode a (nyieun) jeung ngarobah hiji nilai (setData) dipisahkeun: ngan konci aya bisa dibaca tur dirobah. Arloji tiasa digantelkeun kana operasi mariksa ayana titik, maca nilai, sareng kéngingkeun murangkalih. Watch mangrupikeun pemicu hiji waktos anu hurung nalika versi data anu aya dina server robih. Titik ephemeral dianggo pikeun ngadeteksi gagalna. Aranjeunna dihijikeun ka sési klien anu nyiptakeunana. Nalika klien nutup sési atawa eureun ngabéjaan ZooKeeper ngeunaan ayana, titik ieu otomatis dihapus. Transaksi saderhana dirojong - sakumpulan operasi anu sadayana suksés atanapi gagal upami ieu teu mungkin pikeun sahenteuna salah sahijina.

jsb

Lima murid sareng tilu toko nilai konci anu disebarkeun

Pamekar tina sistem ieu jelas diideuan ku ZooKeeper, sahingga ngalakukeun sagalana béda. Henteu aya hirarki konci, tapi aranjeunna ngabentuk set anu disusun sacara leksikografis. Anjeun tiasa kéngingkeun atanapi ngahapus sadaya konci anu aya dina rentang anu tangtu. Struktur ieu sigana aneh, tapi sabenerna pisan ekspresif, sarta pintonan hirarki bisa gampang ditiru ngaliwatan eta.

etcd teu boga operasi ngabandingkeun-sareng-set baku, tapi boga hal hadé: transaksi. Tangtu, aranjeunna aya dina sakabéh tilu sistem, tapi transaksi etcd utamana alus. Éta diwangun ku tilu blok: cek, kasuksésan, gagal. Blok kahiji ngandung sakumpulan kaayaan, kadua sareng katilu - operasi. Transaksi dieksekusi sacara atom. Upami sadaya kaayaan leres, maka blok kasuksésan dieksekusi, upami henteu blok gagal dieksekusi. Dina API 3.3, blok kasuksésan sareng kagagalan tiasa ngandung transaksi nested. Hartina, kasebut nyaéta dimungkinkeun pikeun atom ngaéksekusi constructs kondisional tina tingkat nyarang ampir sawenang. Anjeun tiasa langkung jéntré ngeunaan cék sareng operasi naon anu aya dokuméntasi.

Jam tangan ogé aya di dieu, sanaos aranjeunna langkung rumit sareng tiasa dianggo deui. Nyaéta, saatos masang arloji dina rentang konci, anjeun bakal nampi sadaya apdet dina rentang ieu dugi ka ngabatalkeun arloji, sanés ngan ukur anu munggaran. Dina jsb, analog tina sesi klien ZooKeeper nyaéta ngajakan.

Konsul K.V.

Henteu aya ogé struktur hirarki anu ketat di dieu, tapi Konsul tiasa nyiptakeun penampilan anu aya: anjeun tiasa kéngingkeun sareng ngahapus sadaya konci kalayan awalan anu ditangtukeun, nyaéta, damel sareng "subtree" konci. queries sapertos disebut rekursif. Salaku tambahan, Konsul ngan ukur tiasa milih konci anu henteu ngandung karakter anu ditangtukeun saatos awalan, anu pakait sareng kéngingkeun "barudak" langsung. Tapi sia remembering yén ieu téh persis penampilan struktur hirarki: cukup mungkin pikeun nyieun konci lamun indungna teu aya atawa ngahapus konci nu boga anak, bari barudak bakal terus disimpen dina sistem.

Lima murid sareng tilu toko nilai konci anu disebarkeun
Gantina arloji, Konsul geus blocking requests HTTP. Intina, ieu mangrupikeun telepon biasa pikeun metode maca data, dimana, sareng parameter sanésna, versi data anu terakhir anu dipikanyaho dituduhkeun. Upami versi ayeuna tina data anu aya dina server langkung ageung tibatan anu ditangtukeun, réspon langsung dipulangkeun, upami henteu - nalika nilaina robih. Aya ogé sesi anu tiasa digantelkeun kana konci iraha waé. Perhatos yén teu sapertos etcd sareng ZooKeeper, dimana ngahapus sési nyababkeun ngahapus konci anu aya hubunganana, aya mode dimana sési éta ngan saukur teu aya hubunganana. Aya transaksi, tanpa dahan, tapi kalayan sagala rupa cék.

Putting eta sadayana babarengan

ZooKeeper boga model data paling rigorous. Patarosan rentang ekspresif sadia dina jsb teu bisa éféktif emulated boh ZooKeeper atawa Konsul. Nyobian ngalebetkeun anu pangsaéna tina sadaya jasa, kami ngagaduhan antarmuka anu ampir sami sareng antarmuka ZooKeeper kalayan pengecualian anu penting di handap ieu:

  • runtuyan, wadahna sarta titik TTL teu dirojong
  • ACLs teu dirojong
  • métode set nyiptakeun konci lamun teu aya (dina ZK setData mulih kasalahan dina hal ieu)
  • set sareng metode cas dipisahkeun (dina ZK aranjeunna dasarna sami)
  • Metoda mupus mupus hiji titik sareng subtree na (dina ZK hapus ngabalikeun kasalahan upami node ngagaduhan murangkalih)
  • Pikeun unggal konci ngan aya hiji versi - versi nilai (dina ZK aya tilu diantarana)

Panolakan tina titik sequential téh alatan kanyataan yén etcd na Konsul teu boga diwangun-di rojongan pikeun aranjeunna, sarta aranjeunna bisa gampang dilaksanakeun ku pamaké dina luhureun panganteur perpustakaan hasilna.

Palaksanaan kabiasaan sarupa ZooKeeper nalika mupus vertex a bakal merlukeun ngajaga counter anak misah pikeun tiap konci dina etcd na Konsul. Kusabab urang diusahakeun ulah nyimpen informasi meta, éta mutuskeun pikeun ngahapus sakabéh subtree.

Subtleties palaksanaan

Hayu urang tingali sababaraha aspék palaksanaan antarmuka perpustakaan dina sistem anu béda.

Hierarki di jsb

Ngajaga pandangan hierarki di jsb tétéla janten salah sahiji tugas anu paling pikaresepeun. Paménta rentang ngagampangkeun pikeun nyandak daptar konci kalayan awalan anu ditangtukeun. Contona, upami anjeun peryogi sagalana nu dimimitian ku "/foo", anjeun nanyakeun rentang ["/foo", "/fop"). Tapi ieu bakal balik sakabéh subtree konci, nu bisa jadi teu bisa ditarima lamun subtree badag. Mimitina urang ngarencanakeun ngagunakeun mékanisme tarjamahan konci, dilaksanakeun dina zetcd. Ieu ngawengku nambahkeun hiji bait di awal konci, sarua jeung jero titik dina tangkal. Hayu atuh masihan anjeun conto.

"/foo" -> "u01/foo"
"/foo/bar" -> "u02/foo/bar"

Lajeng meunang sakabeh barudak saharita konci "/foo" mungkin ku requesting rentang ["u02/foo/", "u02/foo0"). Leres, dina ASCII "0" nangtung katuhu sanggeus "/".

Tapi kumaha carana nerapkeun panyabutan vertex dina hal ieu? Tétéla anjeun kedah mupus sadaya rentang jinisna ["uXX/foo/", "uXX/foo0") pikeun XX ti 01 nepi ka FF. Lajeng urang lumpat kana wates angka operasi dina hiji transaksi.

Hasilna, sistem konversi konci basajan ieu nimukeun, nu ngamungkinkeun pikeun éféktif ngalaksanakeun duanana mupus konci jeung meunangkeun daptar barudak. Ieu cukup pikeun nambahkeun karakter husus saméméh token panungtungan. Salaku conto:

"/very" -> "/u00very"
"/very/long" -> "/very/u00long"
"/very/long/path" -> "/very/long/u00path"

Lajeng mupus konci "/very" robah jadi ngahapus "/u00very" jeung rentang ["/very/", "/very0"), sarta meunang sagala barudak - dina pamundut konci ti rentang ["/very/u00", "/very/u01").

Nyoplokkeun konci dina ZooKeeper

Sakumaha anu kuring parantos nyarios, dina ZooKeeper anjeun moal tiasa ngahapus titik upami gaduh murangkalih. Kami hoyong mupus konci sareng subtree. Naon anu kedah abdi lakukeun? Urang ngalakukeun ieu kalawan optimism. Kahiji, urang recursively meuntas subtree, meunangkeun barudak unggal vertex kalawan query misah. Teras we ngawangun transaksi anu nyobian ngahapus sadaya titik subtree dina urutan anu leres. Tangtosna, parobahan tiasa lumangsung antara maca subtree sareng ngahapus. Dina hal ieu, urus bakal gagal. Sumawona, subtree tiasa robih salami prosés maca. Paménta pikeun murangkalih tina titik salajengna tiasa ngabalikeun kasalahan upami, contona, titik ieu parantos dihapus. Dina duanana kasus, urang ngulang sakabéh prosés deui.

Pendekatan ieu ngajadikeun ngahapus konci teu epektip pisan upami gaduh murangkalih, komo deui upami aplikasina terus damel sareng subtree, ngahapus sareng nyiptakeun konci. Sanajan kitu, ieu diwenangkeun urang ulah complicating palaksanaan métode séjénna di etcd na Konsul.

disetel dina ZooKeeper

Dina ZooKeeper aya metode anu misah anu tiasa dianggo sareng struktur tangkal (nyieun, ngahapus, getChildren) sareng anu tiasa dianggo sareng data dina titik (setData, getData). geus dijieun, ngahapus atawa setData - lamun teu acan aya. Urang diperlukeun metoda set nu bisa disebut tanpa pamikiran ngeunaan ayana konci a.

Salah sahiji pilihan nyaéta nyandak pendekatan optimis, sapertos ngahapus. Pariksa naha aya titik. Lamun aya, nelepon setData, disebutkeun nyieun. Upami metodeu terakhir ngabalikeun kasalahan, malikan deui sadayana. Hal kahiji anu kedah diperhatoskeun nyaéta uji ayana henteu aya gunana. Anjeun tiasa langsung nelepon nyieun. Parantosan suksés hartosna yén titik éta henteu aya sareng éta diciptakeun. Upami teu kitu, nyiptakeun bakal mulangkeun kasalahan anu sasuai, saatos anjeun kedah nyauran setData. Tangtu, antara telepon, vertex bisa dihapus ku panggero competing, sarta setData ogé bakal balik kasalahan. Dina hal ieu, anjeun tiasa ngalakukeun deui sadayana, tapi naha éta patut?

Upami duanana padika ngabalikeun kasalahan, maka urang terang pasti yén penghapusan anu saingan lumangsung. Hayu urang ngabayangkeun yén ngahapus ieu lumangsung sanggeus nelepon set. Lajeng naon hartina urang nyoba ngadegkeun geus dihapus. Ieu ngandung harti yén urang bisa nganggap yén set ieu dieksekusi junun, sanajan kanyataanna euweuh ditulis.

Langkung rinci téknis

Dina bagian ieu urang bakal nyandak putus tina sistem disebarkeun sarta ngobrol ngeunaan coding.
Salah sahiji sarat utama palanggan nyaéta cross-platform: sahenteuna salah sahiji jasa kedah dirojong dina Linux, MacOS sareng Windows. Mimitina, urang ngembangkeun ngan pikeun Linux, teras mimiti nguji dina sistem anu sanés engké. Ieu nyababkeun seueur masalah, anu pikeun sababaraha waktos henteu écés kumaha pendekatanna. Hasilna, tilu jasa koordinasi ayeuna dirojong dina Linux sareng MacOS, sedengkeun ngan Konsul KV anu dirojong dina Windows.

Ti mimiti, urang nyobaan ngagunakeun perpustakaan siap-dijieun pikeun ngakses jasa. Dina kasus ZooKeeper, pilihan murag ZooKeeper C++, nu tungtungna gagal pikeun compile on Windows. Ieu, kumaha oge, teu heran: perpustakaan ieu diposisikan salaku linux-hijina. Pikeun Konsul hijina pilihan éta ppkonsul. Pangrojong kedah ditambah kana éta sési и transaksi. Pikeun jsb, perpustakaan full-fledged ngarojong versi panganyarna tina protokol teu kapanggih, jadi urang ngan saukur dihasilkeun grpc klien.

Diideuan ku panganteur Asynchronous perpustakaan ZooKeeper C ++, urang mutuskeun hiji ogé nerapkeun panganteur Asynchronous. ZooKeeper C ++ ngagunakeun masa depan / janji primitif pikeun ieu. Dina STL, hanjakalna, aranjeunna dilaksanakeun pisan modestly. Contona, henteu lajeng métode, anu nerapkeun fungsi anu diliwatan kana hasil anu bakal datang nalika sayogi. Dina kasus urang, metoda ieu diperlukeun pikeun ngarobah hasil kana format perpustakaan urang. Pikeun ngarengsekeun masalah ieu, urang kedah nerapkeun kolam renang benang basajan urang sorangan, sabab dina pamundut palanggan urang teu tiasa nganggo perpustakaan pihak katilu anu beurat sapertos Boost.

Palaksanaan urang teras dianggo sapertos kieu. Lamun disebut, hiji janji tambahan / pasangan hareup dijieun. Masa depan anyar dipulangkeun, sareng anu lulus disimpen sareng fungsi anu saluyu sareng janji tambahan dina antrian. A thread ti kolam renang nu milih sababaraha futures ti antrian jeung polling aranjeunna ngagunakeun wait_for. Nalika hasilna sadia, fungsi nu saluyu disebut tur nilai balik na dibikeun ka jangji.

Kami nganggo kolam renang benang anu sami pikeun ngalaksanakeun patarosan ka etcd sareng Konsul. Ieu ngandung harti yén perpustakaan dasar bisa diaksés ku sababaraha threads béda. ppconsul teu thread aman, jadi nelepon ka eta ditangtayungan ku konci.
Anjeun tiasa damel sareng grpc tina sababaraha benang, tapi aya subtleties. Dina arloji etcd dilaksanakeun via aliran grpc. Ieu mangrupikeun saluran dua arah pikeun pesen tina jinis anu tangtu. Perpustakaan nyiptakeun benang tunggal pikeun sadaya jam tangan sareng benang tunggal anu ngolah pesen anu asup. Janten grpc ngalarang nyerat paralel pikeun ngalirkeun data. Ieu ngandung harti yén nalika ngamimitian atanapi ngahapus arloji, anjeun kedah ngantosan dugi ka pamundut sateuacana réngsé ngirim sateuacan ngirim anu salajengna. Kami nganggo pikeun singkronisasi variabel kondisional.

hasil

Tingali sorangan: liboffkv.

Tim kami: Raed Romanov, Ivan Glushenkov, Dmitry Kamaldinov, Victor Krapivensky, Vitaly Ivanin.

sumber: www.habr.com

Tambahkeun komentar