/* PostgreSQL- ի երկու սերվերներ կան: * PROD - OLTP սերվեր, * STATS - երկարատև վերլուծական հարցերի սերվեր: Ընթացիկ սերվերում, prod տվյալների բազայում, կա մեծ (10Tb) աղյուսակ հետևյալ կառուցվածքով: CREATE TABLE profiles( id SERIAL, data JSONB ) Աղյուսակում կարող են լինել "հորատներ", այսինքն, որոշ `id`-ներ կարող են բաց թողնվել: Պետք է գրել ծրագիր, որը կկոպիրացնի profiles աղյուսակը PROD-ից STATS: Նախատեսվում է, որ օգտագործվելու են հետևյալ ինտերֆեյսները տվյալների բազաներով աշխատելու համար: type Row []interface{} type Database interface { // իրականացմանը կարող է վերականգնել կապերը // SaveRows կանչը էնդպոտենտ է io.Closer GetMaxID(ctx context.Context) (uint64, error) LoadRows(ctx context.Context, minID, maxID uint64) ([]Row, error) // [minID, maxID] SaveRows(ctx context.Context, rows []Row) error } func Connect(ctx context.Context, dbname string) (Database, error) // CopyTable // Եթե full=false, ապա շարունակել տվյալների փոխանցումը նախորդ սխալի վայրից // Եթե full=true, փոխանցել բոլոր տվյալները func CopyTable(fromName string, toName string, full bool) error { // ... ձեր կոդը } Եթե փոխանցվում է `full=false` տարբերակը, ապա ծրագրը պետք է շարունակել տվյալների փոխանցումը նախորդ սխալի վայրից: Եթե `full=true`, ապա պետք է փոխանցի բոլոր տվյալները: **Հիմնական մակարդակ**: - տվյալների սերիական փոխանցում մեկ հոսքով - սխալներից հետո վերականգնում (ընտրանք `full=false`) Ավելին՝ - եթե անհրաժեշտ է, կարող եք ընդլայնել ինտերֆեյսը՝ ավելացնելով ձեր մեթոդները - եթե անհրաժեշտ է, կարող եք ուղղակիորեն օգտագործել **database/sql** փաթեթը
Golang
Կարճ ասեք, ինչ եք զբաղվել նախորդ աշխատանքային վայրերում և ինչ ֆունկցիաներ եք իրականացրել։
Ինչպե՞ս եք կատարել կատարված հարցումների ճշգրտության թեստավորումը և վավերացումը։
Կա՞ որոշակի ժամկետ։
Պատմիր տվյալների բազաների մասին — ինչի հետ էիր աշխատել և հիմա ինչի հետ աշխատում ես?
Ինչն է տարբերությունը local, dev, stage, prod միջավայրերի միջև։
/* Տրված է նիշերի շղթա: գտնել i և j ցուցանիշների զույգերի քանակը (i <= j), որոնց միջև կրկնվող նիշեր չկան: "aba" շղթայի համար պատասխանն է 5: կարող է լինել ոչ միայն ASCII [0, 0] ("a") [0, 1] ("ab") [1, 1] ("b") [1, 2] ("ba") [2, 2] ("a") */
/* Մեզ անհրաժեշտ է տվյալներ փոխանցել որոշ աղբյուրից որոշ սպառողի: Աղբյուրը տվյալները տալիս է փոքր խմբաքանակներով (~տասը գրառում), մինչդեռ սպառողը ավելի արդյունավետ է աշխատում մեծ խմբաքանակներով (~հազար գրառում): Իրական օրինակ է Kafka տիպի հերթերից տվյալների փոխանցումը Clickhouse տվյալաբազա: Աղբյուր: - Հասկանալիորեն անսահմանափակ: - Աղբյուրը երբեք չի վերադարձնի ավելի քան MaxItems գրանցում մեկ Next կանչում: - Մի «սեսիայում» (մեկ Pipe ֆունկցիայի կանչում) աղբյուրը յուրաքանչյուր Next կանչում նոր տվյալներ է վերադարձնում: - Սակայն, վերագործարկումից հետո, աղբյուրը սկսում է նախորդ «հաստատված» դիրքից, որը նշվում է cookie-ով: Այդ պատճառով, յուրաքանչյուր cookie արժեք, որը Next-ը վերադարձնում է, տվյալները պահելուց հետո, պետք է հաստատվի Commit կանչով, նույն հերթականությամբ, ինչպես դրանք վերադարձվել էին Next-ով: Սպառող: - Չի կարող միաժամանակ ավելի քան MaxItems մշակել: Հիմնական մակարդակ: Պետք է իրականացնել func Pipe(p Producer, c Consumer) error ֆունկցիան, որը կարդում է տվյալները աղբյուրից, խմբավորում դրանք ոչ մեծ, MaxItems-ից ոչ ավելի մեծ բուֆերներում և պահում է սպառողում, հետո հաստատում է առաջընթացը աղբյուրում: Ավելորդ բարդություն: Next, Process և Commit մեթոդները կապված են ցանցային կանչերի հետ և կարող են բավական երկար տևել: Արագացման համար անհրաժեշտ է հոսքերը հորիզոնականացնել՝ ընթերցում, գրառում և առաջընթացի հաստատում: Որպեսզի, Process կամ Commit կանչի ժամանակ, ընթերցումը աղբյուրից և նոր բուֆերի ձևավորումը շարունակվի: */ const MaxItems = 9999 type Producer interface { // Next վերադարձնում է: // - մի խմբաքանակ տարրեր՝ մշակման համար // - cookie՝ հաստատելու համար, երբ մշակումը ավարտվի // - սխալ Next() (items []any, cookie int, err error) // Commit օգտագործվում է նշելու տվյալների խմբաքանակը որպես մշակված Commit(cookie int) error } type Consumer interface { Process(items []any) error } func Pipe(p Producer, c Consumer) error { // TODO }
Ներկայացրեք կախվածությունների հակադարձման սկզբունքը և ինչու է ուղիղ կանչը ռեպոզիտորի մեթոդներին օգտագործման դեպքից խախտում SOLID-ը։
Ի՞նչ է ավելացվում պատասխանին, երբ պատուհանը դառնում է վավեր։
/* Միկրոսերվիսի ճարտարապետությամբ հավելված կա: Միկրոսերվիսը կարող է աբստրակտացվել Backend ինտերֆեյսի միջոցով: Միկրոսերվիսի օրինակին մուտք գործելու համար կարող եք օգտագործել BackendImpl տիպը, որը արդեն իրականացված է: Յուրաքանչյուր միկրոսերվիս ունի մի քանի տասնյակ գործարկվող օրինակներ, որոնցից յուրաքանչյուրը հասանելի է իր սեփական հասցեով addr: Այնուամենայնիվ, միկրոսերվիսի առանձին օրինակները չեն վստահելի: նրանք կարող են ընկնել, լինել անհասանելի կամ ծանրաբեռնված: Աստիճանաբար, դուք պետք է իրականացնել Balancer տիպը, որը նույնպես իրականացնում է Backend ինտերֆեյսը և իրականացնում է բեռի հավասարակշռություն հաճախորդի կողմից միկրոսերվիսի օրինակների միջև, ընտրելով ամեն անգամ **ամենափոքր բեռնված** օրինակ: */
Ինչպես է JWT-ն ստուգում իր իսկականությունը: Ինչպե՞ս է հաստատվում, որ տոքենը կեղծ չէ:
/* Կան mikroservis-ների ճարտարապետությամբ կիրառություն: Միկրոսերվիսը կարող է աբստրակտացվել Backend ինտերֆեյսի միջոցով: Դուք կարող եք օգտագործել արդեն իրականացված BackendImpl տիպը միկրոսերվիսի օրինակին մուտք գործելու համար: Յուրաքանչյուր միկրոսերվիս ունի մի քանի տասնյակ աշխատող օրինակներ, որոնք հասանելի են իրենց սեփական հասցեով addr: Բայց, միկրոսերվիսի առանձին օրինակները չեն հուսալի: նրանք կարող են ընկնել, լինել անհասանելի կամ ծանրաբեռնված: Աստիճանաբար, դուք պետք է իրականացնեք Balancer տիպը, որը նույնպես իրականացնում է Backend ինտերֆեյսը և կատարում է բեռի հավասարակշռություն հաճախորդի կողմից միկրոսերվիսի օրինակների միջև, ընտրելով ամենից քիչ բեռնված օրինակ: */ type Request interface{} type Response interface{} type Backend interface { Invoke(ctx context.Context, req Request) (Response, error) } var _ Backend = &BackendImpl{} // addr պարունակում է կոնկրետ օրինակակի ip:port հասցեն func NewBackend(addr string) *BackendImpl type Balancer struct { // TODO } var _ Backend = &Balancer{} // addrs պարունակում են բոլոր հավասարակշռված օրինակակների հասցեները func NewBalancer(addrs []string) *Balancer { // TODO }
Ի՞նչ է առավելագույն քանակը հարցումների/sec (RPS), որ ամենաբարձր ծանրաբեռնված ծառայությունը մշակել է:
Դու ունե՞ք թիմի կառավարում փորձառություն։
Ի՞նչ սահմանափակում ունի սեմաֆորը և բուֆերային ալիքը՝ որպես լուծումներ՝ հոսքերի սահմանափակման համար։
Ինչպե՞ս համեմատել տարրերը քարտեզում: Ինչպե՞ս ստուգել, որ երկու քարտեզները համընկնում են:
Գրեք խնդիր Go լեզվով — պրակտիկ բաժին (ծրագրավորողի կյանքի խնդիրներ, առանց ալգորիթմների): Ծախսը — 1,5 ժամ։
Ի՞նչ էր թիմի կազմը: Միայնակ գործառնական էր, թե բազմաֆունկցիոնալ?
Աշխատանքի ձևաչափը՝ հեռավար, գրասենյակում կամ հիբրիդ?