Redis-ը (Remote Dictionary Server) – դա բաց կոդով NoSQL դասի տվյալների բազաների կառավարման ռեզիդենտ համակարգ է (անգլ. in-memory database, IMDB), որն աշխատում է «բանալի-արժեք»(key-value) տիպի տվյալների կառուցվածքների հետ: Օգտագործվում է ինչպես տվյալների բազաների, այնպես էլ քեշավորման իրագործման և հաղորդագրությունների բրոքերի դերում: Redis-ը մեծ տարածում ունի ծրագրավորողների շրջանում իր գերարագության և տարբեր տեսակի տվյալների կառուցվածքների սպասարկման շնորհիվ, ինչպիսիք են տողերը, հեշերը, ցուցակները, հավաքածուները, գրաֆիկական նկարները, հոսքերը(stream) և այլն:
Ավելին, Redis-ն ունի բազմաթիվ ներկառուցված հնարավորություններ, ինչի պատճառով այս համակարգը այդքան պահանջված է. ներկառուցված կրկնօրինակումը-ռեպլիկացիան, Lua սցենարները, LRU-ի ջնջման ալգորիթմը, տրանզակցիաները և այլն: Հոդվածում մենք կխոսենք հոսքերի մասին, որը Redis-ի տվյալների կառուցվածքների տեսակներից մեկն է: Մենք կարող ենք հոսքերն օգտագործել՝ միկրոսերվիսի և նրա սպառողի(անգլ.՝ consumer, ռուս.՝ потребитель) միջև հաղորդագրությունների փոխանակման ծառայության համար:
Կարճ ասած, տվյալների այս կառուցվածքը մենք կարող ենք օգտագործել որպես հաղորդագրությունների բրոքեր, որի միջոցով միկրոսերվիսները կկարողանան փոխգործակցել: Այսպիսով…
Ի՞նչ են իրենցից ներկայացնում Redis-ի հոսքերը
Եթե փորձենք ամենապարզ ձևով սահմանել՝ հոսքերը դրանք Redis-ի տվյալների կառուցվածքներ են, որոնք հասանելի են միայն ավելացման համար: Այն ունի որոշակի նմանություն տվյալների մեկ այլ տիպի՝ ցուցակների(list) հետ, սակայն ավելի օգտակար և բարդ է: Հոսքային փոփոխականի մեջ տվյալներ/հաղորդագրություններ ավելացնելուն պես դրանք հասանելի են դառնում սպառողների համար: ԱՐԳԵԼԱՓԱԿՈՂ/ԲԼՈԿԱՎՈՐՈՂ API-ի շնորհիվ մենք կարող ենք ստիպել սպառողներին նոր հաղորդագրություններին սպասել: Այսպիսի տվյալների ստրուկտուրան տարբերվում է բարձր արագագործությամբ և իրագործման պարզությամբ: Սպառողները կարող են միավորվել սպառողների խմբերում, ինչը հնարավորություն կտա հաղորդագրությունների տարբեր ենթաբազմություն ուղարկել տարբեր սպառողների:
Կիրառման օրինակ
Ենթադրենք՝ ունենք երկու միկրոսերվիս, MS-1 և MS-2: Նրանց միջև փոխազդեցության կամ տվյալների սինխրոն փոխանակման անհրաժեշտություն կա: Նման սցենարի դեպքում առաջին պլան է գալիս հաղորդագրությունների փոխանակման ծառայությունը: Redis-ի հոսքերը դիրքավորվում են MS-1-ի և MS-2-ի միջև և հանդես են գալիս որպես հաղորդագրությունների բրոքեր/միջնորդ: Նրանք Redis-ի համապատասխան հոսքային փոփոխականների միջոցով հաղորդագրություններ/տվյալներ են փոխանցում MS-1-ից MS-2, և հակառակը:
Պարզության համար ենթադրենք նաև, որ MS-1-ն ինչ-որ տվյալներ է ավելացնում հոսքին, իսկ MS-2-ն անընդհատ լսում է նրան: Այս պարագայում, MS-1-ի կողմից հոսքին տվյալներ ավելացնուն պես, MS-2-ը կստանա դրանք:
Հիմնական գործողություններ
Հոսքի մեջ տվյալն ուղղակի տող չէ, այլ մեկ կամ մի քանի զույգ դաշտերի արժեքներից բաղկացած տող: Առանձնացվում են երկու հիմնական տիպի գործողություններ՝ հոսքի մեջ տվյալների ավելացում և հոսքից տվյալների ստացում:
Տվյալների ավելացում
Գրանցման հիմնական հրամանն այս դեպքում հանդիսանում է XADD-ը, որը նշված հոսքին նոր գրանցում/տվյալ է ավելացնում:
> XADD profile-information * name alex age 27 hair black
Sample Output
-------------------------------------------
1627885225420-0
Վերը նշված հրամանը հոսքի մեջ (profile information) բանալիով նոր գրանցում է ավելացնում: Այս հրամանն ավելի լավ հասկանալու համար փորձենք փոքր ինչ մանրամասնել:
- XADD-ը հրաման է, որը Redis-ին ցուցում է, որ անհրաժեշտ է նոր գրանցում ավելացնել ըստ նշված բանալու:
- Պրոֆիլի ինֆորմացիան (profile-information) - հոսքում մեր բանալի անունն է:
*
սիմվոլը ցուցում է Redis-ին յուրաքանչյուր նոր գրանցման համար մոնոտոն աճող ID ստեղծելուն: Մենք նաև կարող ենք բացահայտ նշել ID-ն, բայց նման պրակտիկա շատ հազվադեպ է կիրառվում, ավելորդ անճշտություններից խուսափելու համար: Սերվերի կողմից ավտոմատ գեներացվող ID-ն լիարժեք բավարարում է բոլոր դեպքերի համար:- Հրամանի մնացած մասը բանալի-արժեք զույգն է, հոսքային գրառման հիմնական բաղադրիչը:
- Հրամանի կատարման արդյունքում ելքում ստանում ենք 1627885225420-0, որն էլ հենց ID-ն է, ինչին կանդրադառնանք ստորև:
Մենք կարող ենք օգտագործել XLEN հրամանը՝ հոսքի մեջ առկա էլեմենտների քանակը ստանալու համար.
> XLEN profile-information
Sample Output
-------------------------------------------
(integer) 1
- profile-information-ը մեր հոսքի բանալի անունն է:
Տվյալների ստացում
Եվ այսպես, արդեն իսկ տվյալ ավելացնելու փորձ ունենալով հանդերձ, հասկանանք, թէ ինչպես կարող ենք հոսքից տվյալներ ստանալ: Այս խնդրի լուծման երեք հիմնական օպերացիա կա, որոնք հերթականությամբ քննարկենք:
Հարցում ըստ դիապազոնի(միջակայքի, տիրույթի). XRANGE և XREVRANGE.
Բայց նախքան շարունակել ըստ դիապազոնի հարցումն ուսումնասիրելը, անհրաժեշտ է ավելի մոտիկից ծանոթանալ իդենտիֆիկատորի հետ (ID): XADD հրամանի արդյունքում վերադարձված իդենտիֆիկատորը, որն ունի 1627796743670–0
տեսքը, ներկայացված է հետևյալ ֆորմատով.
<millisecondsTime>-<sequenceNumber>
(<Ժամանակը միլիվայրկյաններով>-<Հերթական համար>)
Ժամանակը միլիվայրկյաններով — սա տեղական ժամանակն է Redis-ի լոկալ հանգույցում, իսկ հերթական համարն օգտագործվում է գրառումներն իրարից տարանջատելու համար, հաշվի առնելով, որ մեկից ավելի գրառում կարող են ստեղծվել միևնույն պահին և ունենալ միևնույն արժեքն ըստ միլիվարկյաների: Redis-ն ապահովում է այս արժեքների մոնոտոն աճման կարգով բաշխումը:
ID-ների առաջին մասը որպես կանոն(եթե այն գեներացվել է ավտոմատ) ժամանակի դրոշմ է, ուստի մենք հնարավորություն ունենք հարցումներ կատարել ժամանակի(ID-ների) տիրույթների հիման վրա: Ըստ դիապազոնի հարցում անելու համար անհրաժեշտ է նշել երկու իդենտիֆիկատոր՝ սկզբնականն ու վերջնականը՝ համապատասխանորեն: Ուշադրություն դարձրեք, որ ըստ միջակայքի հարցման արժեքները հանդիսանում է ներառվող: Սա նշանակոմ է, որ վերադարձվող տիրույթը կներառի սկզբնական կամ վերջնական արժեքով իդենտիֆիկատորներ ունեցող էլեմենտները ևս:
> XRANGE profile-information - +
Sample Output
-------------------------------------------
1) 1) 1627885225420-0
2) 1) "name"
2) "alex"
3) "age"
4) "27"
5) "hair"
6) "black"
Վերծանենք հրամանն ու ելքը.
- XRANGE-ը ըստ դիապազոնի հարցման հրամանն է:
- profile-information)-ը հոսքի բանալի անունն է:
- (
—
և+
) հատուկ իդենտիֆիկատորները նշանակում են տվյալ հոսքում հաանելի փոքրագույն և մեծագույն իդենտիֆիկատորները, այսինքն այն բազմության սահմանային արժեքները, որի մեջ կատարվելու է հարցումը: - Մենք կարող ենք նաև
—
-ի և+
-ի փոխարեն նշել ցանկացած հասանելի իդենտիֆիկատոր, որով կնշենք անհրաժեշտ դիապազոնի սկզբնական և վերջնական կետերը:
Ըստ ժամանակային միջակայքի հարցում
Մենք կարող ենք բաց թողնել հաջորդականության համարի մասը՝ ժամանակի վրա հիմնված հարցման համար, և տրամադրել միայն ժամանակի ցուցիչները՝ սկզբնական և վերջնական ժամանակները նշելու համար: Երբ մենք բաց ենք թողնում համարակալված մասը, սկզբնական հաջորդականության հերթական համարն ավտոմատ սահմանվում է 0, իսկ վերջնականինը՝ առավելագույն հասանելի հաջորդականության համարը:
> XRANGE profile-information 1627796743670 1627799297560
Մենք կարող ենք COUNT հրաման նշել հարցման վերջում: Այդ կերպ մենք կստանանք միջակայքում ներառված առաջին N օբյեկտները:
> XRANGE profile-information - + COUNT 2
XREVRANGE-ն աշխատում է նույն կերպ, ինչպես XRANGE-ը, պարզապես հակառակ հերթակարգով:
> XREVRANGE profile-information + - COUNT 2
Ֆունկցիան կվերադարձնի դիապազոնում գտնված վերջին N էլեմենտները:
Նոր էլեմենտների ստացումը XREAD-ի միջոցով
Մենք կարող ենք բաժանորդագրվել նոր ստեղծվող էլեմենտների համար, որոնք կուղղվեն դեպի հոսք: Այս կոնցեպտը նման է Pub/Sub-ի աշխատանքի սկզբունքին, բայց այստեղ կա նշանակալի տարբերություններ:
Հիմնական նմանությունը նրանում է, որ հոսքին կարող է ունենալ մի քանի օգտագործող, և նոր ստեղծված ամեն մի էլեմենտ կառաքվի դրանցից յուրաքանչյուր հաղորդագրություն սպասողին: Սա որոշակիորեն նման է նաև ճյուղավորման տեխնոլոգիային, որպիսին և հանդիսանում է Pub/Sub-ը:
Իսկ հիմնական տարբերությունն էլ կայանում է նրանում, որ ի տարբերություն Pub/Sub-ի, որն աշխատում է Click-and-forget(սղմեց և մոռացավ) սկզբունքով, այն է, հաղորդագրությունների ճյուղավորումից հետո դրանք ջնջվում են Redis-ից, հոսքերի դեպքում ամեն ինչ այլ է: Նրանք պահպանում են հաղորդագրությունը՝ համապատասխան իդենտիֆիկատորի հետ միասին: Բացի հոսքերի ապահովումից, օգտագործողների խմբերը վերահսկողության այնպիսի մակարդակ են տրամադրում, որը հասանելի չէ Pub/Sub-ի կամ արգելափակման ցուցակների(lock lists) դեպքում:
XREAD -ը հոսք մտնող նոր հաղորդագրությունները լսելու հրամանն է:
> XREAD COUNT 1 STREAMS profile-information 0
- COUNT-ը ոչ պարտադիր հրաման է՝ ելքային գրառումները սահմանափակելու համար: COUNT-ից հետո արժեքը ցույց է տալիս, թե քանի գրառում ենք ուզում կարդալ հոսքից:
- STREAMS – պարտադիր նշում, որից հետո ցույց ենք տալիս հոսքի բանալի անունը:
- Վերջին արժեքը (0) – հանդիսանում է իդենտիֆիկատոր: Այն ցույց է տալիս այն իդենտիֆկատորի համարը, որը ենթադրվում է որ արդեն իսկ պահպանված է հոսքի մեջ, և ակնկալվում է ստանալ դրան հաջորդող՝ նոր ստեղծվող գրառումները: Քանի որ մենք արդեն իսկ գիտենք, որ ավտոմատ գեներացված իդենտիֆիկատորները մոնոտոն աճում են, ուստի նոր իդենտիֆիկատորները կլինեն ավելի մեծ, քան մեր նշված արժեքն է: Մեր դեպքում 0-ն նշանակում է, որ մենք ցանկանում ենք, որ հոսքի սկզբնական հաղորդագրությունն ունենա 0-0-ից մեծ իդենտիֆիկատոր:
Մենք հեշտությամբ կարող ենք վերածել XREAD-ը բլոկավորող հրամանի:
> XREAD BLOCK 0 STREAMS profile-information $
BLOCK
հրամանը 0 թայմաութի արժեքով նշանակում է, որ այս հրամանը կստուգի թե հնարավոր է արդյո՞ք անհապաղ մշակել հարցումը: Եթե այն կարողանա մշակել հարցումը՝ կկատարի մշակումը, հակառակ պարագայում հարցումը կարգելափակվի՝ մինչ տվյալների մուտքը:$
– սա հատուկ ID է, որը ներկայացնում է հոսքերում արդեն իսկ պահված առավելագույն ID-ն, այնպես որ մենք կստանանք միայն նոր հաղորդագրություններ:- Մենք նաև նշել ենք
COUNT
կարգավորումը, որպեսզի սահմանափակենք ելքային արժեքները: Իրականում,XREAD
-ին ունի ընդամենը երկու կարգավորման հնարավորություն՝ դրանքBLOCK
-ն ուCOUNT
-ն են:
Սպառողների խմբեր
Մենք հասնում ենք հոդվածի ամենահետաքրքիր մասին. XREAD
-ն առաջարկում է ճյուղավորման տեխնոլոգիայի առավելությունները: Հիմա անդրադառնանք մեկ այլ դեպքի. Ենթադրենք, մենք ունենք բազմաթիվ սպառողներ և ցանկանում ենք նրանց միջև տարածել հաղորդագրությունների ենթախումբ: Մենք նույն հաղորդագրությունը չենք փոխանցի տարբեր սպառողներին։ Ենթադրենք, մենք ունենք երկու սպառող՝ C1 և C2 և 7 հաղորդագրություն, որոնց ID-ներն են 1, 2, 3, 4, 5, 6, 7: Մենք ցանկանում ենք այս հաղորդագրությունները բաշխել C1 և C2 միջև հետևյալ կերպ.
1 -> C1
2 -> C2
3 -> C1
4 -> C2
5 -> C1
6 -> C2
7 -> C1
Հավանաբար դուք նկատեցիք, որ մենք ոչ թե միևնույն հաղորդագրությունն ուղարկում եք բոլոր սպառողներին, այլ տարբեր հաղորդագրություններ ուղարկվում են տարբեր սպառողների: Այս դեպքում մեզ օգնում են սպառողների խմբերը։
Սպառողների խմբի ստեղծումը
Ենթադրենք, մենք արդեն իսկ ունենք
բանալի անունով հոսք: Այս դեպքում հետևյալ հրամանը կստեղծի սպառողների խումբ.
> XGROUP CREATE profile-information mygroup $
- Մենք արդեն գիտեք, որ
$
-ը հատուկ իդենտիֆիկատոր է, որը ներկայացնում է հոսքերում հասանելի վերջին առավելագույն ID-ն: Սպառողների խումբը պետք է իմանա, թե որտեղից սկսած պետք է հետևի իր սպառողի հաղորդագրություններին:$
փոխանցելով միայն այս խմբի ստեղծումից հետո նոր հաղորդագրությունները կհետևվեն: Եթե $
-ի փոխարեն փոխանցենք 0, ապա այս խումբը կօգտագործի բոլոր հաղորդագրությունները հոսքի սկզբից: Մենք կարող ենք տրամադրել ցանկացած վավեր իդենտիֆիկատոր, որը ցույց է տալիս մեկնարկային կետը, որտեղից խումբը կստանա հաղորդագրությունը: mygroup
– խմբի անվանումը:profile-information
– գոյություն ունեցող հոսքի բանալի անունը:- Եթե հոսքը գոյություն չունի,
XGROUP
-ը կօգնի ստեղծել այն՝ փոխանցելով ենթահրաման վերջինMKSTREAM
-ին:
> XGROUP CREATE newstream mygroup $ MKSTREAM
Խմբից սպառման գործընթացը
Redis-ը տրամադրում է գրեթե նմանատիպ հրաման, որը կոչվում է XREADGROUP
՝ BLOCK
կարգավորիչով (այս դիրեկտիվի բացակայությունը հրամանը կդարձնի ասինխրոն): Առկա է նաև GROUP
կարգավորիչը՝ երկու արգումենտով. սպառողների խմբի անունը և այն սպառողի անունը, որը փորձում է կարդալ տեղեկատվությունը:
> XREADGROUP BLOCK 0 GROUP mygroup John COUNT 1 STREAMS profile-information >
- Հրամանը հիմնականում նկարագրական է: Այն ասում է, որ անհրաժեշտ է “John” անունով օգտագործողի անունից կարդալ տվյալները
profile information
հոսքից՝ օգտագործելովmygroup
սպառողների խումբը: Յուրաքանչյուր սպառող պետք է նշի իր անունը, որը կծառայի որպես խմբի ներսում նրա տարբերիչ իդենտիֆիկատոր: & gt;
-ը ևս մեկ հատուկ իդենտիֆիկատոր, որն աշխատում է միայն սպառողների խմբերի համատեքստում: Դա նշանակում է, որ տվյալ պահին հաղորդագրությունները դեռևս չեն հասցվել այլ սպառողների:
Առաջիկայում մենք կշարունակենք Redis-ի հոսքերի ներածությունը՝ երկրորդ մասով, որտեղ կդիտարկենք ձախողված գործողությունների վերականգնումը, ավտոմատ հարցումները, հարցումների և առաքումների հաշվիչները, ռեպլիկացիայի և անվտանգությանը վերաբերող հարցեր:
Սկզբնաղբյուր՝ Introduction to Redis Streams