← Назад к вопросам

Какую БД выберешь при написании нового микросервиса?

2.0 Middle🔥 201 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Выбор базы данных для нового микросервиса

Мой подход к выбору БД

Выбор БД зависит от конкретного use case микросервиса. Я не делаю выбор заранее, а анализирую требования. Расскажу мой процесс принятия решения.

Матрица решений

Представлю как выбирать БД по типам данных:

ТИП ДАННЫХ И USE CASE → РЕКОМЕНДУЕМАЯ БД

1. Реляционные данные (users, orders, products)
   → PostgreSQL (мой первый выбор)
   Почему: ACID гарантии, JSON support, ecosystem

2. Высоконагруженные reads (кеш, сессии)
   → Redis
   Почему: In-memory, высокая скорость, TTL

3. Временные ряды (metrics, logs)
   → ClickHouse или TimescaleDB
   Почему: Оптимизировано для time-series

4. Полнотекстовый поиск (поиск по текстам)
   → Elasticsearch или OpenSearch
   Почему: Инвертированный индекс, быстрый поиск

5. Иерархические данные (меню, комментарии)
   → PostgreSQL (с рекурсивными CTE)
   Почему: Простота, транзакции

6. Графовые данные (рекомендации, социальные сети)
   → Neo4j
   Почему: Оптимизирована для связей

7. Неструктурированные данные (JSON, документы)
   → MongoDB
   Почему: Гибкая схема, масштабируемость

Вариант 1: PostgreSQL (мой первый выбор)

Для нового микросервиса я выбираю PostgreSQL как базу по умолчанию:

Преимущества:

  • ACID гарантии (важно для консистентности)
  • JSON/JSONB поддержка (гибкость схемы)
  • Отличный ecosystem
  • Full-text search встроен
  • Репликация и failover хорошие
  • Open source

Когда использовать:

@Entity
@Table(name = "orders")
public class Order {
    @Id
    private UUID id;
    
    @ManyToOne
    private User user;
    
    @OneToMany(mappedBy = "order")
    private List<OrderItem> items;
    
    @Type(JsonType.class)
    @Column(columnDefinition = "jsonb")
    private OrderMetadata metadata;  // Гибкие данные
}

Вариант 2: Redis (для кеша и сессий)

Добавляю Redis для:

  • Кеширования
  • Сессий пользователей
  • Rate limiting
  • Real-time data
@Service
public class UserCacheService {
    private final RedisTemplate<String, User> redisTemplate;
    private final UserRepository userRepository;
    
    public User getUserWithCache(String userId) {
        String cacheKey = "user:" + userId;
        
        // Пытаемся из кеша
        User cached = redisTemplate.opsForValue().get(cacheKey);
        if (cached != null) {
            return cached;
        }
        
        // Если нет - берем из БД
        User user = userRepository.findById(userId).orElseThrow();
        
        // Кешируем на час
        redisTemplate.opsForValue().set(
            cacheKey, user, Duration.ofHours(1)
        );
        
        return user;
    }
}

Вариант 3: ClickHouse (для аналитики и логов)

Если микросервис генерирует много логов или метрик:

# docker-compose.yml
version: '3'
services:
  clickhouse:
    image: clickhouse/clickhouse-server:latest
    ports:
      - "8123:8123"
    volumes:
      - clickhouse_data:/var/lib/clickhouse
@Service
public class EventLogService {
    private final ClickHouseClient client;
    
    public void logUserEvent(UserEvent event) {
        // ClickHouse оптимизирована для INSERT'ов миллионов строк
        client.execute(
            "INSERT INTO user_events (user_id, event_type, timestamp) "
            + "VALUES (?, ?, ?)",
            event.getUserId(), event.getType(), Instant.now()
        );
    }
}

Вариант 4: Elasticsearch (для поиска)

Если нужен полнотекстовый поиск:

@Service
public class ProductSearchService {
    private final ElasticsearchOperations elasticsearchOps;
    
