Colloquio di system design: Progetta Uber
"Progetta Uber" è una delle richieste di system design più comuni perché tocca indicizzazione geospaziale, streaming della posizione in tempo reale, matching e throughput di scrittura elevato, tutto insieme. L'intervistatore non sta cercando la vera architettura di Uber — vuole vederti definire l'ambito del problema, fare scelte difendibili e ragionare ad alta voce sulla scala.
Affrontalo con un ordine deliberato: chiarisci i requisiti, stima la scala, abbozza le entità e le API principali, progetta i dati e il percorso di matching, poi discuti i colli di bottiglia e i trade-off. La guida qui sotto segue questo ordine così puoi allenare la struttura, non solo la risposta.
1. Chiarire i requisiti
Separa il funzionale dal non funzionale e fissa l'ambito prima di progettare. I passeggeri richiedono una corsa e vedono il conducente avvicinarsi in tempo reale; i conducenti si collegano e ricevono richieste vicine; il sistema li accoppia e segue la corsa fino al completamento.
- Funzionale: richiedere una corsa, abbinare a un conducente vicino, seguire la corsa in diretta, calcolo della tariffa, storico delle corse.
- Non funzionale: matching a bassa latenza (secondi), alta disponibilità, aggiornamenti di posizione in tempo reale, coerenza — un conducente assegnato a esattamente un passeggero.
- Fuori ambito (dillo esplicitamente): i dettagli interni dell'elaborazione dei pagamenti, le valutazioni, il ML per le tariffe dinamiche — menzionali e poi rinviali.
2. Stimare la scala
Numeri approssimativi giustificano le scelte successive. Supponi ~10 milioni di conducenti attivi al giorno che inviano un ping di posizione ogni 4 secondi — sono ~2,5 milioni di scritture al secondo di dati di posizione, un carico dominato dalla scrittura che esclude immediatamente una semplice tabella relazionale come percorso critico.
3. Componenti principali e API
Abbozza i servizi e il flusso delle richieste. Mantieni il percorso di matching indipendente dall'archivio durevole delle corse, così ciascuno può scalare secondo le proprie caratteristiche.
- Servizio di posizione: riceve i ping dei conducenti e mantiene le posizioni attuali in un indice geospaziale in memoria.
- Servizio di matching: alla richiesta di una corsa, interroga i conducenti online nelle vicinanze e ne assegna uno.
- Servizio corse: registro durevole del ciclo di vita della corsa (richiesta → abbinata → in corso → completata).
- Notifiche/streaming: invia la posizione del conducente in diretta al passeggero (WebSocket/long-poll).
4. Matching geospaziale — il cuore del problema
È questo che l'intervistatore vuole sentire più di tutto. Memorizzare lat/long grezzi e scansionarli è O(n); serve un indice spaziale. Spiega i quadtree o il geohashing: dividere la mappa in celle in modo che 'trova i conducenti vicini a questo punto' diventi una ricerca in poche celle, non una scansione completa.
Il geohashing codifica una regione in una stringa breve dove prefissi condivisi indicano vicinanza spaziale, trasformando 'vicino' in una query per prefisso. Le celle attuali dei conducenti vivono in un archivio in memoria (ad es. Redis) per letture rapide e aggiornamenti frequenti; la granularità delle celle è un trade-off regolabile tra precisione e fan-out delle query.
5. Scalabilità e colli di bottiglia
Indica i punti critici e come li allevieresti. Il flusso di 2,5 milioni di scritture di posizione al secondo è quello dominante.
- Partiziona (shard) l'indice di posizione geograficamente — i conducenti e i passeggeri di una città sono gestiti dallo stesso shard, mantenendo il matching locale.
- Assorbi il picco di scrittura con un archivio in memoria e scritture durevoli asincrone; non serve che ogni ping arrivi a un database durevole.
- Garantisci un conducente per passeggero con un'assegnazione atomica (un lock o un aggiornamento condizionale) per evitare doppie prenotazioni.
- Usa una coda di messaggi (Kafka) tra l'ingestione della posizione e i consumer a valle per disaccoppiare i picchi.
6. Trade-off da esprimere a voce
Chiudi nominando le tensioni che un intervistatore apprezza: coerenza forte contro eventuale (l'assegnazione del conducente deve essere forte; la visualizzazione della posizione può essere eventuale), velocità in memoria contro durabilità, e precisione della dimensione delle celle contro fan-out delle query. Dichiararle esplicitamente è la differenza tra una risposta che passa e una risposta solida.
Allenati nel system design di Uber con aiuto in tempo reale
L'assistente per colloqui di system design di Natively può mantenerti strutturato durante un colloquio dal vivo — suggerendo la prossima dimensione da trattare e mostrando i trade-off in tempo reale, tutto sul tuo stesso dispositivo.
