Distribuita Registro por Radoj: Sperto kun Hyperledger Fabric

Saluton, mi laboras en la teamo de la projekto DRD KP (distribuita datuma registro por monitorado de la vivociklo de radoj). Ĉi tie mi volas dividi la sperton de nia teamo pri evoluigado de entreprena blokĉeno por ĉi tiu projekto sub la limoj de teknologio. Mi plejparte parolos pri la Hyperledger Fabric, sed la aliro priskribita ĉi tie povas esti eksterpolita al iu ajn permesata blokĉeno. La fina celo de nia esplorado estas prepari entreprenajn blokĉenajn solvojn por ke la fina produkto estu agrabla uzi kaj ne tro malfacila por konservi.

Ne estos malkovroj, neatenditaj solvoj, kaj neniuj unikaj evoluoj estos reliefigitaj ĉi tie (ĉar mi ne havas). Mi volas nur konigi mian modestan sperton, montri, ke "eblis" kaj, eble, legi pri la spertoj de aliaj homoj pri fari bonajn kaj ne tiom bonajn decidojn en la komentoj.

Problemo: Blokĉenoj ankoraŭ ne skalas

Hodiaŭ, la klopodoj de multaj programistoj celas fari blokĉenon vere oportuna teknologio, kaj ne horloĝbombo en bela envolvaĵo. Ŝtataj kanaloj, optimisma kunigo, plasmo kaj sharding povas iĝi ordinaraj. Iun tagon. Aŭ eble TON denove prokrastos la lanĉon dum ses monatoj, kaj la sekva Plasma Grupo ĉesos ekzisti. Ni povas kredi je la sekva vojmapo kaj legi brilajn blankajn librojn nokte, sed ĉi tie kaj nun ni devas fari ion kun tio, kion ni havas. Faru fekon.

La tasko fiksita por nia teamo en la nuna projekto aspektas ĝenerale tiel: estas multaj subjektoj, atingantaj kelkmil, kiuj ne volas konstrui rilatojn sur fido; Estas necese konstrui solvon sur DLT, kiu funkcios sur ordinaraj komputiloj sen specialaj agado-postuloj kaj havigos uzantan sperton ne pli malbonan ol iuj centralizitaj kontadaj sistemoj. La teknologio malantaŭ la solvo devas minimumigi la eblecon de malica manipulado de datumoj - tial blokĉeno estas ĉi tie.

Sloganoj de blankpaperoj kaj amaskomunikiloj promesas al ni, ke la venonta evoluo permesos al ni fari milionojn da transakcioj por sekundo. Kio estas vere?

Mainnet Ethereum nuntempe funkcias ĉe ~30 tps. Pro tio sole, estas malfacile percepti ĝin kiel blokĉeno iel ajn taŭga por kompaniaj bezonoj. Inter permesitaj solvoj estas komparnormoj montrantaj 2000 tps (Kvorumo) aŭ 3000 tps (Hyperledger Fabric, estas iom malpli en la publikigo, sed vi devas konsideri, ke la komparnormo estis efektivigita sur la malnova konsenta motoro). Estis provo de radikala traktado de Ŝtofo, kiu ne donis la plej malbonajn rezultojn, 20000 tps, sed ĝis nun tio estas nur akademia esplorado, atendante ĝian stabilan efektivigon. Estas neverŝajne, ke korporacio, kiu povas pagi konservi fakon de blokĉenaj programistoj, toleros tiajn indikilojn. Sed la problemo ne estas nur trapaso, ankaŭ ekzistas latencia.

atendotempo

La malfruo de la momento, kiam transakcio estas komencita ĝis ĝia fina aprobo de la sistemo, dependas ne nur de la rapideco, kun kiu la mesaĝo pasas tra ĉiuj etapoj de validigo kaj mendado, sed ankaŭ de la parametroj de blokformado. Eĉ se nia blokĉeno ebligas al ni engaĝiĝi kun rapido de 1000000 tps, sed postulas 10 minutojn por generi 488 MB-blokon, ĉu ĝi fariĝos pli facila por ni?

Ni rigardu pli proksime al la transakcia vivociklo en Hyperledger Fabric por kompreni kie tempo estas pasigita kaj kiel ĝi rilatas al blokgeneraciaj parametroj.

Distribuita Registro por Radoj: Sperto kun Hyperledger Fabric
prenita de ĉi tie: hyperledger-fabric.readthedocs.io/en/release-1.4/arch-deep-dive.html#swimlane

(1) La kliento kreas transakcion, sendas ĝin al aprobantaj samuloj, ĉi-lastaj simulas la transakcion (apliku ŝanĝojn faritajn per ĉenkodo al la nuna stato, sed ne kompromitas al la ĉeflibro) kaj ricevas RWSet - ŝlosilaj nomoj, versioj kaj valoroj. prenitaj el la kolekto en CouchDB, (2) apogantoj resendas subskribitan RWSet al la kliento, (3) la kliento aŭ kontrolas la ĉeeston de subskriboj de ĉiuj necesaj kunuloj (subtenantoj), kaj tiam sendas la transakcion al la menda servo. , aŭ sendas ĝin sen konfirmo (la kontrolo ankoraŭ okazos poste), la mendservo formas blokon kaj ( 4) resendas al ĉiuj kunuloj, ne nur apogantoj; samuloj kontrolas, ke la ŝlosilaj versioj en la legita aro kongruas kun la versioj en la datumbazo, ke ĉiuj apogantoj havas subskribojn, kaj finfine transigas la blokon.