    public List<Product> search(String query) {
        SearchHits<Product> results = elasticsearchOps.search(
            Query.findAll()
                .addFilter(QueryBuilders.matchQuery("name", query))
                .addFilter(QueryBuilders.termQuery("active", true)),
            Product.class
        );
        
        return results.getSearchHits()
            .stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());
    }
}

Вариант 5: MongoDB (для документов)

Если нужна максимальная гибкость схемы:

@Service
public class UserPreferencesService {
    private final MongoTemplate mongoTemplate;
    
    public void savePreferences(String userId, Map<String, Object> prefs) {
        // MongoDB хранит JSON документы как есть
        Document doc = new Document()
            .append("_id", userId)
            .append("preferences", prefs)
            .append("lastUpdated", new Date());
        
        mongoTemplate.save(doc, "user_preferences");
    }
}

Мой default stack для микросервиса

# Для каждого нового микросервиса я использую:

1. PostgreSQL
   - Основная БД для бизнес-данных
   - Транзакции и консистентность
   - Репликация для HA

2. Redis
   - Кеш (query cache, object cache)
   - Сессии пользователей
   - Очереди (для async задач)
   - Rate limiting

3. (Опционально) Elasticsearch
   - Если нужен full-text поиск
   - Синхронизация через Kafka/RabbitMQ

4. (Опционально) ClickHouse
   - Если генерируем 1M+ событий/день
   - Аналитика и отчеты

Процесс выбора БД

  1. Анализирую требования:

    • Объём данных
    • Тип данных (реляционные, временные ряды, граф)
    • Требования по консистентности (ACID vs BASE)
    • Требования по latency
  2. Сравниваю варианты:

    PostgreSQL: ACID ✅, Масштабируемость ⚠️, Стоимость ✅
    MongoDB:   ACID ⚠️, Масштабируемость ✅, Стоимость ✅
    Cassandra: ACID ❌, Масштабируемость ✅, Стоимость ⚠️
    
  3. Выбираю с запасом:

    • Если сомневаюсь - выбираю PostgreSQL
    • Легче мигрировать из PG в специализированную БД
    • Чем наоборот
  4. Тестирую на данных:

    • Проверяю performance под нагрузкой
    • Smoke тесты для failover сценариев
    • Backup/restore процедуры

Типичная архитектура микросервиса

Microservice Architecture:

┌─────────────────────────────────────┐
│          REST API (Spring)          │
└─────────────────────────────────────┘
            ↓
┌─────────────────────────────────────┐
│    Caching Layer (Redis)            │
│  - Query cache                      │
│  - Session store                    │
│  - Rate limiting                    │
└─────────────────────────────────────┘
            ↓
┌─────────────────────────────────────┐
│    Primary Data Store               │
│    (PostgreSQL)                     │
│  - ACID транзакции                  │
│  - Business data                    │
└─────────────────────────────────────┘
            ↓
┌─────────────────────────────────────┐
│    Secondary Systems                │
│  - Elasticsearch (поиск)            │
│  - ClickHouse (аналитика)           │
│  - S3 (файлы)                       │
└─────────────────────────────────────┘

Отличный пример: финтех сервис

// Account Service микросервис

// 1. PostgreSQL - основной store
@Entity
public class Account {
    @Id
    private UUID id;
    private BigDecimal balance;
    private LocalDateTime lastUpdated;
}

// 2. Redis - для быстрого доступа к балансам
@Service
public class AccountBalanceCache {
    public BigDecimal getBalance(UUID accountId) {
        String key = "account:balance:" + accountId;
        return redis.get(key);  // ~1ms
    }
}

// 3. ClickHouse - для аналитики
@Service
public class TransactionLogger {
    public void logTransaction(Transaction txn) {
        clickhouse.insert("transactions", txn);
        // Потом можно анализировать паттерны
    }
}

Заключение

Для нового микросервиса я выбираю:

  1. По умолчанию: PostgreSQL + Redis
  2. Затем анализирую: Нужны ли специализированные хранилища
  3. В итоге выбираю: Минимальный набор, который решает задачу

Лучше использовать 2-3 БД в совершенстве, чем 10 поверхностно.