Rattapaaride hajutatud register: kogemus Hyperledgeri kangaga

Tere, töötan projekti DRD KP meeskonnas (hajutatud andmeregister rattakomplektide elutsükli jälgimiseks). Siin tahan jagada meie meeskonna kogemust selle projekti jaoks ettevõtte plokiahela väljatöötamisel tehnoloogia piirangute alusel. Peamiselt räägin Hyperledger Fabricust, kuid siin kirjeldatud lähenemist saab ekstrapoleerida mis tahes lubatud plokiahelale. Meie uurimistöö lõppeesmärk on valmistada ette ettevõtte plokiahela lahendused, et lõpptoode oleks meeldiv kasutada ja seda poleks liiga keeruline hooldada.

Siin ei ole avastusi, ootamatuid lahendusi ega unikaalseid arenguid esile tõstetud (sest mul pole neid). Tahan lihtsalt jagada oma tagasihoidlikku kogemust, näidata, et "see oli võimalik" ja võib-olla lugeda kommentaaridest teiste inimeste kogemusi heade ja mitte nii heade otsuste tegemisel.

Probleem: plokiahelad ei skaleeri veel

Tänapäeval on paljude arendajate jõupingutused suunatud sellele, et plokiahelast saaks tõeliselt mugav tehnoloogia, mitte viitsütikuga pomm ilusas ümbrises. Olekukanalid, optimistlik kokkuvõte, plasma ja killustamine muutuvad ilmselt igapäevaseks. Mõni päev. Või võib-olla lükkab TON taas käivitamise kuue kuu võrra edasi ja järgmine Plasma Group lakkab olemast. Me võime uskuda järgmisse tegevuskavasse ja lugeda öösel hiilgavaid valgeid pabereid, kuid siin ja praegu on vaja midagi ette võtta sellega, mis meil on. Tee jama ära.

Praeguses projektis meie meeskonnale seatud ülesanne näeb üldjoontes välja selline: on palju subjekte, mis ulatuvad mitme tuhandeni, kes ei taha suhteid usaldusele rajada; DLT-le on vaja ehitada lahendus, mis töötaks tavalistes arvutites ilma eriliste jõudlusnõueteta ja pakuks kasutajakogemust, mis pole halvem kui mis tahes tsentraliseeritud raamatupidamissüsteemid. Lahenduse taga olev tehnoloogia peab minimeerima võimalust andmetega pahatahtlikuks manipuleerimiseks – seepärast ongi plokiahel siin.

Valgete lehtede ja meedia loosungid lubavad meile, et järgmine arendus võimaldab teha miljoneid tehinguid sekundis. Mis see tegelikult on?

Mainnet Ethereum töötab hetkel ~30 tps juures. Juba ainuüksi seetõttu on seda keeruline tajuda plokiahelana mis tahes viisil, mis sobib ettevõtte vajadustega. Lubatud lahenduste hulgas on etalonid, mis näitavad 2000 tps (Kvoorum) või 3000 tps (Hyperledger kangas, on väljaandes veidi vähem, kuid peate arvestama, et võrdlusanalüüs viidi läbi vanal konsensusmootoril). Oli Kanga radikaalse töötlemise katse, mis ei andnud just kõige halvemaid tulemusi, 20000 XNUMX tps, kuid seni on see vaid akadeemiline uurimus, mis ootab selle stabiilset rakendamist. On ebatõenäoline, et ettevõte, kes suudab endale lubada plokiahela arendajate osakonna ülalpidamist, selliste näitajatega talub. Kuid probleem pole mitte ainult läbilaskevõimes, vaid ka latentsuses.

Hilinemine

Viivitus tehingu algatamise hetkest kuni selle lõpliku kinnitamiseni süsteemi poolt ei sõltu ainult kiirusest, millega sõnum läbib kõik valideerimise ja tellimise etapid, vaid ka ploki moodustamise parameetritest. Isegi kui meie plokiahel võimaldab meil pühenduda kiirusega 1000000 10 488 tps, kuid XNUMX MB ploki genereerimiseks kulub XNUMX minutit, muutub see meie jaoks lihtsamaks?

Vaatame lähemalt Hyperledger Fabricu tehingu elutsüklit, et mõista, kuhu aega kulutatakse ja kuidas see on seotud ploki genereerimise parameetritega.

Rattapaaride hajutatud register: kogemus Hyperledgeri kangaga
siit võetud: hyperledger-fabric.readthedocs.io/en/release-1.4/arch-deep-dive.html#swimlane

(1) Klient loob tehingu, saadab selle kinnitavatele partneritele, viimased simuleerivad tehingut (rakendavad ahelkoodiga tehtud muudatused praegusele olekule, kuid ei seo pearaamatusse) ja saavad RWSet – võtmenimed, versioonid ja väärtused ​​võetud CouchDB kogust, (2) kinnitajad saadavad kliendile allkirjastatud RWSeti tagasi, (3) klient kas kontrollib kõigi vajalike partnerite allkirjade olemasolu ja saadab seejärel tehingu tellimisteenusele. , või saadab selle kontrollimata (kontroll toimub ikkagi hiljem), tellimisteenus moodustab ploki ja (4) saadab tagasi kõigile partneritele, mitte ainult kinnitajatele; kaaslased kontrollivad, et lugemiskomplekti võtmeversioonid ühtivad andmebaasis olevate versioonidega, kas kõigil kinnitajatel on allkirjad, ja lõpuks panevad bloki toime.

