
Në vitin 2017, fitojmë një konkurs për zhvillimin e bërthamës transaksionale të biznesit investues të Alfa-Bank dhe fillojmë punën (në HighLoad++ 2018 me një prezantim mbi bërthamën e biznesit investues. Vladimir Dryinkin, drejtor i drejtimit të bërthamës transaksionale të biznesit investues të Alfa-Bank). Ky sistem duhet të agregojë të dhëna mbi transaksionet nga burime të ndryshme në formate të ndryshme, t'i sjellë ato në një format të unifikuar, t'i ruajë dhe të ofrojë qasje në to.
Gjatë zhvillimit, sistemi evoluoi dhe fitoi funksionalitete të reja, dhe një moment e kuptuam se po formohej diçka shumë më e madhe se thjesht një softuer aplikativ, i krijuar për të zgjidhur një grup të caktuar problemesh: ne krijuam një sistem për ndërtimin e aplikacioneve të shpërndara me ruajtje persistente.Eksperienca që fituam u bë baza për produktin e ri — (TDG).
Dua të flas për arkitekturën e TDG dhe për zgjidhjet që arritëm gjatë zhvillimit, t'ju prezantoj me funksionalitetin kryesor dhe të tregoj se si produkti ynë mund të bëhet baza për ndërtimin e zgjidhjeve përfundimtare.
Arkitektonikisht, ne e ndamë sistemin në komponentë të veçantë, çdo njëra prej të cilave është përgjegjëse për zgjidhjen e një grupi të caktuar të problemesh. Një instancë e ulur e aplikacionit implementon një ose më shumë tipe rolesh. Në klaster mund të ketë disa role të një tipi: rollet, secila nga të cilat është përgjegjëse për zgjidhjen e një rrethi të caktuar detyrash. Një instancë e nisur e aplikacionit realizon një ose disa lloje rolerash. Në klaster mund të ketë disa role të një lloji:

