Sobes.tech

Golang

Ispričajte nam o najtežem i najzanimljivijem zadatku koji ste riješili, posebno o arhitektonskom iskustvu.

225

Можете ли да наведете свој тренутни ниво прихода?

Junior — Middle
223

Da li trenutno živite u Moskvi? Koji grad razmatrate? Razmišljate li o hibridnom formatu rada? Na kojoj ste fazi traženja?

223

Da li imate druge aktivne procese intervjua?

222

Kako se ove metrike integrišu i prikazuju u Grafani?

Junior — Middle
221

Dizajn skalabilnog sistema za razmenu poruka koji podržava 150 miliona korisnika, 75 miliona DAU, 225 miliona MAU, 1.2 miliona čitanja / 300k pisanja QPS, 5 miliona istovremenih korisnika, 60 PB novih podataka godišnje, rast od 30% godišnje, P99 <200 ms za čitanje, <300 ms za pisanje, SLA 99,95%. KONTEKST Potrebno je dizajnirati distribuirani sistem za razmenu poruka, sličan WhatsApp-u, koji podržava 1:1 i grupne chatove, obezbeđuje dostavu poruka, prikazuje online statuse korisnika i prenosi multimedijalne fajlove (fotografije, video, audio). Sistem mora obezbediti visoku dostupnost i nisku latenciju, podržavati visok paralelizam i skalirati na globalnom nivou. FUNKCIONALNI ZAHTEVI - Podrška za lične (1:1) i grupne chatove sa mogućnošću dodavanja/uklanjanja učesnika - Slanje i primanje tekstualnih poruka i multimedijalnih fajlova Nefunkcionalni zahtevi: - Nema eksplicitne implementacije end-to-end enkripcije na nivou servisa ili klijenata, osim opšte napomene. - Nema jasnog opisa sharding-a i replikacije baza podataka po chat_id ili user_id radi skalabilnosti i otpornosti na greške. - Nema eksplicitnog komponenta ili mehanizma za offline sinhronizaciju poruka i potvrda isporuke. - Nije jasno kako se vrši balansiranje opterećenja između baza podataka i servisa, posebno pri vršnim opterećenjima. **Ključne tačke na koje treba obratiti pažnju:** (Dijagram prikazuje arhitekturu sa Load Balancer-om, API Gateway-jem, Message Queue-om, Service-om, Cache-om, Database-om, Object Storage-om i CDN-om)

220

Koji je bio sastav tima sa kojim ste poslednji put radili?

Junior — Middle
219

Da li imaš aktivni GitHub ili LinkedIn?

218

Ispričaj ukratko čime si se bavio na prethodnim radnim mestima i koje funkcije si implementirao.

214

Kako su organizovani testovi u timu — ko šta piše, kakvo pokriće, postoji li E2E?

213