Kuid see pole veel kõik. Sõnad “tellija moodustab ploki” peidavad mitte ainult tehingute järjestamist, vaid ka 3 järjestikust võrgupäringut juhilt jälgijatele ja tagasi: juht lisab logisse teate, saadab selle jälgijatele, viimane lisab selle. nende logisse, saadab juhile kinnituse eduka replikatsiooni kohta, juht kinnitab sõnumi, saadab jälgijatele sidumiskinnituse, jälgijad kohustuvad. Mida väiksem on ploki moodustamise suurus ja aeg, seda sagedamini peab tellimisteenus saavutama konsensuse. Hyperledger Fabricul on ploki moodustamiseks kaks parameetrit: BatchTimeout – ploki moodustamise aeg ja BatchSize – ploki suurus (tehingute arv ja ploki enda suurus baitides). Niipea kui üks parameetritest jõuab piirini, vabastatakse uus plokk. Mida rohkem tellimissõlmi, seda kauem see aega võtab. Seetõttu peate suurendama BatchTimeout ja BatchSize. Kuid kuna RWSetid on versioonitud, siis mida suurema ploki teeme, seda suurem on MVCC konfliktide tõenäosus. Lisaks, kui BatchTimeout suureneb, halveneb UX katastroofiliselt. Järgnev skeem nende probleemide lahendamiseks tundub mulle mõistlik ja ilmne.

Kuidas vältida ploki lõpetamise ootamist ja mitte kaotada võimalust jälgida tehingu olekut

Mida pikem on moodustamise aeg ja ploki suurus, seda suurem on plokiahela läbilaskevõime. Üks ei tulene teisest otseselt, kuid tuleb meeles pidada, et konsensuse saavutamine RAFT-is nõuab kolme võrgupäringut juhilt järgijatele ja tagasi. Mida rohkem tellimissõlmi, seda kauem see aega võtab. Mida väiksem on plokkide moodustumise suurus ja aeg, seda rohkem on selliseid interaktsioone. Kuidas suurendada genereerimisaega ja ploki suurust ilma lõppkasutaja jaoks süsteemi reageerimisaega suurendamata?

Esiteks peame kuidagi lahendama suurest ploki suurusest põhjustatud MVCC konfliktid, mis võivad sisaldada erinevaid sama versiooniga RWSete. Ilmselgelt vajate kliendi poolel (seoses plokiahela võrguga võib see olla taustaprogramm ja ma mõtlen seda tõsiselt) MVCC konfliktide käsitleja, mis võib olla kas eraldi teenus või tavaline dekoraator kõne kohal, mis uuesti proovimise loogikaga tehingu algatab.

Uuesti proovimist saab rakendada eksponentsiaalse strateegiaga, kuid siis väheneb latentsusaeg sama eksponentsiaalselt. Seega peaksite kasutama kas juhuslikku korduskatset teatud väikestes piirides või konstantset proovimist. Silmaga võimalikele kokkupõrgetele esimeses variandis.

Järgmise sammuna tuleb muuta kliendi suhtlus süsteemiga asünkroonseks, et see ei ootaks 15, 30 või 10000000 sekundit, mille määrame BatchTimeout. Kuid samal ajal on vaja säilitada võimalus kontrollida, et tehinguga algatatud muudatused on/ei ole plokiahelas fikseeritud.
Tehingu oleku salvestamiseks saab kasutada andmebaasi. Lihtsaim valik on CouchDB tänu selle kasutuslihtsusele: andmebaasil on karbist väljas kasutajaliides, REST API ning selle jaoks saab hõlpsasti seadistada replikatsiooni ja jagamise. Saate lihtsalt luua samas CouchDB eksemplaris eraldi kogu, mis kasutab Fabricit oma maailma oleku salvestamiseks. Peame seda tüüpi dokumente salvestama.

{
 Status string // Статус транзакции: "pending", "done", "failed"
 TxID: string // ID транзакции
 Error: string // optional, сообщение об ошибке
}

See dokument kirjutatakse andmebaasi enne tehingu saatmist partneritele, olemi ID tagastatakse kasutajale (sama ID-d kasutatakse võtmena), kui tegemist on loomistoiminguga, seejärel kuvatakse väljad Status, TxID ja Error ajakohastatakse, kui kaaslastelt saadakse asjakohast teavet.

Rattapaaride hajutatud register: kogemus Hyperledgeri kangaga

Selle skeemi puhul ei oota kasutaja ploki lõplikku moodustumist, jälgides 10 sekundit ekraanil pöörlevat ratast, saab ta süsteemilt kohese vastuse ja jätkab tööd.

