
Më quajnë Yuri, jam drejtues i grupit të administratës së sistemeve në Sitimobil. Sot do të ndaj përvojën time me teknologjinë e rezervoarëve të hollë (thin provisioning) për sistemet e skedarëve Linux dhe do të flas për si mund të aplikohet kjo në proceset teknologjike CI/CD të kompanisë. Do të shqyrtojmë situatën kur për testimin automatik të kodit në dorëzimin në production, na nevojiten sa më shpejt kopjet e DB MySQL, të cilat janë sa më të afërt me versionin 'live', të disponueshme për lexim dhe shkrim.
Hyrje: Pse të japim këshilla të dëmshme?
Një pyetje logjike, pasi ka mekanizma të provuar për migrimin e skemave të DB në ambientet testuese. Pse të arrijmë në këtë volum me të dhënat e SGB-së jo të ndara? Të dhënat e plota nuk janë të nevojshme për testim. Do të përpiqem ta shpjegoj.
Rreth një vit më parë, në sfondin e rritjes aktive të agregatorit tonë të taksive (në vitin 2018 u rritëm rreth 15 herë në udhët e përfunduara), u rritën volumet e të dhënave, ngarkesa në servera, dhe frekuenca e lançimeve. Ne u gjetëm në situatën e mëposhtme:
- DB kryesore MySQL u rrit në rreth 1000 tabela, me një volum total prej 2.5 TB dhe vazhdonte të rritet.
- Nuk kishte mundësi për të shpërndarë shpejt dhe për të shpërndarë bazën. Kjo nuk e lejonte qasja e vjetër «po shkruaj në bazë çfarë dua dhe si dua», shumë JOIN's dhe varësi të brendshme të tabelave.
- Nuk kishte një mekanizëm për migrimin e skemës së DB në ambientet testuese.
- Nuk kishte testim automatik të kodit gjatë lëshimit në prodhim.
Problemin e fundit doja ta zgjidhja sa mĂ« shpejt tĂ« ishte e mundur. Testet Postman ishin tashmĂ« shkruar pĂ«r tĂ« kontrolluar monolitin kryesor PHP, por mungonte njĂ« bazĂ« tĂ« dhĂ«nash aktuale. NdĂ«rkohĂ«, nuk mund tĂ« krijonim njĂ« replikĂ« gjatĂ« natĂ«s, ta bĂ«nim master dhe tâia jepnim pĂ«r tâu pĂ«rdorur gjatĂ« ditĂ«s: numri i madh i lĂ«shimeve dhe ndryshimeve, pĂ«rfshirĂ« tĂ« dhĂ«nat dhe skemĂ«n e DB, do ta bĂ«nte platformĂ«n jo funksionale qĂ« nĂ« mes tĂ« ditĂ«s. Dhe gjithashtu, do tĂ« ishte joefikas tĂ« kufizohej lĂ«shimi vetĂ«m nĂ« ditĂ«n e punĂ«s.
Megjithatë, detyra u përfundua: ne morëm platformën e parë funksionale brenda dy javësh. Gjatë vitit të kaluar ajo ka përjetuar shumë ndryshime dhe vazhdon të përdoret.
Më poshtë do të përshkruaj në detaje të gjitha hapat dhe fazat e zhvillimit të zgjidhjes sonë. Do të bindeni se kjo metodë meriton të ekzistojë.
ĂfarĂ« Ă«shtĂ« «rezervimi i hollë»?
Kjo Ă«shtĂ« njĂ« teknologji harduerike ose softuerike (emri tjetĂ«r â volumet sparse), qĂ« lejon alokimin e njĂ« sasie mĂ« tĂ« madhe tĂ« burimeve tĂ« nevojshme se sa ato qĂ« janĂ« nĂ« dispozicion. NĂ« tĂ« njĂ«jtĂ«n kohĂ«, volumi i alokuar duhet tĂ« pĂ«rmbushĂ« kriteret just-enough (aq sa duhet) dhe just-in-time (nĂ« kohĂ«n e nevojshme). Kryesisht, rezervimi i hollĂ« aplikohet nĂ« Sistemet e Ruajtjes, pĂ«r tĂ« ofruar hapĂ«sirĂ« diskore nĂ« sasi qĂ« tejkalojnĂ« ato qĂ« janĂ« nĂ« fakt tĂ« disponueshme. Teknologjia mbĂ«shtetet nga sisteme tĂ« ndryshme skedare, pĂ«r shembull, LVM2, ZFS, BTRFS. Ajo Ă«shtĂ« pĂ«rdorur gjerĂ«sisht nĂ« hipervizorĂ«t e virtualizimit. Rezervimi i hollĂ« na lejon tĂ« krijojmĂ« shpejt kopje tĂ« seksionit kryesor tĂ« tĂ« dhĂ«nave nga snapshot-et, aq kopje sa na nevojitet (direktoria data e DBMS MySQL).
Stenda e parë, teknologjia Thin LVM
Kjo kapitull mund të quhet gjithashtu "Si të krijoni snapshot-e të shpejtë me sasi të mëdha të të dhënave me anë të ", duke e ulur stabilitetin e sistemit skedar dhe të DBMS MySQL në tregues të papranueshëm.
Duke kemi pĂ«rdorur tashmĂ« LVM pĂ«r tĂ« ndĂ«rtuar seksionet kryesore tĂ« OS-it, vendosĂ«m tĂ« fillojmĂ« me tĂ«. Fillimisht, na nevojitej njĂ« makinĂ« fizike e veçantĂ« â njĂ« replike e bazĂ«s sonĂ« kryesore MySQL, nĂ« tĂ« cilĂ«n mund tĂ« krijonim njĂ« snapshot tĂ« replikĂ«s dhe ta ngrinim atĂ« si njĂ« instancĂ« tĂ« veçantĂ« MySQL. GjatĂ« testimit, lejuam qĂ« operacionet e ndryshimit tĂ« pĂ«rdoreshin nĂ« kĂ«tĂ« instancĂ«, dhe pas pĂ«rfundimit tĂ« testeve e fshihnim me sukses. Konfigurimi i serverit ishte ky:
- 2 x Intel Silver 4114 (10Ă2,2 GHz HT)
- 8 x 32 GB DDR4
- 8 x 1920 GB Intel SSD në RAID-kontroller Adaptec në RAID-10
Mund të shkruhet një artikull i veçantë mbi zgjedhjen midis RAID-kontrollerit dhe RAID-it programor MD. Do të thosha vetëm se dy faktorë ndikuan në zgjedhjen tonë:
- Në kohën e caktimit të kësaj detyre, ne gjithmonë instalonim DBMS në RAID-kontrollerë, prandaj mund të thuhet se ka ndodhur historikisht kështu.
- Dallimi në performancë në testet sintetike të sistemit të skedarëve dhe në testet me operacione të ndryshme në MySQL ishte minimal.
Ne kemi ndarë RAID-10 që kemi krijuar: formuam një grup volumesh të vetëm (VG) për të gjithë kapacitetin (me shpenzime të zakonshme rreth 6.7 GB) dhe krijuam një ndarje logjike (Logical Volume, LV) për sistemin me 50 GB. Në një situatë normale, pjesa tjetër e hapësirës përcaktohet për ndarjen e MySQL. Por, na duhej rezervimi i hollë, prandaj fillimisht krijuam një quajtur pool, brenda të cilit krijuam një ndarje për /var/lib/mysql me 3.5 TB (duke u bazuar në volumin e parashikuar të bazës së të dhënave):
lvcreate -l 100%FREE -T vga/thin
lvcreate -V 3.5T -T vga/thin -n mysqlFormatuam ndarjen nĂ« ext4, e montuam, shkruam replikĂ«n dhe morĂ«m kĂ«rkesĂ«n fillestare. Pastaj krijuam njĂ« ndĂ«rfaqe nĂ« formĂ«n e API, e cila duhet tĂ« krijojĂ« snapshots, tĂ« ngrejĂ« njĂ« instancĂ« MySQL nĂ« portin e caktuar dhe tĂ« fshijĂ« instancĂ«n e krijuar. Duke qenĂ« se pĂ«rdoren vetĂ«m thirrje sistemike, si gjuhĂ« pĂ«r tĂ« shkruar skenarĂ« zgjodhĂ«m bash-in e zakonshĂ«m, dhe pĂ«r lidhjen e API-sĂ« HTTP â bash zhvilluam njĂ« zgjidhje open source. , e shkruar nĂ« Go.
Një ditë do t'i publikojmë skenaret tanë në open source, por tani po e përshkruaj algoritmin kryesor:
Krijimi i snapshotit kryesor snapmain:
- Ndalim replikën kryesore.
- Vendosim bllokimin e operacioneve me snapshotin snapmain.
- Krijojmë një snapshot të ri snapmain.
- Nisim MySQL dhe heqim bllokimin.
Krijimi i DB në port të rastësishëm nga snapmain:
- Vendosim bllokimin për një instancë të caktuar të DB (port).
- Kontrollojmë për praninë e bllokimit të krijimit të snapshot-it kryesor. Nëse është e pranishme, presim dhe kontrollojmë përsëri çdo 5 sekonda.
- Kontrollojmë nëse ekziston një LV-particion i vjetër të instancës.
3.1 Nëse ekziston, ndalojmë instancën MySQL me ndihmën e kill -9 dhe fshijmë LV-particionin. - Krijojmë një instancë të re nga snapmain.
- Përgatitim dhe montojmë direktoret për këtë instancë.
- Heqim shenjat e slay-it (skedaret) dhe nisim instancën MySQL.
- E bëjmë atë master.
- Heqim bllokimin.
Fshirja e DB në port të rastësishëm:
- Vendosim bllokimin për një instancë të caktuar të DB (port).
- Vrasim instancën MySQL me ndihmën e kill -9.
- Heqim montimet e direktoreve.
- Fshijmë LV-particionin dhe heqim bllokimin.
Shembuj komandash për klonimin e particioneve të instancës së re të DB:
lvcreate -n stage_3307 -s vga/snapmain
lvchange -ay -K vga/stage_3307
mount -o noatime,nodiratime,data=writeback /dev/mapper/vga-stage_3307 /mnt/stage_3307Tani do t'ju tregoj për problemin kryesor me të cilin përballëm nga përdorimi i rezervimit të hollë. Dola në performancën e disqeve SSD. Kjo ndodhi për shkak të veçorive të Thin LVM: ajo në thelb operon në nivelin e pajisjes me blloqe të nivelit të ulët me një madhësi prej 4 MB si default. Si dukej kjo:
- Krijojmë një snapshot nga seksioni kryesor /var/lib/mysql.
- Nisim replikimin për të arritur masterin.
- Ădo ndryshim nĂ« tabelat e replikĂ«s bĂ«n qĂ« tĂ« ruajmĂ« blloqet e vjetra dhe tĂ« paprekura tĂ« tĂ« dhĂ«nave nĂ« seksionin e snapshot-it.
- Ădo ndryshim nĂ« instancĂ«n e testit tĂ« ngjitur bĂ«n qĂ« tĂ« ruajmĂ« blloqet e vjetra dhe tĂ« paprekura tĂ« tĂ« dhĂ«nave nĂ« seksionin e snapshot-it tĂ« klonuar pĂ«r kĂ«tĂ« instancĂ«.
- Marrim ngarkesë të operacioneve të hyrjes-daljes në 100% në pajisje, ngadalësim të çdo operacioni dhe një vonesë të gradualshme të replikës.
- Në fund të ditës së punës, marrim një skenë të vonuar me disa orë pas.
Si e luftuam këtë për të marrë një rezultat më të arsyeshëm (pikat kryesore):
RAID-kontrolleri:
- Ăaktivizuam tĂ« gjitha llojet e caching nĂ« mĂ«nyrĂ« tĂ« paracaktuar.
- Kemi aktivizuar writeback (kur të dhënat hynë në buffer, shkrimi përfundon para se ruajtja e vërtetë në disk të kryhet).
Sistema e skedarëve:
- Në pikën e montimit /var/lib/mysql kemi shkruar noatime,nodiratime,data=writeback
- Fiku regjistrimin ext4 me anë të tune2fs.
MySQL:
- Kemi shkruar innodb_flush_method = O_DSYNC (përmirësuam shpejtësinë e shkrimit, duke zvogëluar kështu besueshmërinë).
- Fiku regjistrimin, log-et nuk na duhen.
- Kemi shkruar innodb_buffer_pool_size = 4G (sa më e vogël të jetë madhësia e pool-it InnoDB, aq më shpejt do të mbyllet MySQL gjatë ndaljes, dhe aq më shpejt do të krijojmë një snapshot).
Ky është vetëm një listë parciale, sidomos për MySQL. Megjithatë, ndryshimet e tjera janë minor dhe shpesh nuk ose nuk aplikohen saktësisht. Për shembull, në tentativën për të lehtësuar diskët, ne madje e kemi marrë innodb_parallel_doublewrite_path në /dev/shm, që në disa raste gjatë nisjes së një instance të papërfunduar na kursente deri në 5 sekonda.
Pse e ndalnim MySQL para se të bëjmë një snapshot? Sepse mund ta marrim atë nga një replikë e punës. E gjithë kjo është e vërtetë, por vetë instanca e re e DB në këtë snapshot do të konsiderohet e dëmtuar nga parazgjedhja dhe do të kërkojë një skanim të plotë gjatë nisjes. Të ndalosh replikën është padyshim më e shpejtë, megjithatë, kjo në fund është operacioni më i gjatë në të gjithë procesin.
Si rezultat, ne arritëm koha më të pranueshme dhe një ambient të gatshëm për punë. Megjithatë, siç tregohet nga grafiku më ilustrues i vonesës së replikimit të replikës kryesore, situata ende është shumë larg idealit:

Nga mangësitë e tjera, duhet të theksohet pamundësia praktike e monitorimit të Pool-it Thin LVM: përveç funksioneve standarde të sistemit si iostat, është e pamundur të kuptosh, për shembull, cili element i pool-it po prodhon tani ngarkesën më të madhe në sistemin e skedave.
Një mangësi e madhe që merret parasysh për optimizimin e përmendur më sipër është se ne kemi marrë një YOLO-stand. Rreth një herë në një deri në dy muaj, ext4 nuk e përballonte një abuzim të tillë dhe thyhej në mënyrë të pakthyeshme, duke kërkuar formatim dhe rinovim të replikës. E fituam shpejtësinë, por shkatërruam stabilitetin e pashpresë.
Cilat metrika duhen monitoruar gjatë operimit të Thin LVM:
- Përqindja e të dhënave të pishinës së hollë
- Përqindja e metadatat e pishinës së hollë
Nëse vendi i përfunduar për të dhëna e përballon standin tonë (mjafton të pastrohen diskët), vendi i përfunduar për metadatat do të çojë në shembjen e plotë të pishinës dhe nevojën për ta krijuar nga fillimi.
Sistemi i skedarëve brenda pishinës fragmentohet shumë me kalimin e kohës. Rekomandoj që çdo ditë të ekzekutohet një komandë nga cron fstrim -v /var/lib/mysql.
Përfundimet ndërmjetëse:
- Teknologjia është e lehtë për t'u zbatuar, si dhe vetë LVM, dhe nuk kërkon kualifikim të veçantë për inxhinierët.
- Ajo është e përshtatshme për DB-të e vogla dhe jo shumë të ngarkuara. Sa më e vogël të jetë DB, aq më pak çonka do të lëvizin në sistemin e skedarëve brenda pishinës, dhe sa më e ulët është ngarkesa në disk.
- Për problemin tonë, filluam të kërkojmë zgjidhje të tjera, për të cilat do të flasim në seksionin në vijim.
Standi i dytë, teknologjia ZFS
Dikur kam pasur të bëj me sistemin e skedarëve ZFS, por atëherë ZFS funksiononte mirë në familjen e saj të sistemit operativ Solaris. Ekzistonte një version i portuar në FreeBSD me një nivel të mjaftueshëm implementimi. Po ashtu kishte një port të papërfunduar në Linux, të cilin shumë pak njerëz e përdornin. Për shkak të strukturës së ruajtjes së të dhënave B-tree (në të vërtetë, e njëjta strukturë ruajtjeje e ka edhe InnoDB MySQL), ZFS ka dështuar në instalimet me një numër shumë të madh skedarësh. Të gjitha këto, përveç nevojës për të mësuar materialin themelor para përdorimit, e përjashtuan këtë sistem skedash nga praktika ime për një kohë të gjatë. U shfaqën ext4 dhe xfs, të cilat u bënë standard. Megjithatë, duke marrë parasysh se ZFS përshtatet më shumë se mirë për nevojat tona, dhe versioni i Linux, sipas komentëve, është rritur në një produkt të arsyeshëm (edhe pse jo me mbështetje të plotë, për këtë arsye sistemi mund të vendoset në ZFS plotësisht nga e para vetëm me ndihmën e disa manovrave), ne vendosëm ta provojmë.
Për arsye të qarta, u zgjodh një stendë me konfigurim të ngjashëm (përveç kontrolluesit RAID). Instaluan tetë disqe SSD prej 1920 GB. Nuk kishte dëshirë të shkruanin imazhin e rrjetit të tyre për të ngarkuar serverin mbi ZFS të papërpunuar, prandaj morëm nga të gjithë disqet 50 GB dhe bëmë një RAID-10 MD për sistemin. 1950 GB të mbetur në secilin disk u bashkuan në një ZFS të ngjashëm me RAID-10:
zpool create zpool mirror /dev/sda2 /dev/sdb2 mirror /dev/sdc2 /dev/sdd2 mirror /dev/sde2 /dev/sdf2 mirror /dev/sdg2 /dev/sdh2Krijuam particione për MySQL:
zfs create zpool/mysql
zfs set compression=gzip zpool/mysql
zfs set recordsize=128k zpool/mysql
zfs set atime=off zpool/mysql
zfs create zpool/mysql/data
zfs set recordsize=16k zpool/mysql/data
zfs set primarycache=metadata zpool/mysql/data
zfs set mountpoint=/var/lib/mysql zpool/mysql/dataVini re se kemi aktivizuar kompresimin e tĂ« dhĂ«nave gzip. Burimet procesorĂ«ve nĂ« serverin tonĂ« janĂ« tĂ« shumta dhe nuk pĂ«rdoren plotĂ«sisht. Si rezultat, 3 TB e DB-sĂ« sonĂ« u shndĂ«rruan nĂ« 1,6 TB, dhe meqenĂ«se pika e dobĂ«t, ashtu si nĂ« rastin e kaluar, Ă«shtĂ« performanca maksimale e disqeve, aq mĂ« pak tĂ« dhĂ«na â aq mĂ« mirĂ«, ne qĂ« nĂ« fillim marrim njĂ« bonus tĂ« shkĂ«lqyer nga ZFS! NĂ« orĂ«t e pikut, nĂ«n ngarkesĂ« tĂ« plotĂ«, ruajtja e funksionimit tĂ« gzip merr deri nĂ« 4 bĂ«rthama, por nuk na shqetĂ«son.
Implementimi vazhdoi më shpejt. U kopjua konfigurimi i replikës MySQL nga stenda LVM. Duhej të kalonim një kohë të caktuar për të shkruar përsëri skriptet në komandat ZFS, por në përgjithësi algorithmet mbetën të njëjta. Shembujt për krijimin e një snapshot-i:
zfs set snapdir=visible zpool/mysql/data
zfs create zpool/stage_3307
zfs clone zpool/mysql/data@snapmain zpool/stage_3307/data
zfs set mountpoint=/mnt/stage_3307 zpool/stage_3307/dataNga tuning suplementar: nxorrëm në memorjen e seksioneve ZFS me metadatat dhe logjete l2arc dhe zil. Për detyrën tonë, siç u pranua më vonë, kjo ishte e tepërt, por deri tani e kemi lënë këtë optimizim; duke e ndryshuar në rast se është e nevojshme, nuk është e vështirë. Nga efektet negative - pas rinisjes së serverit duhet të krijojmë përsëri përfshij përkatëse të memorjes. Të dhënat në këtë rast nuk humbasin. Shkurtimi i zpool status:
logs
/dev/shm/zil_slog.img ONLINE 0 0 0
cache
/dev/shm/l2arc.img ONLINE 0 0 0Në këtë konfigurim filluam të testojmë stendën dhe morëm rezultate të shkëlqyera: me dy instanca të DB që punonin njëkohësisht (dhe replikën kryesore aktive) në snapshot-e, fituam ngarkesë të disqeve prej 50-60 %.
Ne kemi eliminuar problemin tonë kryesor, i cili është i dukshëm në grafikën e vonesës së riprodhimit (krahasuar me grafikën e mëparshme në seksionin Thin LVM):