Sed tio ne estas ĉio. La vortoj "mendanto formas blokon" kaŝas ne nur la ordigon de transakcioj, sed ankaŭ 3 sinsekvajn retajn petojn de la gvidanto al la sekvantoj kaj reen: la gvidanto aldonas mesaĝon al la protokolo, sendas ĝin al la sekvantoj, ĉi-lasta aldonas ĝin. al ilia protokolo, sendas konfirmon pri sukcesa reproduktado al la gvidanto, la gvidanto transigas la mesaĝon , sendas konfirmon al sekvantoj, sekvantoj transigas. Ju pli malgranda estas la grandeco kaj tempo de blokformado, des pli ofte la menda servo devos establi konsenton. Hyperledger Fabric havas du parametrojn por blokformado: BatchTimeout - blokforma tempo kaj BatchSize - blokgrandeco (la nombro da transakcioj kaj la grandeco de la bloko mem en bajtoj). Tuj kiam unu el la parametroj atingas la limon, nova bloko estas liberigita. Ju pli da ordaj nodoj, des pli longe ĉi tio daŭros. Tial vi devas pliigi BatchTimeout kaj BatchSize. Sed ĉar RWSets estas versionita, ju pli granda la bloko ni faras, des pli alta la verŝajneco de MVCC-konfliktoj. Krome, kiam BatchTimeout pliiĝas, la UX katastrofe degradas. La sekva skemo por solvi ĉi tiujn problemojn ŝajnas al mi racia kaj evidenta.

Kiel eviti atendi blokan finiĝon kaj ne perdi la kapablon spuri transakcian statuson

Ju pli longa estas la formada tempo kaj bloka grandeco, des pli alta estas la trairo de la blokĉeno. Unu ne sekvas rekte de la alia, sed oni devas memori, ke establi konsenton en RAFT postulas tri retajn petojn de la gvidanto ĝis la sekvantoj kaj reen. Ju pli da ordaj nodoj, des pli longe ĉi tio daŭros. Ju pli malgrandaj estas la grandeco kaj tempo de blokformado, des pli tiaj interagoj ekzistas. Kiel pliigi la generaciotempon kaj blokan grandecon sen pliigi la sisteman respondtempon por la fina uzanto?

Unue, ni devas iel solvi MVCC-konfliktojn kaŭzitajn de granda bloka grandeco, kiu povas inkluzivi malsamajn RWS-arojn kun la sama versio. Evidente, ĉe la kliento (rilate al la blokĉena reto, ĉi tio bone povus esti la backend, kaj mi volas diri ĝin) vi bezonas MVCC-konflikttraktilo, kiu povas esti aŭ aparta servo aŭ regula dekoraciisto super la voko kiu iniciatas la transakcion kun reprova logiko.

Reprovi povas esti efektivigita kun eksponenta strategio, sed tiam latencia degradiĝos same eksponente. Do vi devus uzi aŭ randomigitan reprovon ene de certaj malgrandaj limoj, aŭ konstantan. Kun okulo sur eblaj kolizioj en la unua opcio.

La sekva paŝo estas fari la interagon de la kliento kun la sistemo nesinkrona por ke ĝi ne atendu 15, 30 aŭ 10000000 sekundojn, kiujn ni starigos kiel BatchTimeout. Sed samtempe, necesas konservi la kapablon kontroli, ke la ŝanĝoj komencitaj de la transakcio estas/ne estas registritaj en la blokĉeno.
Datumaro povas esti uzata por stoki transakcian staton. La plej simpla opcio estas CouchDB pro sia facileco de uzo: la datumbazo havas UI el la skatolo, REST API, kaj vi povas facile agordi reproduktadon kaj sharding por ĝi. Vi povas simple krei apartan kolekton en la sama CouchDB-instanco, kiu uzas Fabric por konservi sian mondan staton. Ni devas konservi ĉi tiujn specojn de dokumentoj.

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

Ĉi tiu dokumento estas skribita al la datumbazo antaŭ ol la transakcio estas sendita al samuloj, la enta ID estas resendita al la uzanto (la sama ID estas uzata kiel ŝlosilo) se ĉi tio estas krea operacio, kaj tiam la kampoj Statuso, TxID kaj Eraro estas. ĝisdatigita kiam koncernaj informoj estas ricevitaj de kunuloj.

Distribuita Registro por Radoj: Sperto kun Hyperledger Fabric

En ĉi tiu skemo, la uzanto ne atendas ke la bloko finfine formiĝos, rigardante la ŝpinilon sur la ekrano dum 10 sekundoj, li ricevas tujan respondon de la sistemo kaj daŭre funkcias.