/* Moramo preneti podatke iz izvora do potrošača. Izvor pruža podatke u malim paketima (~deset zapisa), dok potrošač efikasnije radi sa većim paketima (~hiljadu zapisa). Pravi primer je prenos podataka iz Kafka tipa redova u bazu podataka Clickhouse. Izvor: - Praktično beskonačan. - Izvor nikada ne vraća više od MaxItems zapisa u jednom Next pozivu. - U okviru jedne "sesije" (jedan poziv funkcije Pipe), izvor u svakom Next pozivu vraća nove podatke. - Međutim, nakon restartovanja, izvor počinje od prethodne "potvrđene" pozicije, označene cookie-jem. Zato, svaka vrednost cookie-a koju Next vrati, nakon što se podaci sačuvaju u primaocu, mora biti potvrđena pozivom na Commit, u istom redosledu u kojem su vraćeni od strane Next. Primaoc: - Ne može obraditi više od MaxItems odjednom. Osnovni nivo: Potrebno je implementirati funkciju func Pipe(p Producer, c Consumer) error koja čita podatke iz izvora, grupiše ih u bafer veličine ne većoj od MaxItems i čuva u primaocu, nakon čega potvrđuje napredak u izvoru. Dodatna složenost: Metode Next, Process i Commit povezane su sa mrežnim pozivima i mogu trajati dosta dugo. Za ubrzanje procesa, potrebno je paralelizovati procese čitanja, zapisivanja i potvrđivanja napretka. Tako da, tokom Process ili Commit, čitanje iz izvora i formiranje novog bafera nastave. */ const MaxItems = 9999 type Producer interface { // Next vraća: // - paket stavki za obradu // - cookie za potvrdu kada je obrada završena // - grešku Next() (items []any, cookie int, err error) // Commit se koristi za označavanje paketa podataka kao obrađenih Commit(cookie int) error } type Consumer interface { Process(items []any) error } func Pipe(p Producer, c Consumer) error { // TODO }

213

Kako povećati efikasnost pretraživanja elemenata u strukturi podataka Map?

Junior — Middle
212

Dizajn skalabilnog sistema za razmenu poruka koji podržava 150 miliona korisnika, 75 miliona DAU, 225 miliona MAU, 1.2M peak QPS za čitanje / 300k za pisanje, 5 miliona istovremenih korisnika, 60 PB novih podataka godišnje, rast od 30% godišnje, SLA 99.95%, p99 <200 ms za čitanje, <300 ms za pisanje. KONTEKST Potrebno je dizajnirati distribuirani sistem za razmenu poruka, sličan WhatsApp-u, koji podržava 1:1 i grupne razgovore, obezbeđuje dostavu poruka, prikazuje online statuse korisnika i omogućava prenos multimedijalnih fajlova (fotografije, video, audio). Sistem mora obezbediti visoku dostupnost i nisku latenciju, podržavati visok paralelizam i skalirati na globalnom nivou. FUNKCIONALNI ZAHTEVI - Podrška za lične (1:1) i grupne razgovore sa mogućnošću dodavanja/uklanjanja učesnika - Slanje i primanje tekstualnih poruka i multimedijalnih fajlova Nije jasno implementiran mehanizam end-to-end enkripcije na nivou servisa ili klijenata, osim opšte napomene. - Nedostaje eksplicitni opis sharding-a i replikacije baza podataka po chat_id ili user_id radi skalabilnosti i otpornosti na greške. - Nema jasnog komponenta ili mehanizma za offline sinhronizaciju poruka i potvrda isporuke. - Nije jasno kako se vrši balansiranje opterećenja između baza podataka i servisa, posebno u vršnim periodima. **Kritične tačke za razmatranje:**

211

/* PostgreSQL-ova dva servera: * PROD - OLTP server, * STATS - server za duge analitičke upite. Na trenutnom serveru, u bazi podataka prod, postoji velika tabela (10Tb) sa sledećom strukturom: CREATE TABLE profiles( id SERIAL, data JSONB ) U tabeli mogu biti "rupe", tj. neki `id` mogu biti izostavljeni. Potrebno je napisati program za kopiranje tabele profiles sa PROD na STATS. Pretpostavlja se da će se koristiti sledeći interfejsi za rad sa bazama podataka: type Row []interface{} type Database interface { // implementacija interfejsa Database može ponovo uspostaviti konekcije // poziv SaveRows je idempotentan 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 // Ako je full=false, nastaviti prenos podataka od mesta prethodne greške // Ako je full=true, preneti sve podatke func CopyTable(fromName string, toName string, full bool) error { // ... vaš kod } Ako je prosleđena opcija `full=false`, program treba da nastavi prenos podataka od mesta prethodne greške. Ako je `full=true`, treba da prenese sve podatke. **Osnovni nivo**: - sekvencijalni prenos podataka u jednom toku - oporavak nakon greške (opcija `full=false`) Dodatne informacije: - ako je potrebno, možete proširiti interfejs dodavanjem sopstvenih metoda - ako je potrebno, možete direktno koristiti paket **database/sql**

211

/* Dano je niz karaktera. Pronađite broj parova indeksa i i j (i <= j), između kojih nema ponovljenih karaktera. Za niz "aba" odgovor je 5: mogu biti ne samo ASCII [0, 0] ("a") [0, 1] ("ab") [1, 1] ("b") [1, 2] ("ba") [2, 2] ("a") */

211

Дат је низ карактера. Пронађите број парова индекса i и j (i <= j), између којих, укључујући, нема понављајућих карактера. За низ "aba" одговор је 5: [0, 0] ("a") [0, 1] ("ab") [1, 1] ("b") [1, 2] ("ba") [2, 2] ("a") За низ "abcb" одговор је ?: aba 3 + 2 = 5 abcb 4 (a, b, c, d) + 1 (ab) + 1 (bc) + 1 (cb) + 1 (abc) = 8

209

/* Postoji aplikacija s arhitekturom mikroservisa. Mikroservis se može apstrahirati pomoću sučelja Backend. Za pristup primjerku mikroservisa, možete koristiti tip BackendImpl, koji je već implementiran. Svaki mikroservis ima nekoliko desetaka pokrenutih primjeraka, od kojih je svaki dostupan putem svoje adrese addr. Međutim, pojedinačni primjerci mikroservisa nisu pouzdani: the mogu pasti, biti nedostupni ili preopterećeni. Stoga morate implementirati tip Balancer, koji također implementira sučelje Backend i vrši balansiranje opterećenja na strani klijenta između primjeraka mikroservisa, birajući svaki put **najmanje opterećen** primjerak. */ type Request interface{} type Response interface{} type Backend interface { Invoke(ctx context.Context, req Request) (Response, error) } var _ Backend = &BackendImpl{} // addr sadrži ip:port određenog primjerka func NewBackend(addr string) *BackendImpl type Balancer struct { // TODO } var _ Backend = &Balancer{} // addrs sadrže adrese svih uravnoteženih primjeraka func NewBalancer(addrs []string) *Balancer { // TODO }

209

Kako funkcioniše WebSocket veza u arhitekturi — u kom trenutku se uspostavlja i ko sa kim komunicira?

209

Да ли имате искуство са распоређеним системима?

209

Koji je problem sa trenutnom implementacijom ažuriranja mape u radniku (tasksRes[t.id][task{...}])?

209
/11