رجیستری توزیع شده برای چرخ ها: تجربه ای با پارچه هایپرلجر

سلام، من در تیم پروژه DRD KP (رجیستری داده های توزیع شده برای نظارت بر چرخه عمر مجموعه های چرخ) کار می کنم. در اینجا می‌خواهم تجربه تیم خود را در توسعه یک بلاک چین سازمانی برای این پروژه تحت محدودیت‌های فناوری به اشتراک بگذارم. من بیشتر در مورد Hyperledger Fabric صحبت خواهم کرد، اما رویکردی که در اینجا توضیح داده شده را می توان به هر بلاک چین مجاز تعمیم داد. هدف نهایی تحقیق ما این است که راه حل های بلاک چین سازمانی را آماده کنیم تا استفاده از محصول نهایی خوشایند باشد و نگهداری آن چندان دشوار نباشد.

هیچ اکتشاف، راه حل غیرمنتظره ای وجود نخواهد داشت، و هیچ پیشرفت منحصر به فردی در اینجا برجسته نخواهد شد (زیرا من هیچ کدام را ندارم). من فقط می خواهم تجربه ساده خود را به اشتراک بگذارم، نشان دهم که "امکان پذیر بود" و، شاید، در مورد تجربیات دیگران از تصمیم گیری های خوب و نه چندان خوب در نظرات بخوانم.

مشکل: بلاک چین ها هنوز مقیاس نشده اند

امروزه، تلاش‌های بسیاری از توسعه‌دهندگان در جهت تبدیل بلاک چین به یک فناوری واقعا راحت است و نه یک بمب ساعتی در یک بسته بندی زیبا. کانال های حالت، جمع آوری خوش بینانه، پلاسما و شاردینگ احتمالاً عادی خواهند شد. یه روزی یا شاید TON دوباره راه اندازی را به مدت شش ماه به تعویق بیندازد و گروه پلاسما بعدی وجود نداشته باشد. می‌توانیم به نقشه راه بعدی ایمان داشته باشیم و شب‌ها روزنامه‌های سفید درخشان بخوانیم، اما اینجا و اکنون باید با آنچه داریم کاری انجام دهیم. کارتو انجام بده

وظیفه تعیین شده برای تیم ما در پروژه فعلی به طور کلی به این صورت است: افراد زیادی وجود دارند که به چندین هزار نفر می رسد که نمی خواهند روابطی را بر اساس اعتماد ایجاد کنند. لازم است راه حلی بر روی DLT ساخته شود که بر روی رایانه های شخصی معمولی بدون نیاز به عملکرد خاص کار کند و تجربه کاربری را بدتر از هر سیستم حسابداری متمرکز ارائه کند. فناوری پشت راه حل باید احتمال دستکاری مخرب داده ها را به حداقل برساند - به همین دلیل است که بلاک چین اینجاست.

شعارهای کاغذهای سفید و رسانه ها به ما این نوید را می دهند که توسعه بعدی به ما امکان می دهد میلیون ها تراکنش در ثانیه انجام دهیم. واقعا چیه؟

Mainnet Ethereum در حال حاضر با سرعت ~30 tps در حال اجرا است. به همین دلیل به تنهایی، درک آن به عنوان بلاک چین به هر نحوی که برای نیازهای شرکتی مناسب است دشوار است. در میان راه حل های مجاز، معیارهایی وجود دارد که 2000 tps را نشان می دهد (کوروم) یا 3000 tps (پارچه ای هیجان انگیز، کمی کمتر در انتشار وجود دارد، اما باید در نظر داشته باشید که معیار بر روی موتور اجماع قدیمی انجام شده است). بود تلاشی برای پردازش رادیکال پارچه، که بدترین نتایج را نداد ، 20000 tps ، اما تا کنون این فقط تحقیقات آکادمیک است و منتظر اجرای پایدار آن است. بعید است که شرکتی که بتواند از عهده اداره توسعه دهندگان بلاک چین برآید، چنین شاخص هایی را تحمل کند. اما مشکل تنها توان عملیاتی نیست، تاخیر نیز وجود دارد.

تاخیر

تأخیر از لحظه شروع تراکنش تا تأیید نهایی آن توسط سیستم نه تنها به سرعت عبور پیام از تمام مراحل اعتبار سنجی و سفارش بستگی دارد، بلکه به پارامترهای تشکیل بلوک نیز بستگی دارد. حتی اگر بلاک چین به ما اجازه دهد تا با سرعت 1000000 tps انجام دهیم، اما برای تولید یک بلوک 10 مگابایتی به 488 دقیقه زمان نیاز دارد، آیا این کار برای ما آسان تر خواهد شد؟

