Dobrodošli u četvrti deo serijala na ITNetwork.rs! Do sada smo prošli kroz monolit i mikroservise, frontend arhitekturu (SPA, SSR, SSG) i backend API-je (REST, GraphQL, gRPC). Danas ulazimo u srce svake aplikacije – baze podataka. Razjasnićemo: kada koristiti relacione, a kada NoSQL baze, šta je polyglot persistence, i kako primeniti napredne obrasce poput CQRS i Event Sourcing.
Zašto je izbor baze ključan?
Baza podataka nije samo „skladište“. Ona utiče na:
- Performanse (latencija upita)
- Skalabilnost (horizontalno/vertikalno)
- Konzistentnost podataka
- Troškove (cloud, licence)
- Brzinu razvoja
Pogrešna baza = tehnički dug za godine.
1. Relacione baze (RDBMS)
Definicija
Podaci u tabelama, sa stranim ključevima, transakcijama (ACID) i SQL jezikom.
Popularni alati
| Baza | Karakteristike |
|---|---|
| PostgreSQL | Open-source, JSONB, ekstenzije |
| MySQL | Brza, široko korišćena |
| MariaDB | Fork MySQL-a |
| PlanetScale | MySQL u cloud-u, serverless |
| CockroachDB | Distribuirana, skalabilna |
| + | Objašnjenje |
|---|---|
| ACID garancije | Transakcije su sigurne |
| Jasna šema | Lako modelovanje domena |
| SQL standard | Prenosivost, alati |
| JOIN-ovi | Kompleksni upiti |
| – | Objašnjenje |
|---|---|
| Teško horizontalno skaliranje | Sharding je bolan |
| Krute šeme | Migracije = downtime |
| Spori za velike podatke | Nema ugrađenog full-text pretrage |
- Finansije, računovodstvo
- ERP, CRM
- Kada su relacije između entiteta ključne
2. NoSQL baze
Definicija
„Not Only SQL“ – fleksibilni modeli, bez šeme, skalabilni.
| Tip | Primeri | Upotreba |
|---|---|---|
| Dokument | MongoDB, CouchDB | JSON-like podaci |
| Ključ-vrednost | Redis, DynamoDB | Keš, sesije |
| Kolonske | Cassandra, ClickHouse | Analitika |
| Graf | Neo4j | Društvene mreže, preporuke |
| + | Objašnjenje |
|---|---|
| Fleksibilna šema | Dodaj polje bez migracije |
| Horizontalno skaliranje | Dodaj nod → više throughput |
| Brzina za specifične upite | Redis: <1ms |
| – | Objašnjenje |
|---|---|
| Eventual consistency | Nema ACID po defaultu |
| Kompleksni upiti teži | Nema JOIN-ova |
| Dupliranje podataka | Denormalizacija |
- Logovi, IoT podaci
- Keš, sesije
- Katalog proizvoda (fleksibilna polja)
3. Polyglot Persistence – više baza u jednom sistemu
Definicija
Primer: E-commerce platforma
| Podaci | Baza | Zašto |
|---|---|---|
| Korisnici, narudžbine | PostgreSQL | Transakcije, relacije |
| Pretraga proizvoda | Elasticsearch | Full-text, faceted search |
| Sesije, keš | Redis | Brz pristup |
| Logovi događaja | Kafka → ClickHouse | Analitika |
4. CQRS (Command Query Responsibility Segregation)
Definicija
Odvoji pisanje od čitanja:
- Command → CreateOrder, UpdateUser
- Query → GetUserOrders, SearchProducts
Zašto?
- Različiti modeli za čitanje i pisanje
- Optimizacija po upotrebi
- Lakše skaliranje
Primer: CQRS sa Node.js
// command: create-order.ts
class CreateOrderCommand {
constructor(public userId: number, public items: any[]) {}
}
// Handler
class CreateOrderHandler {
async handle(cmd: CreateOrderCommand) {
// 1. Validacija
// 2. Transakcija u PostgreSQL
// 3. Emituj događaj: OrderCreated
await eventBus.publish(new OrderCreatedEvent(cmd));
}
}
// query: get-user-orders.ts
class GetUserOrdersQuery {
constructor(public userId: number) {}
}
class GetUserOrdersHandler {
async handle(query: GetUserOrdersQuery) {
// Čitaj iz denormalizovane tabele ili Redis-a
return await readDB.getOrders(query.userId);
}
}
Definicija
Ne čuvaj trenutno stanje – čuvaj događaje koji su ga stvorili.
OrderCreated → ItemAdded → OrderShipped → OrderDelivered
| + | Objašnjenje |
|---|---|
| Potpuna revizija | „Šta se desilo i kada?“ |
| Fleksibilnost | Rekonstruiši stanje kako hoćeš |
| Debugovanje | Replay događaja |
| – | Objašnjenje |
|---|---|
| Kompleksnost | Potreban event store |
| Eventual consistency | Stanje se gradi asinhrono |
- EventStoreDB
- Kafka + Schema Registry
- Axon Framework (Java), EventFlow (.NET)
Praktičan primer: TODO aplikacija sa polyglot persistence
Arhitektura
1. Kreiraj TODO (Command)
// command
await db.transaction(async (trx) => {
await trx('todos').insert({ title, user_id });
await kafka.send('todo-events', {
type: 'TodoCreated',
payload: { id, title, user_id }
});
});
2. Projekcija za čitanje
// Kafka consumer
consumer.on('todo-events', async (event) => {
if (event.type === 'TodoCreated') {
await mongo.collection('todos_view').insertOne(event.payload);
await elasticsearch.index({
index: 'todos',
id: event.payload.id,
body: { title: event.payload.title }
});
}
});
3. Brzo čitanje
// Query
const todos = await mongo.collection('todos_view').find({ user_id }).toArray();
| Kriterijum | RDBMS | NoSQL | Polyglot |
|---|---|---|---|
| Konsistentnost | ★★★★★ | ★★ | ★★★★ |
| Skalabilnost | ★★ | ★★★★★ | ★★★★★ |
| Fleksibilnost | ★★ | ★★★★★ | ★★★★★ |
| Kompleksnost | ★★ | ★★★ | ★★ |
| Tim znanje | ★★★★★ | ★★★ | ★★ |
| Tip aplikacije | Preporuka |
|---|---|
| Bankarstvo, fakture | PostgreSQL |
| Blog, keš, sesije | Redis + PostgreSQL |
| Pretraga, logovi | Elasticsearch + ClickHouse |
| Veliki mikroservisni sistem | Polyglot + CQRS |
| MVP, brzina | PostgreSQL ili MongoDB |
Zlatno pravilo: Počni sa jednom bazom. Dodaj drugu kada osetiš bol.
Šta dalje?
U petom delu ulazimo u mikroservisnu arhitekturu:
- Granice servisa (DDD)
- Komunikacija (sync vs async)
- Service Discovery, Circuit Breaker
Tvoj izazov
- Napravi dva servisa:
- user-service → PostgreSQL
- search-service → Elasticsearch
- Kada se kreira korisnik → pošalji događaj → indeksiraj u Elasticsearch
- Komentariši ispod: „Koliko baza koristiš u svom trenutnom projektu?“
Autor: Dušan Antonijević – saradnik ITNetwork.rs
Hvala na čitanju! Podeli tekst sa kolegama.



