Home SOFTWAREArhitektura modernih web aplikacija – Deo 4: Baze podataka u modernim aplikacijama

Arhitektura modernih web aplikacija – Deo 4: Baze podataka u modernim aplikacijama

od itn
Arhitektura

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
Prednosti
+ Objašnjenje
ACID garancije Transakcije su sigurne
Jasna šema Lako modelovanje domena
SQL standard Prenosivost, alati
JOIN-ovi Kompleksni upiti
Mane
Objašnjenje
Teško horizontalno skaliranje Sharding je bolan
Krute šeme Migracije = downtime
Spori za velike podatke Nema ugrađenog full-text pretrage
Kada koristiti?
  • 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
Prednosti
+ Objašnjenje
Fleksibilna šema Dodaj polje bez migracije
Horizontalno skaliranje Dodaj nod → više throughput
Brzina za specifične upite Redis: <1ms
Mane
Objašnjenje
Eventual consistency Nema ACID po defaultu
Kompleksni upiti teži Nema JOIN-ova
Dupliranje podataka Denormalizacija
Kada koristiti?
  • Logovi, IoT podaci
  • Keš, sesije
  • Katalog proizvoda (fleksibilna polja)

3. Polyglot Persistence – više baza u jednom sistemu

Definicija

PolyglotPrimer: 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);
  }
}
5. Event Sourcing – podaci kao niz događaja

Definicija

Ne čuvaj trenutno stanje – čuvaj događaje koji su ga stvorili.

OrderCreated → ItemAdded → OrderShipped → OrderDelivered
Prednosti
+ Objašnjenje
Potpuna revizija „Šta se desilo i kada?“
Fleksibilnost Rekonstruiši stanje kako hoćeš
Debugovanje Replay događaja
Mane
Objašnjenje
Kompleksnost Potreban event store
Eventual consistency Stanje se gradi asinhrono
Alati
  • EventStoreDB
  • Kafka + Schema Registry
  • Axon Framework (Java), EventFlow (.NET)

Praktičan primer: TODO aplikacija sa polyglot persistence

Arhitektura

TODO1. 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();
Poređenje: RDBMS vs NoSQL vs Polyglot
Kriterijum RDBMS NoSQL Polyglot
Konsistentnost ★★★★★ ★★ ★★★★
Skalabilnost ★★ ★★★★★ ★★★★★
Fleksibilnost ★★ ★★★★★ ★★★★★
Kompleksnost ★★ ★★★ ★★
Tim znanje ★★★★★ ★★★ ★★
Zaključak: Koju bazu izabrati?
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

  1. Napravi dva servisa:
    • user-service → PostgreSQL
    • search-service → Elasticsearch
  2. Kada se kreira korisnik → pošalji događaj → indeksiraj u Elasticsearch
  3. Komentariši ispod: „Koliko baza koristiš u svom trenutnom projektu?“

Autor: Dušan Antonijević – saradnik ITNetwork.rs
Hvala na čitanju! Podeli tekst sa kolegama.

Banner

Banner

Možda će vam se svideti i