Engineering Notes
2.45K subscribers
137 photos
5 files
208 links
Kanalda asosan backend engineeringga oid postlar yozib boriladi.

Ba'zi postlarda xatoliklar bor.
Postlar foydali bo’lgan bo’lsa adminni duo qilib qo’ying. Rahmat.

Contact: @Bobosher_Musurmonov
LinkedIn: https://www.linkedin.com/in/bobosher-musurmonov
Download Telegram
PostgreSQL 9.1 versiyasidan boshlab MySQL, Oracle kabi boshqa ko'plab Relational Database Management Systemlarda, shu qatorda ANSI SQL-92 standartlarida ham yo'q bo'lgan yangi xususiyat qo'shildi. Ya'ni shu versiyadan boshlab PostgreSQLning Multi Version Concurrency Control mexanizmi Repeatable Read izolyatsiya darajasidagi tranzaksiyalarda ANSI SQL-92 standartida ko'rsatilgan Phantom Read anomaliyasi (boshqa tranzaksiya tomonidan yangi row qo'shilishi) sodir bo'lishining to'liqligicha oldini oladi.

P.S. Endi shu gapni dasturlashdan xabari yo'q tanishingizga aytib ko'ring ))
👍7😁1
Bu PostgreSQLning "lost updates"ning oldini olish uchun ishlatadigan logikasi.
Tranzaksiya ma'lumotni o'zgartirish vaqtida u ma'lumotni lock qiladi, ya'ni qulflaydi. Agar shu vaqtda boshqa tranzaksiya shu ma'lumotni o'zgartirmoqchi bo'lsa, narigi tranzaksiya ishini tugatib, lockni ochgunicha kutib turadi. Mana bu usul pessimistic concurrency control deyiladi.
Sababi, bu yerda tranzaksiyalar boshqalar ma'lumotni o'zgartirishidan qo'rqib, har doim lock olib yuradi (yomg'irdan qo'rqib, har doim soyabon olib yurgan odamdek). Natijada updatelar sekinlashadi.

Lost updatesning oldini olishning oldini olishning yana bir usuli optimistic concurrency control deyiladi. Bunda hech qanday lock ishlatilmaydi. Bu tranzaksiyalar optimist, hayotning yaxshi tarafiga umid qiladi. Shunchaki tranzaksiya boshida va oxirida ma'lumotlar bir ekanini tekshiradi. Agar bir xil bo'lsa, unda commit qiadi. Mabodo ma'lumot o'zgargan bo'lsa, demak yomg'ir yog'gan, endi tranzaksiya abort qilinadi.

©️ https://www.interdb.jp/pg/pgsql05.html
👍2
Databaselardan biroz uzoqlashamiz.
Network engineer bo'yicha quyidagi savollarga javob berib, bu sohadagi boshlang'ich bilimlaringizni sinab ko'ring:

1. Ikkita qurilmada bir xil MAC addressi bo'lishi mumkinmi?

2. OSI va TCP/IP modellarining asosiy vazifasi nima?

3. Nega streaming uchun asosan UDP protokoli ishlatiladi?

4. Qurilmadagi ma'lum portga kelayotgan requestlarni bloklaydigan firewall qurmoqchisiz. Bunda firewall OSI modelining eng kamida qaysi qavatida turishi kerak?

5. HTTP/1.1 protokolida 2 ta qurilma orasida bir vaqtda parallel 6 ta connection ochish mumkin. Lekin HTTP/2 protokolidagi 1 ta connection bu 6 ta connectiondan ko'ra ko'proq ma'lumot tashiy oladi. Qanday qilib?

6. Netmask nima uchun ishlatiladi?

7. ARP poisoning nima?

8. Diffie-Hellman kalit almashish algoritmi qanday ishlaydi?

9. TLS termination nima va qachon ishlatiladi?

10. Reverse proxy request pathga qarab requestni backend servislardan biriga yo'naltirishi uchun u OSI modelining qaysi qavatida ishlashi kerak?

11. UDP holepunching nima va nega TCP bilan bog'liq bunday narsa yo'q?

12. DNS spoofing nima?

13 DDoS xujumlaridan himoyalanishning eng sodda usullari qanday?

14. HTTP request tarkibidagi keep-alive headeri qanday vazifani bajaradi?

15. TCP paketlari hajmini kattalashtirishning qanday yaxshi va yomon taraflari bor?