Connector
Connector është përgjegjës për lidhjen me botën jashtë; detyra e tij është të pranojë një kërkesë, ta analizoje atë, dhe nëse arrin, të dërgojë të dhënat për përpunim në input processor. Ne mbështesim formatet HTTP, SOAP, Kafka, FIX. Arkitektura lejon të shtojmë lehtësisht mbështetje për formate të reja, përfshirë mbështetje për IBM MQ të shfaqet së shpejti. Nëse analiza e kërkesës përfundoi me një gabim, connector do të kthejë një gabim; në të kundërt, ai do të përgjigjet që kërkesa u përpunua me sukses, edhe nëse ndodhi një gabim gjatë përpunimit të saj më tej. Kjo është bërë posaçërisht për të bashkëpunuar me sisteme që nuk dinë të përsërisin kërkesat — ose përkundrazi, e bëjnë këtë shumë insistent. Për të mos humbur të dhëna, përdoret një radhë riparimi: objekti fillimisht përfundon atje dhe vetëm pas përpunimit të suksesshëm hiqet prej saj. Administratorët mund të marrin njoftime për objektet që mbeten në radhën e riparimit, dhe pas eliminimit të defekteve softuerike ose aksidentale mund të bëjnë një tentativë tjetër.
Input processor
Input processor klasifikon të dhënat e marra sipas karakteristikave të tyre dhe thërrasin trajtues të përshtatshëm. Trajtesit janë kod në gjuhën Lua, të ekzekutuar në një sand box, kështu që ata nuk mund të ndikojnë në funksionimin e sistemit. Në këtë fazë, të dhënat mund të përpunohen në formatin e nevojshëm, dhe gjithashtu, nëse është e nevojshme, të aktivizojnë një numër të pakufizuar të detyrave që mund të zbatojnë logjikën e nevojshme. Për shembull, në produktin MDM (Master Data Management), e ndërtuar mbi Tarantool Data Grid, kur shtojmë një përdorues të ri, për të mos ngadalësuar procesimin e kërkesës, krijimin e një regjistri të artë e aktivizojmë si një detyrë të veçantë. Sand box mbështet kërkesa për lexim, modifikim dhe shtim të të dhënave, dhe lejon ekzekutimin e një funksioni në të gjitha rolet e tipusit storage dhe agregimin e rezultatit (map/reduce).
Trajtesit mund të përshkruhen në skedarë:
sum.lua
local x, y = unpack(...)
return x + yDhe pastaj, shpallur në konfigurim:
functions:
sum: { __file: sum.lua }
Pse Lua? Lua është një gjuhë shumë e thjeshtë. Nga përvoja jonë, pas disa orësh njohje me të, njerëzit fillojnë të shkruajnë kod që zgjidh problemin e tyre. Dhe kjo nuk është vetëm për zhvilluesit profesionistë, por edhe për analistët, për shembull. Për më tepër, falë jit-kompilatorit, Lua punon shumë shpejt.
Storage
Storage mban të dhëna persistuese. Para ruajtjes, të dhënat kalojnë një verifikim për përputhjen me skemën e të dhënave. Për përshkrimin e skemës ne përdorim një format të zgjeruar . Shembull:
{
"name": "User",
"type": "record",
"logicalType": "Aggregate",
"fields": [
{ "name": "id", "type": "string"},
{"name": "first_name", "type": "string"},
{"name": "last_name", "type": "string"}
],
"indexes": ["id"]
}Nga ky përshkrim, automatikisht gjenerohet DDL (Data Definition Language) për DBM Tarantool dhe schema për qasje në të dhëna.
Mbështetet replikimi asinkron i të dhënave (plani është të shtohet sinqronic).
Output processor
Ndonjëherë, është e nevojshme të njoftoni përdoruesit e jashtëm për hyrjen e të dhënave të reja. Për këtë ekziston roli Output processor. Pas ruajtjes së të dhënave, ato mund të dërgohen në procesorin përkatës (për shembull, për të i dhënë atyre formatin e kërkuar nga përdoruesi) dhe më pas dërguar në connector për dërgim. Këtu përdoret gjithashtu një radhë rikuperimi: nëse objekti nuk është pranuar nga askush, administratori mund të provojë përsëri më vonë.
Масштабирование
Rolat connector, input processor dhe output processor nuk kanë gjendje, çka na lejon të shkallëzojmë sistemin horizontalisht, thjesht duke shtuar ekzemplarë të rinj të aplikacionit me rolin e nevojshëm të aktivizuar. Për shkallëzim horizontal, përdoret storage i organizimit të klasterit duke përdorur kontenierë virtualë. Pas shtimit të një serveri të ri, një pjesë e kontenierëve nga serverët e vjetër lëvizin në mënyrë të fshehtë në serverin e ri; kjo ndodh pa asnjë ndikim për përdoruesit dhe nuk ndikon në funksionimin e të gjithë sistemit.
Karakteristikat e të dhënave
Objektet mund të jenë shumë të mëdha dhe të përmbajnë objekte të tjera. Ne sigurojmë atomikën e shtimit dhe përditësimit të të dhënave, duke ruajtur objektin me të gjitha varësitë në një kontenier virtual. Kështu, përjashtohet "shkërbimi" i objektit në disa servera fizikë.
Përversionimi përkrah: çdo përditësim i objektit krijon një version të ri, dhe ne gjithmonë mund të bëjmë një prerje temporale dhe të shohim si ishte bota atëherë. Për të dhënat që nuk kërkojnë një histori të gjatë, ne mund të kufizojmë numrin e versioneve ose madje të ruajmë vetëm një — atë më të fundit, çka do të thotë të çaktivizojmë përversionimin për një lloj të caktuar. Gjithashtu, është e mundur të kufizojmë historinë sipas kohës: për shembull, të fshijmë të gjitha objektet e një lloji më të vjetër se 1 vit. Arkivimi gjithashtu përkrah: ne mund të nxjerrim objekte që janë më të vjetra se koha e specifikuar, duke shkruar vend për në klaster.
Detyrat
Nga funksionet interesante, merret parasysh mundësia e ekzekutimit të detyrave sipas një programi, me kërkesë nga përdoruesi ose programatikisht nga sandbox:

Këtu shohim një rol tjetër — runner. Ky rol nuk ka gjendje, dhe kur është e nevojshme, është e mundur të shtoni ekzemplarë të rinj të aplikacionit me këtë rol në klaster. Përgjegjësia e runner është të ekzekutojë detyrat. Siç u tha, nga sandbox është e mundur të krijohen detyra të reja; ato ruajnë në radhë në storage dhe më pas ekzekutohen nga runner. Ky lloj detyre quhet Job. Gjithashtu kemi një lloj detyre të quajtur Task — këto janë detyra të përcaktuara nga përdoruesi dhe të ekzekutuara sipas programit (përdoret sintaksa cron) ose me kërkesë. Për të nisur dhe ndjekur këto detyra, kemi një menaxher të përshtatshëm detyrash. Për të qenë e mundur kjo funksionalitet, është e nevojshme të aktivizohet roli scheduler; ky rol ka gjendje dhe prandaj nuk shkallëzohet, e cila megjithatë nuk është e nevojshme; ndërkohë, ai, ashtu si të gjitha rolet e tjera, mund të ketë një replikë, e cila fillon të punojë nëse master-i rastësisht dështon.
Logger
Një rol tjetër quhet logger. Ai mbledh log-et nga të gjithë anëtarët e klasterit dhe siguron një ndërfaqe për të nxjerrë dhe parë ato përmes një ndërfaqeje web.
Shërbimet
Është e rëndësishme të përmendet se sistemi lejon lehtësisht krijimin e shërbimeve. Në skedarin e konfigurimit mund të tregoni se cilat kërkesa duhet të drejtohen në procesorin e shkruar nga përdoruesi, që ekzekutohet në sandbox. Në këtë procesor, për shembull, mund të ekzekutoni një kërkesë analitike dhe të ktheheni me rezultatin.
Shërbimi përshkruhet në skedarin e konfigurimit:
services:
sum:
doc: "shton dy numra"
function: sum
return_type: int
args:
x: int
y: int
GraphQL API gjenerohet automatikisht dhe shërbimi bëhet i disponueshëm për thirrje:
query {
sum(x: 1, y: 2)
} Kjo do të çojë në thirrjen e procesorit sum, i cili do të kthejë rezultatin:
3
Profilizimi i kërkesave dhe metrika
Për të kuptuar funksionimin e sistemit dhe për të profilizuar kërkesat, ne e realizuam mbështetje për protokollin OpenTracing. Sistemi mund të dërgojë informacion sipas kërkesës për instrumentat që mbështesin këtë protokoll, për shembull Zipkin, çka do të lejojë të kuptojmë se si është ekzekutuar kërkesa:

Natyrisht, sistemi ofron metrika të brendshme, të cilat mund të mblidhen me anë të Prometheus dhe të vizualizohen me anë të Grafana.
Dërgo
Tarantool Data Grid mund të deploy-het nga pakot RPM ose nga arka, me një utilitar të ofruar ose me Ansible, gjithashtu ka mbështetje për Kubernetes ().
Aplikacioni që realizon logjikën e biznesit (konfigurimi, procesorët) ngarkohet në klasterin e deploy-uar Tarantool Data Grid si një arkiv përmes UI ose me anë të një skripti, përmes API-së që ofrojmë.
Shembuj aplikacionesh
Cilat aplikacione mund të krijohen me Tarantool Data Grid? Në të vërtetë, shumica e detyrave të biznesit lidhen në një mënyrë ose tjetër me përpunimin e rrjedhës së të dhënave, ruajtjen dhe aksesin në to. Prandaj, nëse keni rrjedha të mëdha të dhënash që duhen ruajtur me besueshmëri dhe aksesuar, produkti ynë mund t'ju kursejë shumë kohë në zhvillim dhe t'ju ndihmojë të fokusoheni në logjikën tuaj të biznesit.
Për shembull, ne duam të mbledhim informacion mbi tregun e pasurive të patundshme, me qëllim që më vonë të kemi informacion mbi ofertat më të favorshme. Në këtë rast, ne do të përzgjedhim detyrat si më poshtë:
- Robotët që mbledhin informacion nga burime të hapura do të jenë burimet tona të dhënash. Këtë detyrë mund ta zgjidhni duke përdorur zgjidhje të gatshme ose duke shkruar kod në çdo gjuhë.
- Më pas, Tarantool Data Grid do të pranojë dhe ruajë të dhënat. Nëse formati i të dhënave nga burime të ndryshme ndryshon, mund të shkruani kod në gjuhën Lua që do të konvertojë këto të dhëna në një format të uniformuar. Në fazën e përpunimit paraprak, gjithashtu mund të filtroni ofertat e përsëritura ose të përditësoni informacionin mbi agjentët që punojnë në tregun.
- Tani ju keni një zgjidhje të shkallëzuar në një klaster që mund të mbushet me të dhëna dhe të kryejë kërkime të dhënash. Më tej, mund të zbatoni funksionalitete të reja, për shembull, të shkruani një shërbim që do të bëjë një kërkesë ndaj të dhënave dhe do të nxjerrë ofertën më të favorshme brenda 24 orëve — kjo do të kërkojë disa radhë në skedarin e konfigurimit dhe pak kod në Lua.
Çfarë ndodh më tej?
Prioritet ynë është rritja e lehtësisë së zhvillimit përmes . Për shembull, kjo është një IDE që mbështet profilimin dhe debugimin e përpunuesve që punojnë në sandboxes.
Gjithashtu, ne i kushtojmë shumë rëndësi çështjeve të sigurisë. Aktualisht jemi në procesin e certifikimit nga FSTEC i Rusisë për të konfirmuar nivelin e lartë të sigurisë dhe për të përmbushur kërkesat për certifikimin e produkteve softuerike që përdoren në sistemet informative të të dhënave personale dhe sistemet informative qeveritare.
Burimi: habr.com