بیایید نگاهی دقیق‌تر به چرخه عمر تراکنش در Hyperledger Fabric بیندازیم تا بفهمیم زمان در کجا صرف می‌شود و چگونه با پارامترهای تولید بلوک ارتباط دارد.

رجیستری توزیع شده برای چرخ ها: تجربه ای با پارچه هایپرلجر
از اینجا گرفته شده: hyperledger-fabric.readthedocs.io/en/release-1.4/arch-deep-dive.html#swimlane

(1) مشتری یک تراکنش ایجاد می کند، آن را به همتایان تایید کننده می فرستد، دومی تراکنش را شبیه سازی می کند (تغییرات ایجاد شده توسط کد زنجیره ای را در وضعیت فعلی اعمال می کند، اما به دفتر کل تعهد نمی دهد) و RWSet - نام های کلیدی، نسخه ها و مقادیر را دریافت می کند. از مجموعه در CouchDB گرفته شده است، (2) تایید کنندگان یک RWSet امضا شده را برای مشتری ارسال می کنند، (3) مشتری یا وجود امضای همه همتایان لازم (تأیید کنندگان) را بررسی می کند و سپس تراکنش را به سرویس سفارش دهنده می فرستد. ، یا آن را بدون تأیید ارسال می کند (چک همچنان بعداً انجام می شود)، سرویس سفارش یک بلوک را تشکیل می دهد و (4) به همه همتایان، نه فقط تأیید کنندگان، باز می فرستد. همتایان بررسی می‌کنند که نسخه‌های کلیدی در مجموعه خوانده شده با نسخه‌های موجود در پایگاه داده مطابقت داشته باشند، آیا همه تأییدکننده‌ها دارای امضا هستند، و در نهایت بلوک را انجام می‌دهند.

اما این همه ماجرا نیست. کلمات "سفارش کننده یک بلوک را تشکیل می دهد" نه تنها ترتیب تراکنش ها، بلکه 3 درخواست متوالی شبکه از رهبر به دنبال کنندگان و برگشت را نیز پنهان می کند: رهبر یک پیام را به گزارش اضافه می کند، آن را به دنبال کنندگان می فرستد، دومی آن را اضافه می کند. به لاگ آنها، تأیید تکرار موفقیت آمیز را برای رهبر ارسال می کند، رهبر پیام را متعهد می کند، تأییدیه ارتکاب را به دنبال کنندگان می فرستد، فالوورها متعهد می شوند. هرچه اندازه و زمان تشکیل بلوک کوچکتر باشد، سرویس سفارش اغلب باید اجماع ایجاد کند. Hyperledger Fabric دو پارامتر برای تشکیل بلوک دارد: BatchTimeout - زمان تشکیل بلوک و BatchSize - اندازه بلوک (تعداد تراکنش ها و اندازه خود بلوک بر حسب بایت). به محض اینکه یکی از پارامترها به حد مجاز رسید، یک بلوک جدید آزاد می شود. هر چه تعداد نودهای سفارش بیشتر باشد، مدت زمان بیشتری طول خواهد کشید. بنابراین، باید BatchTimeout و BatchSize را افزایش دهید. اما از آنجایی که RWSet ها نسخه بندی شده اند، هر چه بلوک بزرگتر بسازیم، احتمال تداخل MVCC بیشتر می شود. علاوه بر این، با افزایش BatchTimeout، UX به طرز فاجعه‌باری کاهش می‌یابد. طرح زیر برای حل این مشکلات به نظر من منطقی و بدیهی است.

چگونه از انتظار نهایی شدن بلوک جلوگیری کنیم و توانایی ردیابی وضعیت تراکنش را از دست ندهیم

هر چه زمان تشکیل و اندازه بلوک بیشتر باشد، توان عملیاتی زنجیره بلوک بالاتر است. یکی مستقیماً از دیگری پیروی نمی کند، اما باید به خاطر داشت که ایجاد اجماع در RAFT به سه درخواست شبکه از رهبر به دنبال کنندگان و بازگشت نیاز دارد. هر چه تعداد نودهای سفارش بیشتر باشد، مدت زمان بیشتری طول خواهد کشید. هرچه اندازه و زمان تشکیل بلوک کوچکتر باشد، چنین فعل و انفعالات بیشتری وجود دارد. چگونه می توان زمان تولید و اندازه بلوک را بدون افزایش زمان پاسخگویی سیستم برای کاربر نهایی افزایش داد؟