Bu savollarning nechtasiga javob bera oldingiz?
Agar javobingiz 15 dan kam bo'lsa, tabriklayman, bugun o'rganish uchun mavzu topildi.

P.S. Savollar yoqqan bo'lsa, tanishlarga yuboring.

P.S.2: Shaxsiy kanalingiz bo'lsa, kanalingizda forward qilsangiz, undan ham yaxshi ))
👍16
print("Hello world")

Bu kodni biz yaxshi bilamiz.
Lekin bu postni o'qiyotganlarning 99% qismi bu kod aslida qanday ishlashini bilmaydi. Ha, aynan shunday.
To'g'ri, Python interpreter kodni o'qib, execute qiladi deyishingiz mumkin, lekin o'sha execute qilish o'zi nima?
Buni siz yozgan bir qator koddan boshlab CPU, RAMda nima sodir bo'lishi-yu, kompyuteringizdagi har bitta atom qanday harakatlanishigacha tushuntirib bera olasizmi? Katta ehtimol bilan, yo'q.

Endi o'rinli savol: Hatto "Hello world" qanday ishlashini bilmaydigan dasturchi qanday qilib sun'iy intellekt yaratishi mumkin?

Gap shundaki, dasturlashda biz hamma narsani noldan, aniqrog'i nolgacha chuqur o'rgana olmaymiz. Xo'sh, unda o'sha chuqurlikni qanday yopamiz? Axir uy tomdan boshlab emas, asosdan boshlab quriladi-ku. Javob – abstraksiya orqali.
Ya'ni biz ichki ishlash tizimini bilmaydigan (ko'p hollarda bilish zarur bo'lmagan) narsalarni shunchaki ishlaydi deb hisoblaymiz yoki qanday ishlashi haqida aslidan farq qiladigan, sodda tushunchaga ega bo'lamiz (aslida bu ham biroz pastroqdagi abstraksiyalar yig'indisi).

Masalan, eng oddiy backend server yozayapsiz va u request kelganida databasedan ma'lumot olib, response yuboradi.
Buni qilish uchun request o'zi nima, uni qanday olamiz, database qanday qilib ma'lumot beradi va hokazolarni bilishimiz shart emas. Ular "shunchaki" o'z vazifasini bajaradi deb hisoblaymiz.

Natijada bizda tizim qanday ishlashi haqida minimal ma'lumot bilgan holda uni ishlab chiqish imkoniyati paydo bo'ladi. Ya'ni aynan abstraksiya sabab komputerdagi har bitta atom qanday ishlashini bilmay turib ham dastur ishlab chiqa olamiz.

Lekin rivojlanishni xohlasangiz, abstraksiyalarni buzib kirishdan qo'rqmang. Yanada chuqurroqqa tushish sizga ko'proq narsani ko'rish va o'rganish imkonini beradi. Natijada biror texnologiya haqida oldin bilgan narsalaringiz noto'g'ri ekanini va u aslida boshqacha ekanini tushunasiz. Oldingi tushunchalaringiz esa kulguli darajada oddiy tuyulishni boshlaydi.
Yana ozgina pastroqda tushsangiz, o'sha "batafsil" bilganlaringiz ham juda oddiy ko'rinadi.

Lekin abstraksiyalarni buzib, chuqurroqqa tushish bizga o'zi kerakmi?
Bilmadim, bu sizga bog'liq. Shaxsan menga end-user ishlatadigan mahsulot ishlab chiqishdan ko'ra boshqa dasturchilar ishlatadigan toollar ishlab chiqish yoqadi. Menga "chuqurroqda" ishlash yoqadi.

Update: Juda yaxshi misol berilgan komment yozildi, biroz o'zgartirib, postga qo'shib qo'yaman:
Har kuni mashinani o't oldiramiz va haydab, ishga boramiz. Lekin buning uchun mashina qanday ishlashini bilish shart emas.
Agar mashinadan faqat ishga borish uchun foydalansangiz, shu yetarli.
Lekin siz mashina tuzatadigan yoki ishlab chiqaradigan mexanik bo'lsangiz ichki qismlar va ular qanday ishlashini albatta bilishingiz kerak bo'ladi.
👍31
RDBMS, umuman DBMSlar haqida 20 ta savol.
Qolganlaridan qiyinroq savollar * bilan belgilangan.


1. ACID xususiyatlaridan biri bo'lgan atomicity nimani bildiradi?

2. RDBMSlarda qaysi holatlarda denormalizatsiya qilish foydali hisoblanadi?

3. Database cursor nima? Server-side cursorning client-side cursordan ustun tomoni qaysi?

4. Database engine nima?

5. Read committed va repeatable read izolyatsiya darajalarining orasidagi asosiy farq nimada?

6. Pessimistic Concurrency control nima? Uning qanday kamchiliklari bor?

7*. Transaction snapshot nima?

8*. Serialization anomaliyalaridan biri bo'lgan rw-conflict qachon sodir bo'ladi?

9. Connection pool haqida ma'lumot bering.

10. Clustered index bilan non-clustered indexning farqi nimada?

11*. B-tree va B+tree orasidagi farq nimada?

12. Master va slave replicalar orasida to'liq consistencyni qanday ta'minlash mumkin?

13. Database sharding nima?

14*. Row-based storage nima? U nima uchun OLAP operatsiyalari uchun yaxshi tanlov emas?

15*. WAL nima?

16. PostgreSQLda vacuuming nima?

17. PostgreSQLda index scan va index-only scan bir-biridan qanday farq qiladi?

18. PostreSQLda view nima?

19. PostgreSQLda ANALYZE buyrug'i nima vazifani bajaradi?

20*. PostgreSQLda SELECT FOR UPDATE komandasi nima vazifani bajaradi?


P.S. Bu savollardan ba'zilari backend developer uchun texnik intervyularda tushishi mumkin.

P.S.2. Agar to'g'ri javoblaringiz soni 20 dan kam bo'lsa tabriklayman, o'rganish uchun sizga yangi mavzu topildi.
👍15
Pythonda yozilgan applicationlarda background tasklar uchun Celery ishlatish ancha keng tarqalgan usul. Ochig'ini aytsam, bu softwareni unchalik yoqtirmayman. Ko'p featurelarni implement qilishga harakat qilishadi, lekin u featurelar ning ko'pchiligi native ishlab keta olmaydi.
Eng yomoni, bu "oqsagan" featurelar boshqa, oldin yaxshi ishlayotgan featurelarga ham yomon ta'sir qiladi.
Celeryning umumiy arxitekturasini va ayniqsa, network layerni butunlay qayta ko'rib chiqish kerak deb o'ylayman.

Yetarlicha vaqtingiz bo'lsa, biror tayyor MQdan foydalanib(Redis, RabbitMQ, Kafka), loyihangiz uchun maxsus background task tizimini qurishni tavsiya qilaman. Katta loyihalarda Celery ishlatish unchalik to'g'ri variant emas ekan.

P.S. Yoki sekin EDAga o'ting. Agar shunga arzisa.
👍7
#savol
Why HTTP/3 uses UDP instead of TCP?

#javob
I think the main reason why HTTP/3 (which uses QUIC) is built on top of UDP instead of TCP is to solve the problem with lost packets in HTTP/2.

One of the biggest problems with h2 is that streams (a logical communication for a single request) are not fully independent from each other. Since the TCP retransmission works on layer 4 of the OSI model but h2 itself is implemented on layer 7, the TCP connection has no knowledge of h2 streams. So if a single TCP packet is missing in one of the streams, TCP blocks the entire connection (thus, all the streams on it) till the missing packet is retransmitted successfully.
That means, if I try to send 10 request at the same time over h2 and if any of them fails to reach, all 10 requests are blocked. This is called HOL blocking, but on the transport layer.

HTTP/3 solves this problem by using QUIC, which is built on top of UDP. Since UDP does not guarantee delivery of data, it has no retransmission mechanism. QUIC has its own recovery mechanism that guarantees delivery. Unlike TCP, this recovery mechanism works on the same layer as the QUIC streams and knows which packet belongs to which stream. That's why if any packet is lost, the recovery mechanism blocks only the stream that packet belongs to. It does not affect other streams.
👍5
"NEGA?"
Forwarded from Nuruddin Blogs
Hamma narsani o’rganish uchun retsept - qiziquvchanlik.

Kung fu pandada lag’monni sehrli siri ham shu bo’lgan menimcha )

