در سال 2017، ما برنده مسابقه ای برای توسعه هسته معاملاتی کسب و کار سرمایه گذاری آلفا بانک شدیم و شروع به کار کردیم (در HighLoad++ 2018 با گزارشی در مورد هسته کسب و کار سرمایه گذاری
در طول فرآیند توسعه، سیستم تکامل یافت و عملکردی به دست آورد، و در مقطعی متوجه شدیم که چیزی بسیار بیشتر از نرم افزار کاربردی ایجاد شده برای حل یک محدوده کاملاً تعریف شده از وظایف را متبلور می کنیم: ما موفق شدیم. سیستمی برای ساخت برنامه های کاربردی توزیع شده با ذخیره سازی پایدار. تجربه ای که ما به دست آوردیم اساس یک محصول جدید را تشکیل داد -
من می خواهم در مورد معماری TDG و راه حل هایی که در طول فرآیند توسعه به آنها رسیدیم صحبت کنم، شما را با عملکرد اصلی آشنا کنم و نشان دهم که چگونه محصول ما می تواند پایه ای برای ساخت راه حل های کامل شود.
از نظر معماری، سیستم را به مجزا تقسیم کردیم نقش هاکه هر کدام وظیفه حل طیف خاصی از مسائل را بر عهده دارند. یک نمونه برنامه در حال اجرا یک یا چند نوع نقش را پیاده سازی می کند. میتواند چندین نقش از یک نوع در یک خوشه وجود داشته باشد:
اتصال
کانکتور مسئول ارتباط با دنیای خارج است. وظیفه آن پذیرش درخواست، تجزیه و تحلیل آن است و در صورت موفقیت آمیز بودن، داده ها را برای پردازش به پردازنده ورودی ارسال می کند. ما از فرمت های HTTP، SOAP، Kafka، FIX پشتیبانی می کنیم. این معماری به شما امکان می دهد به سادگی از فرمت های جدید پشتیبانی کنید، با پشتیبانی از IBM MQ به زودی. اگر تجزیه درخواست ناموفق باشد، کانکتور یک خطا را برمیگرداند. در غیر این صورت، پاسخ خواهد داد که درخواست با موفقیت پردازش شده است، حتی اگر در طول پردازش بیشتر آن خطایی رخ داده باشد. این به طور خاص به منظور کار با سیستم هایی انجام شد که نمی دانند چگونه درخواست ها را تکرار کنند - یا برعکس، این کار را بیش از حد مداوم انجام می دهند. برای از دست ندادن داده ها، از صف تعمیر استفاده می شود: شی ابتدا وارد آن می شود و تنها پس از پردازش موفقیت آمیز از آن حذف می شود. مدیر می تواند هشدارهایی در مورد اشیاء باقی مانده در صف تعمیر دریافت کند و پس از رفع خطای نرم افزار یا خرابی سخت افزار، دوباره امتحان کنید.
پردازنده ورودی
پردازنده ورودی داده های دریافتی را بر اساس ویژگی های مشخصه طبقه بندی می کند و پردازنده های مناسب را فراخوانی می کند. هندلرها کدهای Lua هستند که در یک جعبه شنی اجرا می شوند، بنابراین نمی توانند بر عملکرد سیستم تأثیر بگذارند. در این مرحله می توان داده ها را به شکل مورد نیاز کاهش داد و در صورت لزوم تعداد دلخواه کارها را راه اندازی کرد که بتواند منطق لازم را پیاده سازی کند. به عنوان مثال، در محصول MDM (Master Data Management) که بر روی Tarantool Data Grid ساخته شده است، هنگام اضافه کردن کاربر جدید، برای اینکه پردازش درخواست کند نشود، ایجاد یک رکورد طلایی را به عنوان یک کار جداگانه راه اندازی می کنیم. جعبه شنی از درخواستهای خواندن، تغییر و افزودن دادهها پشتیبانی میکند، به شما اجازه میدهد تا برخی از عملکردها را در همه نقشهای نوع ذخیرهسازی و تجمیع نتیجه (نقشه/کاهش) انجام دهید.
هندلرها را می توان در فایل ها شرح داد:
sum.lua
local x, y = unpack(...)
return x + y
و سپس در پیکربندی اعلام شد:
functions:
sum: { __file: sum.lua }
چرا لوا؟ لوا زبان بسیار ساده ای است. بر اساس تجربه ما، چند ساعت پس از آشنایی، افراد شروع به نوشتن کدی می کنند که مشکل آنها را حل می کند. و اینها نه تنها توسعه دهندگان حرفه ای، بلکه به عنوان مثال، تحلیلگران هستند. علاوه بر این، به لطف کامپایلر jit، Lua بسیار سریع اجرا می شود.
ذخیره سازی
Storage داده های پایدار را ذخیره می کند. قبل از ذخیره، داده ها در مقابل طرح داده اعتبارسنجی می شوند. برای توصیف مدار از قالب توسعه یافته استفاده می کنیم
{
"name": "User",
"type": "record",
"logicalType": "Aggregate",
"fields": [
{ "name": "id", "type": "string"},
{"name": "first_name", "type": "string"},
{"name": "last_name", "type": "string"}
],
"indexes": ["id"]
}
بر اساس این توضیحات، DDL (زبان تعریف داده) به طور خودکار برای DBMS Tarantula و
تکثیر داده های ناهمزمان پشتیبانی می شود (برنامه هایی برای اضافه کردن همزمان داده ها وجود دارد).
پردازنده خروجی
گاهی اوقات لازم است که مصرف کنندگان خارجی از ورود داده های جدید مطلع شوند؛ برای این منظور، نقش پردازشگر خروجی وجود دارد. پس از ذخیره داده ها، می توان آن را به کنترل کننده مربوطه ارسال کرد (مثلاً برای آوردن آن به فرم مورد نیاز مصرف کننده) - و سپس برای ارسال به کانکتور ارسال کرد. یک صف تعمیر نیز در اینجا استفاده می شود: اگر کسی شی را نپذیرفت، مدیر می تواند بعداً دوباره امتحان کند.
مقیاس بندی
نقشهای رابط، پردازنده ورودی و پردازنده خروجی بدون حالت هستند و به ما این امکان را میدهند که با افزودن نمونههای کاربردی جدید با فعال بودن نوع نقش مورد نظر، سیستم را به صورت افقی مقیاس کنیم. ذخیره سازی برای پوسته پوسته شدن افقی استفاده می شود
ویژگی های داده
اجسام می توانند بسیار بزرگ باشند و شامل اشیاء دیگری باشند. ما با ذخیره یک شی با تمام وابستگی ها در یک سطل مجازی، اتمی بودن افزودن و به روز رسانی داده ها را تضمین می کنیم. این مانع از "گسترش" شی در چندین سرور فیزیکی می شود.
نسخهسازی پشتیبانی میشود: هر بهروزرسانی یک شی یک نسخه جدید ایجاد میکند، و ما همیشه میتوانیم یک برش زمانی برداریم و ببینیم جهان در آن زمان چگونه به نظر میرسید. برای دادههایی که نیاز به تاریخچه طولانی ندارند، میتوانیم تعداد نسخهها را محدود کنیم یا حتی فقط یک نسخه - آخرین نسخه - را ذخیره کنیم، یعنی اساساً نسخهسازی را برای یک نوع خاص غیرفعال کنیم. همچنین می توانید تاریخچه را بر اساس زمان محدود کنید: به عنوان مثال، تمام اشیاء از نوع خاصی قدیمی تر از 1 سال را حذف کنید. بایگانی نیز پشتیبانی میشود: میتوانیم اشیاء قدیمیتر از زمان مشخصشده را بارگیری کنیم و فضایی را در خوشه آزاد کنیم.
وظایف
از جمله ویژگی های جالب، قابل ذکر است که می توانید وظایف را بر اساس برنامه زمان بندی، به درخواست کاربر یا به صورت برنامه ریزی شده از جعبه شنی اجرا کنید:
در اینجا نقش دیگری را می بینیم - دونده. این نقش بدون حالت است و در صورت نیاز میتوان نمونههای برنامه اضافی با این نقش را به خوشه اضافه کرد. مسئولیت دونده تکمیل وظایف است. همانطور که گفته شد، امکان تولید وظایف جدید از sandbox وجود دارد. آنها در یک صف در ذخیره سازی ذخیره می شوند و سپس در runner اجرا می شوند. به این نوع کار Job می گویند. ما همچنین یک نوع وظیفه به نام Task داریم - اینها وظایف تعریف شده توسط کاربر هستند که بر اساس یک زمانبندی (با استفاده از نحو cron) یا بر اساس تقاضا اجرا می شوند. برای راه اندازی و ردیابی چنین وظایفی، ما یک مدیر وظیفه مناسب داریم. برای اینکه این قابلیت در دسترس باشد، باید نقش زمانبندی را فعال کنید. این نقش یک حالت دارد، بنابراین مقیاس نمی شود، اما لازم نیست. در عین حال، مانند همه نقشهای دیگر، میتواند یک ماکت داشته باشد که در صورت امتناع استاد، شروع به کار کند.
متمرکز ساز
نقش دیگری به نام Logger است. گزارشها را از همه اعضای خوشه جمعآوری میکند و یک رابط برای آپلود و مشاهده آنها از طریق رابط وب فراهم میکند.
خدمات
شایان ذکر است که سیستم ایجاد خدمات را آسان می کند. در فایل پیکربندی، میتوانید تعیین کنید که کدام درخواستها به یک کنترلکننده نوشته شده توسط کاربر که در sandbox اجرا میشود ارسال شود. در این هندلر می توانید به عنوان مثال نوعی کوئری تحلیلی را اجرا کرده و نتیجه را برگردانید.
این سرویس در فایل پیکربندی توضیح داده شده است:
services:
sum:
doc: "adds two numbers"
function: sum
return_type: int
args:
x: int
y: int
GraphQL API به طور خودکار تولید می شود و سرویس برای تماس در دسترس می شود:
query {
sum(x: 1, y: 2)
}
با این کار کنترل کننده تماس می گیرد sum
که نتیجه را برمی گرداند:
3
پروفایل پرس و جو و متریک
برای درک عملکرد سیستم و درخواست های پروفایل، ما از پروتکل OpenTracing پشتیبانی کردیم. این سیستم میتواند اطلاعات درخواستی را به ابزارهایی که از این پروتکل پشتیبانی میکنند، مانند Zipkin ارسال کند، که به شما امکان میدهد نحوه اجرای درخواست را درک کنید:
به طور طبیعی، این سیستم معیارهای داخلی را ارائه می دهد که می توان با استفاده از Prometheus جمع آوری کرد و با استفاده از Grafana تجسم کرد.
مستقر کنید
Tarantool Data Grid را می توان از بسته های RPM یا بایگانی، با استفاده از ابزاری از توزیع یا Ansible مستقر کرد، همچنین از Kubernetes پشتیبانی می شود (
برنامهای که منطق کسبوکار (پیکربندی، کنترلکنندهها) را پیادهسازی میکند، در قالب یک آرشیو از طریق رابط کاربری یا با استفاده از یک اسکریپت از طریق API ارائهشده توسط ما، در خوشه شبکه دادههای Tarantool مستقر بارگذاری میشود.
نمونه برنامه های کاربردی
چه برنامه هایی را می توان با استفاده از Tarantool Data Grid ایجاد کرد؟ در واقع، بیشتر وظایف تجاری به نوعی با پردازش، ذخیره سازی و دسترسی به جریان داده مرتبط هستند. بنابراین، اگر جریانهای بزرگی از دادهها دارید که باید به صورت ایمن ذخیره شوند و به آنها دسترسی داشته باشید، محصول ما میتواند زمان زیادی برای توسعه شما صرفهجویی کند و بر منطق کسبوکارتان تمرکز کنید.
مثلاً می خواهیم اطلاعاتی در مورد بازار املاک جمع آوری کنیم تا در آینده مثلاً از بهترین پیشنهادات اطلاعاتی داشته باشیم. در این مورد، وظایف زیر را برجسته می کنیم:
- ربات هایی که اطلاعات را از منابع باز جمع آوری می کنند، منابع داده ما خواهند بود. با استفاده از راه حل های آماده یا نوشتن کد به هر زبانی می توانید این مشکل را حل کنید.
- در مرحله بعد، Tarantool Data Grid داده ها را می پذیرد و ذخیره می کند. اگر فرمت داده از منابع مختلف متفاوت است، می توانید کدی را در Lua بنویسید که تبدیل به یک فرمت را انجام دهد. در مرحله پیش پردازش، شما همچنین قادر خواهید بود، برای مثال، پیشنهادات تکراری را فیلتر کنید یا اطلاعات مربوط به عواملی که در بازار کار می کنند را در پایگاه داده به روز کنید.
- اکنون شما یک راه حل مقیاس پذیر در یک خوشه دارید که می تواند با داده ها پر شود و داده ها را انتخاب کنید. سپس می توانید عملکرد جدیدی را پیاده سازی کنید، به عنوان مثال، سرویسی بنویسید که درخواست داده را ارائه می دهد و سودمندترین پیشنهاد را در روز ارائه می دهد - این به چند خط در فایل پیکربندی و کمی کد Lua نیاز دارد.
گام بعدی چیست؟
اولویت ما بهبود سهولت استفاده از توسعه است
ما همچنین به مسائل ایمنی توجه زیادی می کنیم. در حال حاضر ما در حال گذراندن گواهینامه توسط FSTEC روسیه برای تأیید سطح بالای امنیت و برآورده کردن الزامات صدور گواهینامه محصولات نرم افزاری مورد استفاده در سیستم های اطلاعات شخصی و سیستم های اطلاعات دولتی هستیم.
منبع: www.habr.com