Ni elektis BoltDB por stoki transakciajn statusojn ĉar ni bezonas ŝpari memoron kaj ne volas malŝpari tempon pri interagado de reto kun aparta datumbaza servilo, precipe kiam ĉi tiu interago okazas per simpla teksta protokolo. Cetere, ĉu vi uzas CouchDB por efektivigi la skemon priskribitan supre aŭ simple por stoki mondan staton, ĉiukaze havas sencon optimumigi la manieron konservi datumojn en CouchDB. Defaŭlte, en CouchDB, la grandeco de b-arbaj nodoj estas 1279 bajtoj, kio estas multe pli malgranda ol la sektorgrandeco sur la disko, kio signifas, ke ambaŭ legado kaj rebalancado de la arbo postulos pli fizikan aliron al la disko. La optimuma grandeco respondas al la normo Altnivela Formato kaj estas 4 kilobajtoj. Por optimumigi ni devas agordi la parametron btree_chunk_size egala al 4096 en la agorda dosiero CouchDB. Por BoltDB tia mana interveno ne postulita.

Kontrapremo: bufrostrategio

Sed povas esti multaj mesaĝoj. Pli ol la sistemo povas manipuli, kunhavigi rimedojn kun dekduo da aliaj servoj krom tiuj montritaj en la diagramo - kaj ĉio ĉi devus funkcii senmanke eĉ sur maŝinoj sur kiuj ruli Intellij Idea estus ege teda.

La problemo de malsama kapablo de komunikadsistemoj, produktanto kaj konsumanto, estas solvita en malsamaj manieroj. Ni vidu, kion ni povus fari.

Guto: Ni povas aserti, ke ni kapablas prilabori maksimume X-transakciojn en T sekundoj. Ĉiuj petoj superantaj ĉi tiun limon estas forĵetitaj. Ĉi tio estas sufiĉe simpla, sed tiam vi povas forgesi pri UX.

Kontrolado: la konsumanto devas havi ian interfacon per kiu, depende de la ŝarĝo, li povas kontroli la TPS de la produktanto. Ne malbone, sed ĝi trudas obligaciojn al la programistoj de la kliento kreante la ŝarĝon por efektivigi ĉi tiun interfacon. Ĉi tio estas neakceptebla por ni, ĉar blokĉeno estonte estos integrita al granda nombro da longe ekzistantaj sistemoj.

Bufado: Anstataŭ provi rezisti al la eniga datumfluo, ni povas bufri ĉi tiun fluon kaj prilabori ĝin je la bezonata rapideco. Evidente ĉi tio estas la plej bona solvo se ni volas provizi bonan sperton de uzanto. Ni efektivigis la bufron uzante voston en RabbitMQ.

Distribuita Registro por Radoj: Sperto kun Hyperledger Fabric

Du novaj agoj estis aldonitaj al la skemo: (1) post la alveno de peto al la API, mesaĝo kun la parametroj necesaj por voki transakcion estas metita en la atendovico, kaj la kliento ricevas mesaĝon, ke la transakcio estis akceptita de la sistemo, (2) la backend legas la datumojn je la rapideco specifita en la agordo de vosto; iniciatas transakcion kaj ĝisdatigas datumojn en la statusbutiko.
Nun vi povas pliigi la forman tempon kaj bloki kapaciton kiom vi volas, kaŝante prokrastojn de la uzanto.

Aliaj iloj

Nenio estis dirita ĉi tie pri ĉenkodo, ĉar, kiel regulo, estas nenio por optimumigi en ĝi. Ĉenkodo estu kiel eble plej simpla kaj sekura - jen ĉio, kio estas postulata de ĝi. La kadro helpas nin skribi ĉenkodon simple kaj sekure CCKit de S7 Techlab kaj statika analizilo revivi^CC.

Krome, nia teamo disvolvas aron da utilecoj por fari labori kun Fabric simpla kaj agrabla: blokĉena esploristo, utilo por aŭtomataj retaj agordaj ŝanĝoj (aldonante/forigante organizojn, RAFT-nodojn), utileco por revoko de atestiloj kaj forigo de identeco. Se vi volas kontribui, vi estas bonvena.

konkludo

Ĉi tiu aliro permesas vin facile anstataŭigi Hyperledger Fabric kun Quorum, aliaj privataj Ethereum-retoj (PoA aŭ eĉ PoW), signife redukti la realan trairon, sed samtempe konservi normalan UX (kaj por uzantoj en la retumilo kaj por integraj sistemoj). Anstataŭigante Ŝtofon kun Ethereum en la skemo, vi nur bezonos ŝanĝi la logikon de la reprova servo / dekoraciisto de prilaborado de MVCC-konfliktoj al atoma nonce pliigo kaj resendo. Bufrado kaj statusstokado ebligis malkunligi la respondtempon de la blokformadtempo. Nun vi povas aldoni milojn da mendaj nodoj kaj ne timi, ke blokoj formiĝas tro ofte kaj ŝarĝi la mendan servon.

Esence, tion mi volis dividi. Mi ĝojos, se ĉi tio helpos iun en ilia laboro.

fonto: www.habr.com

Aldoni komenton