@nuruddinblogs
👍7
Inkapsulyatsiya

Inkapsulyatsiyaga misol:
- Shashlik yemoqchisiz, shashlikchini oldiga bordingiz
- Mana 2 kg go'sht,1kg qiyma,1kg jaz shashlik bo'lsin
- Go'shtni berasiz, u sizga tayyor shashlik qilib beradi

Nimasi inkapsulyatsiya?
- Shashlikchi - Class
- Unga go'sht berasiz - constructor
- Shashlikka qo'shiladigan ziravorlar - property
- Shashlik qilish uchun myasarovkadan chiqaradi, marinovka qilish, muzlatadi - bular methodlar
- Shashlikga qo'shadigan ziravori bor, uni faqat shashlikchi biladi - private property
- Shashlik sixdan oqib tushmaslik uchun xxx ishni qiladi, bu ham uni siri - private method
- Shashlikchi shu sirlarini faqat farzandlariga o'rgatgan, ular ham bu shashlik qilish usulidan foydalanishadi - protected method

Siz shashlikchini qanday tayyorlaganiyu nimalar qo'shganini, hammasini bilolmaysiz, lekin shashlik tayyor.
U shu private va protected sirlarini tashqariga chiqarishni xohlamaydi - manashu inkapsulyatsiya, ya'ni sirlarini himoyalaydi.

