Ответ
Ключевой принцип работы с данными в микросервисах — «Database per Service» (База данных на сервис). Каждый микросервис владеет своими данными и имеет собственную, изолированную от других базу данных (или схему). Это обеспечивает слабую связанность и независимость сервисов.
Взаимодействие одного сервиса со своей БД
Внутри одного сервиса для взаимодействия с его базой данных применяются стандартные подходы:
Прямые SQL-запросы через пакет
database/sql
:
*Идеально для простых запросов, дает полный контроль.// db *sql.DB
row := db.QueryRowContext(ctx, "SELECT name, email FROM users WHERE id=$1", userID)
var user User
if err := row.Scan(&user.Name, &user.Email); err != nil {
// handle error
}Использование ORM (Object-Relational Mapping), например,
GORM
илиent
:
*Упрощает CRUD-операции и сложные запросы, абстрагируя SQL.// db *gorm.DB
var user User
result := db.First(&user, userID)
if result.Error != nil {
// handle error
}Паттерн Repository:
*Создает слой абстракции над хранилищем данных, изолируя бизнес-логику от деталей реализации (SQL, NoSQL и т.д.). Это самый гибкий и тестируемый подход.type UserRepository interface {
GetByID(ctx context.Context, id int) (*User, error)
}
type PostgresUserRepository struct {
db *sql.DB
}
func (r *PostgresUserRepository) GetByID(ctx context.Context, id int) (*User, error) {
// ... реализация с SQL-запросом
}
Взаимодействие между сервисами
Поскольку прямой доступ к БД другого сервиса запрещен, для межсервисных операций с данными используют:
- API Composition: Один сервис запрашивает данные у другого через его публичный API (REST, gRPC).
- Saga Pattern: Для распределенных транзакций, затрагивающих несколько сервисов. Если один из шагов саги не удается, выполняются компенсирующие транзакции для отката изменений.
- CQRS (Command Query Responsibility Segregation): Разделение операций чтения и записи. Для сложных запросов, требующих данных из многих сервисов, создается отдельный сервис чтения с собственной оптимизированной базой данных, которая асинхронно наполняется событиями из других сервисов (например, через Kafka).
Ключевые выводы:
- Изоляция: Каждый сервис управляет только своей БД.
- Транзакции: Атомарные транзакции ограничены рамками одного сервиса.
- Кэширование: Используйте Redis или Memcached для снижения нагрузки на БД и ускорения ответов.
- Миграции: Каждый сервис самостоятельно управляет миграциями своей схемы БД.