اول، ما باید به نحوی تضادهای MVCC ناشی از اندازه بلوک بزرگ را حل کنیم، که ممکن است شامل مجموعه های RW مختلف با همان نسخه باشد. بدیهی است که در سمت مشتری (در رابطه با شبکه بلاک چین، این می تواند به خوبی یک باطن باشد، و منظورم این است) شما نیاز دارید کنترل کننده تعارض MVCC، که می تواند یک سرویس جداگانه یا یک دکوراتور معمولی بالای تماس باشد که با منطق امتحان مجدد معامله را آغاز می کند.

سعی مجدد را می توان با یک استراتژی نمایی پیاده سازی کرد، اما پس از آن تاخیر به همان میزان نمایی کاهش می یابد. بنابراین شما باید از یک امتحان مجدد تصادفی در محدوده‌های کوچک معین یا یک آزمایش ثابت استفاده کنید. با توجه به برخوردهای احتمالی در گزینه اول.

قدم بعدی این است که تعامل کلاینت با سیستم را ناهمزمان کنیم تا 15، 30 یا 10000000 ثانیه منتظر نماند که آن را به عنوان BatchTimeout تنظیم می کنیم. اما در عین حال، لازم است توانایی تأیید اینکه تغییرات آغاز شده توسط تراکنش در بلاک چین ثبت شده است یا خیر.
یک پایگاه داده می تواند برای ذخیره وضعیت تراکنش استفاده شود. ساده ترین گزینه CouchDB به دلیل سهولت استفاده است: پایگاه داده دارای یک UI خارج از جعبه، یک REST API است، و شما می توانید به راحتی Replication و Sharding را برای آن تنظیم کنید. شما به سادگی می توانید یک مجموعه جداگانه در همان نمونه CouchDB ایجاد کنید که از Fabric برای ذخیره وضعیت جهانی خود استفاده می کند. ما باید این نوع اسناد را ذخیره کنیم.

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

این سند قبل از ارسال تراکنش به همتایان در پایگاه داده نوشته می شود، اگر این یک عملیات ایجاد باشد، شناسه موجودیت به کاربر برگردانده می شود (همان شناسه به عنوان کلید استفاده می شود) و سپس فیلدهای Status، TxID و Error هستند. با دریافت اطلاعات مرتبط از همتایان به روز می شود.

رجیستری توزیع شده برای چرخ ها: تجربه ای با پارچه هایپرلجر

در این طرح، کاربر منتظر نمی ماند تا بلوک در نهایت شکل بگیرد، با تماشای چرخ چرخان روی صفحه به مدت 10 ثانیه، پاسخ آنی سیستم را دریافت می کند و به کار خود ادامه می دهد.

ما BoltDB را برای ذخیره وضعیت تراکنش ها انتخاب کردیم، زیرا نیاز به صرفه جویی در حافظه داریم و نمی خواهیم زمان را در تعامل شبکه با یک سرور پایگاه داده جداگانه تلف کنیم، به خصوص زمانی که این تعامل با استفاده از یک پروتکل متن ساده رخ می دهد. به هر حال، چه از CouchDB برای اجرای طرح توضیح داده شده در بالا استفاده کنید یا صرفاً برای ذخیره وضعیت جهان، در هر صورت منطقی است که نحوه ذخیره داده ها در CouchDB را بهینه کنید. به‌طور پیش‌فرض، در CouchDB، اندازه گره‌های b-tree 1279 بایت است که بسیار کوچک‌تر از اندازه بخش روی دیسک است، به این معنی که خواندن و تعادل مجدد درخت به دسترسی فیزیکی بیشتری به دیسک نیاز دارد. اندازه بهینه مطابق با استاندارد است فرمت پیشرفته و 4 کیلوبایت است. برای بهینه سازی باید پارامتر را تنظیم کنیم btree_chunk_size برابر با 4096 است در فایل پیکربندی CouchDB. برای BoltDB چنین مداخله دستی مورد نیاز نیست.

فشار برگشتی: استراتژی بافر

اما ممکن است پیام های زیادی وجود داشته باشد. بیش از توانایی سیستم، به اشتراک گذاری منابع با ده ها سرویس دیگر به غیر از موارد نشان داده شده در نمودار - و همه اینها باید بدون عیب و نقص حتی بر روی ماشین هایی که اجرای Intellij Idea روی آنها بسیار خسته کننده است، کار کند.