Xato misol bo'lsa iltimos to'g'rilang.
👍23
Forwarded from Programming ∀
Frameworklar ko'p holatlarda biror ishni osonlashtirish uchun ishlab chiqilgan yoki ishlab chiqiladi. Lekin juda ko'p frameworklar antipatterlar asosiga qurilgan. To'g'ri u nimadurni yaxshilaydi nimaduni osonlashtiradi samaradorlikni oshiradi deyiladi. Lekin ko'p holatlada qo'pol ravishta patternlar va prinsplarga zid ishlar qilinadi. Notogri ideologyni imrove qiladi. Masalan ko'p frameworklada controller tushunchasi mavjud. Bu narsa handler vazifasini bajaradi. OOP tomonlama qarasa bu holatda class qandaydur protseduralar yegindisi bo'lib qoladi )) Yoki boshqacharoq misol:

DTO tushunchasi. Getter va setterlar yegindisi. Bu component yoki layer ko'p holatlarda shunchaki protseduralar yegindisiga aylanadi. Object o'z hususiyatlarini yoqotadi.
👍2
Programming ∀
Frameworklar ko'p holatlarda biror ishni osonlashtirish uchun ishlab chiqilgan yoki ishlab chiqiladi. Lekin juda ko'p frameworklar antipatterlar asosiga qurilgan. To'g'ri u nimadurni yaxshilaydi nimaduni osonlashtiradi samaradorlikni oshiradi deyiladi. Lekin…
Shaxsiy fikrim:

Ha, ko'pchilik frameworklar antipatternlar asosiga qurilgan va bu ma'lum darajada asosli.
Agar frameworklar to'liq biz bilgan toza konseptlar asosida yozilganida ular orqali minimal "ishlaydigan" kod yozish hozirgidan ko'ra ancha qiyin bo'lgan bo'lardi.

$20 ga bozordan sifati meni qoniqtiradigan krossovka sotib olsam, Nike meni ularning san'at asari darajasida ishlab chiqilgan $200 turadigan krossovkasini sotib olmaganim uchun ayblay olmaydi. Sababi, menda o'sha mahsulotga ehtiyoj va yetarli mablag' yo'q. O'zim olgan mahsulot sifat va narx jihatidan meni qoniqtiradi.

Xuddi shunday, ko'pchilik kichik va o'rta kompaniyalar va ularning tepasida o'tirgan biznesmenlar uchun siz va men qurishni xohlaydigan ideal (yoki shunga yaqin) dastur kerak emas. Buning uchun ehtiyoj va yetarlicha resurs yo'q ularda.
Siz va men ular aytgan resurslar evaziga software ishlab chiqishga rozi bo'lmasak ham, buni qiladiganlar albatta topiladi va bu tabiiy. Keyin sifat ham shunga yarasha bo'ladi.

Ko'pchilik frameworklar esa o'sha "qoniqarli sifatli" software ishlab chiqish uchun arzon yarimtayyor mahsulot. Agar o'sha frameworklardan foydalanib, yuqori sifatli dastur ishlab chiqmoqchi bo'lsangiz, frameworkni anchagina customize qilishingiz kerak va FAANGda ham shunday qilishadi.
👍12
Emotional damage 😢
👍18😁4👎3
Forwarded from Programming ∀
#paradigms