Përveç kësaj dhe falë kësaj ne kemi përshpejtuar ndjeshëm të gjitha operacionet: krijimi i plotë i snapshot-it me ndalimin dhe ripërtritjen e riprodhimit zgjat deri në 40 sekonda, ndërsa shpërndarja e një instance të re MySQL nga snapshot-i zgjat deri në 20 sekonda. Kjo na kënaq si neve, ashtu dhe testet tona të kodit.
Përfundimet ndërmjetëse:
- Rezultatet plotësuan plotësisht nevojat tona për marrjen e një kopjeje të bazës së të dhënave prodhuese për testingun e kodit.
- Teknologjia kërkon njohuri: duhet të kuptohet se çfarë është ZFS dhe si të punohet me të.
- Nuk e kemi kontrolluar statusin aktual të punës së ZFS me një numër të madh (nga 1 milion) skedarësh të vegjël. Por supozojmë që problemi vazhdon të egzistojë, prandaj nuk do ta rekomandoja këtë sistem skedarësh për ndonjë depo të skedarëve.
ĂfarĂ« ndodh mĂ« tej?
NĂ« kuadĂ«r tĂ« stendĂ«s nuk do tĂ« bĂ«jmĂ« asgjĂ« tjetĂ«r, rezultati na kĂ«naq. Ndoshta nĂ« vijim do tĂ« shtojmĂ« nĂ« cilĂ«simin e replikimit tĂ« stendĂ«s pĂ«rjashtimet e tabelave qĂ« nuk janĂ« tĂ« nevojshme pĂ«r testim, kjo do ta reduktojĂ« akoma mĂ« shumĂ« volumet e DB-sĂ«. Nuk e kemi testuar sistemin BTRFS dhe implementimin e tij tĂ« teknologjisĂ« tĂ« rezervimit tĂ« hollĂ«. MegjithatĂ«, njĂ« detyrĂ« e tillĂ« nuk Ă«shtĂ« mĂ« nĂ« rendin e ditĂ«s, pasi qĂ«llimi kryesor Ă«shtĂ« arritur. PĂ«rgjithĂ«sisht, sigurisht, dĂ«shirojmĂ« tĂ« largohemi nga qasja e pĂ«rshkruar mĂ« lart â tĂ« realizojmĂ« migrime funksionale tĂ« DB-sĂ« nĂ« ambientin e testimit, tĂ« krijojmĂ« njĂ« rreth tĂ« veçantĂ« testimi tĂ« DB-sĂ«, tĂ« merremi me sharding-un e bazĂ«s kryesore. ShumĂ« nga kĂ«to tashmĂ« po i realizojmĂ«, pĂ«r tĂ« cilat gjithsesi do tâi raportojmĂ« nĂ« artikujt e ardhshĂ«m.
Përfundimet
Detyra fillestare është zgjidhur, ndonëse në një mënyrë të pazakontë. Në përfundimet ndërmjetëse janë përshkruar avantazhet dhe disavantazhet e çdo teknologjie të aplikuar, prandaj le të vendosim se cila teknologji dhe kur mund të përdoret:
- Thin LVM â pĂ«r DB tĂ« vogla dhe kur nuk dĂ«shirojmĂ« ose nuk kemi kohĂ« tĂ« mĂ«sojmĂ« ZFS.
- ZFS â nĂ«se kemi pĂ«rvojĂ« nĂ« punimin me tĂ« ose mundĂ«sinĂ« pĂ«r tĂ« shpenzuar kohĂ« pĂ«r tĂ« mĂ«suar nĂ« tĂ« gjitha situatat.
Në një nivel më të lartë të përfaqësimit, ky artikull nuk është thjesht një krahasim i teknologjive të dy sistemeve të skedarëve. Ideja kryesore që do doja të përçoja dhe konsolidoja është se nuk duhet të kemi frikë nga mendimi jashtë kutisë në situatat kritike për biznesin dhe të marrim vetëm receta të gatshme. Njëherë mund të kishim goditur kokën me të gjithë departamentin teknik dhe të thoshim se detyra e krijimit të kopjeve të dhënash prej tre terabajtesh për më pak se një minutë është e pamundur, dhe nuk na duhen teknologji të rrezikshme, le të bëjmë siç duhet. Kjo ishte e mundur, por do të kishim humbur about gjashtë muaj-një vit dhe shumë udhëtime klientësh (udhëtimet janë indikatorët tanë kryesorë të biznesit) pa teste dhe gjatë zbatimit. Duke menduar ndryshe, humbëm jo kaq shumë kohë në zbatim, fituam përvoje në teknologji të reja dhe të harxhuara, dhe ofruam teste pikërisht në momentin kur kishim shumë nevojë për to. Pa dyshim, kjo kishte një efekt pozitiv në të gjitha treguesit tanë. Zgjedhja është gjithmonë e juaja, ndërsa ne nga ana jonë do të vazhdojmë të flasim në blogun tonë mbi arritjet interesante aktuale dhe të ardhshme.
Burimi: habr.com