مشکل ظرفیت های مختلف سیستم های ارتباطی تولید کننده و مصرف کننده به روش های مختلفی حل می شود. بیایید ببینیم چه کاری می توانیم انجام دهیم.

رها کردن: می توانیم ادعا کنیم که می توانیم حداکثر X تراکنش را در T ثانیه پردازش کنیم. تمام درخواست‌هایی که بیش از این حد مجاز هستند، رد می‌شوند. این بسیار ساده است، اما پس از آن می توانید UX را فراموش کنید.

کنترل: مصرف کننده باید نوعی رابط داشته باشد که از طریق آن، بسته به بار، بتواند TPS تولید کننده را کنترل کند. بد نیست، اما تعهداتی را به توسعه دهندگان مشتری که بار اجرای این رابط را ایجاد می کنند، تحمیل می کند. این برای ما غیرقابل قبول است، زیرا بلاک چین در آینده در تعداد زیادی از سیستم های قدیمی ادغام خواهد شد.

بافر: به جای تلاش برای مقاومت در برابر جریان داده های ورودی، می توانیم این جریان را بافر کرده و با سرعت مورد نیاز پردازش کنیم. بدیهی است که اگر بخواهیم تجربه کاربری خوبی ارائه دهیم، این بهترین راه حل است. ما بافر را با استفاده از یک صف در RabbitMQ پیاده سازی کردیم.

رجیستری توزیع شده برای چرخ ها: تجربه ای با پارچه هایپرلجر

دو اقدام جدید به طرح اضافه شده است: (1) پس از رسیدن یک درخواست به API، پیامی با پارامترهای لازم برای فراخوانی تراکنش در صف قرار می گیرد و مشتری پیامی مبنی بر پذیرش تراکنش توسط مشتری دریافت می کند. سیستم، (2) باطن داده ها را با سرعت مشخص شده در پیکربندی از صف می خواند. یک تراکنش را آغاز می کند و داده ها را در فروشگاه وضعیت به روز می کند.
اکنون می توانید زمان شکل گیری را افزایش دهید و ظرفیت را تا آنجا که می خواهید بلاک کنید و تاخیرها را از کاربر پنهان کنید.

ابزارهای دیگر

در اینجا چیزی در مورد کد زنجیره ای گفته نشد، زیرا، به عنوان یک قاعده، چیزی برای بهینه سازی در آن وجود ندارد. کد زنجیره ای باید تا حد امکان ساده و ایمن باشد - این تنها چیزی است که از آن لازم است. چارچوب به ما کمک می کند تا کد زنجیره ای را ساده و ایمن بنویسیم CCKit از S7 Techlab و آنالایزر استاتیک احیای^CC.

علاوه بر این، تیم ما در حال توسعه مجموعه ای از ابزارهای کمکی است تا کار با Fabric را ساده و لذت بخش کند: کاوشگر بلاک چین، ابزاری برای تغییرات پیکربندی شبکه به صورت خودکار (افزودن/حذف سازمان ها، گره های RAFT)، ابزار برای ابطال گواهینامه و حذف هویت. اگر می خواهید مشارکت داشته باشید، خوش آمدید.

نتیجه

این رویکرد به شما امکان می دهد به راحتی Hyperledger Fabric را با Quorum، سایر شبکه های خصوصی اتریوم (PoA یا حتی PoW) جایگزین کنید، توان عملیاتی واقعی را به میزان قابل توجهی کاهش دهید، اما در عین حال UX معمولی را حفظ کنید (هم برای کاربران در مرورگر و هم برای سیستم های یکپارچه). هنگامی که Fabric را با اتریوم در طرح جایگزین می‌کنید، فقط باید منطق سرویس/تزیین‌کننده مجدد را از پردازش تداخل‌های MVCC به افزایش nonce اتمی و ارسال مجدد تغییر دهید. ذخیره سازی بافر و وضعیت این امکان را فراهم می کند که زمان پاسخ را از زمان تشکیل بلوک جدا کنیم. اکنون می‌توانید هزاران گره سفارش اضافه کنید و از اینکه بلاک‌ها اغلب تشکیل می‌شوند نترسید و سرویس سفارش را بارگیری کنید.

اساساً، این تنها چیزی است که می خواستم به اشتراک بگذارم. خوشحال خواهم شد اگر این به کسی در کارش کمک کند.

منبع: www.habr.com

اضافه کردن نظر