Biror dasturiy ta'minotni tuzish uchun xozirgi kunda ko'p holatda juda yuqoridan qaraymiz. Frameworklar tayyor solutionlar pattenlar. Albatta bular muhim ammo juda ko'p xamkasblarda asosiy muammo paradigmalar. Ko'plab dasturchilar uslub, yondoshuvni dasturlash tillaridan olishadi (Shaxsan o'zim ham shu kungacha). Lekin ushbu xolatda bizda bir tomonlama fikrlash juda o'sib ketishi mumkin. Bu esa albatta birkun zararga ishlashi mumkin.

Nega ? Bazi tillarda faqat bir paradigmani tadbiq qilingan. Bu esa umumiy dasturlashni shu doirada ko'rishga o'rgatadi Masalan C. Bazilarida esa multi paradigm lekin juda tartibsiz va sifatiz code yozish extimoli yuqori. Masalan JS. Bazi tillarda til implement qilgan paradimgdan boshqasini tadbiq qila olmaysiz bu bir tomondan juda zo'r boshqa tomondan unchalik emas. Agar shunday bo'lsa JS kabi bo'lish extimoli yurqori.

Yuqorida aytganimday biror muammoga nisbatan berilgan yechim turli yo'llar orqali qilingan bo'lishi mumkin.

Anchadan buyon faqat JS/TS stackda ishlab shu paradigmlar masalasida ko'p chalkashaman. Endi yaxshi expirement boshladim. Paradigmlarni boshqa tillarda o'rganishni boshladim bu narsa ushbu falsafalarni yaxshiroq tushunish va tadbiq qilishga yaxshigina yordam beryabti. Masalan ruby va Java Rubydagi OOP manga ancha yoqdi Javaga qaraganda. Syntax yondoshuv va implementation ancha sugar. Paralell programming uchun esa Go birmuncha yoqdi. Functional programmingni Elixirda sinab ko'rvoman. Bu tajribalar manimcha yillar davomida bo'ladi chunki aniq biror muammoga ushbu bilimlarni tadbiq qilib ko'rish kerak. Lekin bir narsani tushundimki Universal Dasturlash tilining yo'qligiga asosiy sabablardan biri bu paradigmlar ko'pligi. Bu tajribani boshlaganimdan keyin ancha yegilib qolgan savollarga javob topishni boshladim. Lekin xozircha JS/TS dan boshqasida erkin emasman. Manimcha dasturlashni o'rganishda eski classic progamming yoki old school unchalik mos emas xozirgi kunda.

Misol uchun JS bilan OOP o'zini o'rganish birmuncha qiyin yoki design patternlani. Yoki C++ bilan FP ni o'rgana olishiz qiyin. Undan ko'ra aynan OOP yoki FP yaxshiroq tadbiq qilingan tilda o'rgangan yaxshiroq deb o'ylayman. System engineering uchun C ancha qiziq edi manga. Ammo fikrim o'zgardi Rust.

Sizda ham shunday bo'shliqlar bo'lsa qanday to'ldirasiz yoki hali bo'lmagan bo'lsangiz sabringiz yetsa yuqorida yozganimday uslubni tavsiya qilaman.

PS: Ushbu postdan maqsad tillarni yaxshi yomon deb solishtirish emas. Dasturlashni yaxshioq o'rganish va chuquroq tushunish uchun bir uslubni yoritishdan iborat.

PS++: Postda qaysidur tilni yaxshi bilish yoki bilmaslikga davo qilinmagan !!!
👍18👎3
PostgreSQLda index create qilayotganda fillfactor nomli parameter bor. Qisqasi, b-tree page(node)ning qancha qismi to'lganidan keyin bu index pageni to'lgan deb hisoblanib, keyingi pagega yozishni boshlashni bildiradi. Nega 100% to'ldirib, keyin keyingi pagega o'ta olmaymiz? Sababi pageda valuelar tartiblangan bo'ladi, agar tartib bo'yicha shu to'lgan pagega to'g'ri keladigan yangi qiymat kiritilsa, uni shu yerga sig'dirish uchun pageni split qilib, qayta organize qilishga to'g'ri keladi. Bu xuddi arrayning o'rtasiga element qo'shish uchun undan keyingi qismini orqaroqqa surishga o'xshaydi, lekin storege levelda bu yanayam "painful" bo'ladi. Buning oldini ma'lum darajada olish uchun pagening bir qismini oldindan bo'sh qoldirib qo'yish mumkin. Shu pageda turishi kerak bo'lgan yangi qiymat kelganida qolgan valuelarni bezovta qilmasdan, shu yerning o'ziga sig'dirish mumkin bo'ladi.

Index fillfactor index pagening necha foizi to'lganidan keyin yangi pagega o'tishni ko'rsatadi. Default holatda 90%, ya'ni 10% qismi bo'sh turadi. PostgreSQL dokumentatsiyasi bu qiymatni 50-90 foiz oralig'ida ushlashni tavsiya qiladi.
Kamroq fillfactor write operationlar kutilmaganda sekinlashib qolishini kamaytiradi, lekin searchni biroz sekinlashtiradi (fillfactor past bo'lsa, index pagelar soni ko'payadi, ko'proq page ko'proq vaqt degani) va ko'proq joy oladi.

Qachon fillfactorni yuqori qilish tavsiya qilinadi:
1. Tableda write operations juda kam bo'lsa yoki umuman bo'lmasa. Deyarli yoki to'liq static table 100% index fillfactordan kamroq zarar ko'radi.
2. Read performance write performancedan ko'ra muhimroq bo'lsa.
3. Qiymatlar aynan tartib bilan kiritilsa va updatelar juda kam bo'lsa.

Qachon fillfactorni pastroq qilib belgilash tavsiya qilinadi:
1. Write operationlar juda ko'p va tartibsiz bo'lsa.
2. Write performance read performancedan ko'ra muhimroq bo'lsa.
3. UUID yoki GUID bilan ishlaganda.
👍14
Algoritmlar bilan ishlashni endi boshlaganlarida tug'iladigan klassik savol:
Sort qilinmagan arrayda biror elementni izlash O(n) vaqt talab qiladi.
Sort qilingan arrayda esa qidiruv O(log n), lekin sort qilishning o'zi O(n * log n) vaqt oladi. Demak, arrayni sort qilib, elementni izlash sort qilinmagan arraydagi qidiruvdan ko'ra ko'p vaqt oladi. Unda sort qilishning nima keragi bor?

Javob: Sort qilinmagan arrayda har bir search uchun O(n) sarflanadi. Sort qilingan arrayda esa sort qilish uchun esa O(n * log n), keyingi har bir search uchun O(log n) vaqt sarflanadi. Bir martalik operatsiya uchun sort qilmasdan qidirish tezroq bo'lsa-da, umumiy m ta (m >> n) qidiruv uchun sort qilmasdan qidirish O(m * n), sort qilib, keyin qidirish esa O(m * log n) vaqt talab qiladi.
Xulosa qilganda, kelajakdagi qidiruvlarni ham hisobga olganda, arrayni tartiblash foydali.

P.S. Bu savolni yaqinda bir guruhda ko'rgandim, bugun bir kishi shaxsiyda shu savolni so'rabdi. Kimgadir foydali bo'lsa, xursand bo'laman.
👍31
Celeryning arxitekturasida, ayniqsa networking qismida yetarlicha muammolar borligi haqida avvalroq yozgandim.

2019-yil Doordash asinxron tasklar uchun RabbitMQ + Celery stackdan Kafka + custom workerlarga o'tishiga asosiy sabablardan biri ham aynan Celeryning networking muammolari bilan bog'liq bo'lgan ekan.
Doordash Engineering blogida bu jarayon qanday o'tgani haqida batafsil maqola bor ekan. Asosiy va ikkinchi darajali muammolarni analiz qilishdan boshlab potensial yechimlarni ko'rib chiqish, yangi arxitekturaga qanday muammosiz o'tish/moslashish va yangi arxitekturadagi muammolar qanday tuzatilganigacha yozilgan (batafsil bo'lmasa ham, yetarlicha).
Erinmasdan oxirigacha o'qib chiqishni tavsiya qilaman:
https://doordash.engineering/2020/09/03/eliminating-task-processing-outages-with-kafka/
👍15
Hali ko'rmaganlar uchun:
https://youtu.be/wlRbDg8-QH0

P.S. Xato va kamchiliklarini commentda yozsangiz xursand bo'lardim.
Bu keyingi talklar yaxshiroq bo'lishiga xizmat qiladi.
👍5