Valisime tehinguolekute salvestamiseks BoltDB, kuna peame säästma mälu ja ei taha raisata aega võrgu suhtlemisele eraldi andmebaasiserveriga, eriti kui see interaktsioon toimub lihtteksti protokolli kasutades. Muide, olenemata sellest, kas kasutate CouchDB-d ülalkirjeldatud skeemi rakendamiseks või lihtsalt maailma oleku salvestamiseks, on igal juhul mõistlik optimeerida andmete CouchDB-s salvestamise viisi. Vaikimisi on CouchDB-s b-puu sõlmede suurus 1279 baiti, mis on palju väiksem ketta sektori suurusest, mis tähendab, et nii puu lugemine kui ka tasakaalustamine nõuab rohkem füüsilist juurdepääsu kettale. Optimaalne suurus vastab standardile Täpsem vorming ja on 4 kilobaiti. Optimeerimiseks peame määrama parameetri btree_chunk_size võrdub 4096-ga CouchDB konfiguratsioonifailis. BoltDB puhul selline käsitsi sekkumine pole nõutav.

Vasturõhk: puhverstrateegia

Kuid sõnumeid võib olla palju. Rohkem, kui süsteem suudab hakkama saada, jagades ressursse kümnekonna muu teenusega peale diagrammil näidatute – ja see kõik peaks laitmatult töötama ka masinates, millel Intellij Idea töötamine oleks äärmiselt tüütu.

Kommunikatsioonisüsteemide, tootja ja tarbija erineva võimekuse probleemi lahendatakse erineval viisil. Vaatame, mida saaksime teha.

Kukkumine: Võime väita, et suudame T sekundi jooksul töödelda kuni X tehingut. Kõik seda limiiti ületavad taotlused lükatakse tagasi. See on üsna lihtne, kuid siis võite UX-i unustada.

Kontrollimine: tarbijal peab olema mingi liides, mille kaudu ta saab sõltuvalt koormusest juhtida tootja TPS-i. Pole paha, kuid seab koormust loova kliendi arendajatele kohustusi selle liidese juurutamiseks. See on meie jaoks vastuvõetamatu, kuna plokiahel integreeritakse tulevikus paljudesse pikka aega eksisteerivatesse süsteemidesse.

Puhverdamine: Selle asemel, et püüda sisendandmevoogu vastu seista, saame selle voo puhverdada ja vajaliku kiirusega töödelda. Ilmselgelt on see parim lahendus, kui tahame pakkuda head kasutajakogemust. Rakendasime puhvri RabbitMQ-s järjekorra abil.

Rattapaaride hajutatud register: kogemus Hyperledgeri kangaga

Skeemi on lisatud kaks uut toimingut: (1) pärast API päringu saabumist pannakse järjekorda teade tehingu välja kutsumiseks vajalike parameetritega ja klient saab teate, et tehing on aktsepteeritud süsteem, (2) taustaprogramm loeb andmeid konfiguratsioonis määratud kiirusega järjekorrast; algatab tehingu ja värskendab andmeid olekusalves.
Nüüd saate moodustamise aega pikendada ja võimsust blokeerida nii palju kui soovite, varjates kasutaja eest viivitusi.

Muud tööriistad

Ahelkoodi kohta siin midagi ei räägitud, sest reeglina pole selles midagi optimeerida. Ketikood peaks olema võimalikult lihtne ja turvaline – see on kõik, mida sellelt nõutakse. Raamistik aitab meil ahelkoodi lihtsalt ja ohutult kirjutada CCKit S7 Techlabilt ja staatilisest analüsaatorist elustada^CC.

Lisaks töötab meie meeskond välja utiliitide komplekti, et muuta Fabricuga töötamine lihtsaks ja nauditavaks: plokiahela uurija, utiliit automaatsed võrgukonfiguratsiooni muudatused (organisatsioonide lisamine/eemaldamine, RAFT-sõlmed), utiliit sertifikaatide kehtetuks tunnistamine ja identiteedi eemaldamine. Kui soovid panustada, oled oodatud.

Järeldus

See lähenemine võimaldab teil hõlpsasti asendada Hyperledger Fabric Quorumi, teiste privaatsete Ethereumi võrkudega (PoA või isegi PoW), vähendada oluliselt tegelikku läbilaskevõimet, kuid samal ajal säilitada normaalne UX (nii brauseris olevate kasutajate kui ka integreeritud süsteemide jaoks). Kui asendate Fabrici skeemis Ethereumiga, peate muutma ainult prooviteenuse/dekoraatori loogikat MVCC-konfliktide töötlemiselt aatomite arvu suurendamise ja uuesti saatmise asemel. Puhverdamine ja oleku salvestamine võimaldasid reageerimisaja lahti siduda ploki moodustamise ajast. Nüüd saate lisada tuhandeid tellimissõlmi ja mitte karta, et plokke moodustub liiga sageli ja koormate tellimisteenust.

Põhimõtteliselt on see kõik, mida ma jagada tahtsin. Mul on hea meel, kui see aitab kedagi nende töös.

Allikas: www.habr.com

Lisa kommentaar