← Назад к вопросам
Что такое нереляционные базы данных?
2.0 Middle🔥 181 комментариев
#Кэширование и NoSQL
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое нереляционные базы данных?
Нереляционные базы данных (NoSQL — Not Only SQL) — это системы управления базами данных, которые не используют традиционную реляционную модель с таблицами, строками и столбцами. Вместо этого они хранят данные в других форматах: документы, графы, ключ-значение, временные ряды.
Основные различия: SQL vs NoSQL
| Характеристика | SQL (Реляционные) | NoSQL (Нереляционные) |
|---|---|---|
| Модель данных | Таблицы, строки, столбцы | Документы, графы, ключ-значение |
| Схема | Фиксированная схема | Гибкая или без схемы |
| Масштабирование | Вертикальное (мощнее сервер) | Горизонтальное (больше серверов) |
| Транзакции | ACID гарантии | BASE (базовая согласованность) |
| Язык запросов | SQL | Специфичный для БД |
| Примеры | PostgreSQL, MySQL, Oracle | MongoDB, Redis, Cassandra, Neo4j |
Типы NoSQL баз данных
1. Document Stores (MongoDB)
Хранят данные как документы (JSON, BSON).
import com.mongodb.client.*;
import org.bson.Document;
import com.mongodb.MongoClient;
public class MongoDBExample {
public static void main(String[] args) {
// Подключение к MongoDB
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("myapp");
MongoCollection<Document> users = database.getCollection("users");
// ✅ Документ как JSON
Document user = new Document()
.append("_id", 1)
.append("name", "John Doe")
.append("email", "john@example.com")
.append("age", 30)
.append("tags", new String[]{"developer", "java", "spring"})
.append("address", new Document()
.append("street", "123 Main St")
.append("city", "New York")
.append("zip", "10001"));
// Вставка документа
users.insertOne(user);
// Поиск
Document found = users.find(new Document("email", "john@example.com")).first();
System.out.println(found.toJson());
// Обновление
users.updateOne(
new Document("_id", 1),
new Document("$set", new Document("age", 31))
);
// Удаление
users.deleteOne(new Document("_id", 1));
mongoClient.close();
}
}
2. Key-Value Stores (Redis)
Хранят данные как пары ключ-значение, очень быстро.
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import com.google.gson.Gson;
public class RedisExample {
public static void main(String[] args) {
JedisPool pool = new JedisPool("localhost", 6379);
try (Jedis jedis = pool.getResource()) {
// ✅ Простое хранилище ключ-значение
jedis.set("user:1:name", "John");
jedis.set("user:1:email", "john@example.com");
// Чтение
String name = jedis.get("user:1:name");
System.out.println("Name: " + name);
// Хеши (объекты)
jedis.hset("user:1", "name", "John");
jedis.hset("user:1", "email", "john@example.com");
String userName = jedis.hget("user:1", "name");
// Списки (очереди)
jedis.lpush("messages:queue", "msg1", "msg2", "msg3");
String msg = jedis.rpop("messages:queue");
// Множества
jedis.sadd("user:1:tags", "java", "spring", "database");
// Сортированные множества
jedis.zadd("leaderboard", 1000, "player1");
jedis.zadd("leaderboard", 1200, "player2");
}
}
}
3. Wide-Column Stores (Cassandra)
Система типа таблиц, но распределённая и масштабируемая.
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.cql.ResultSet;
import com.datastax.oss.driver.api.core.cql.Row;
public class CassandraExample {
public static void main(String[] args) {
// Подключение к Cassandra
try (CqlSession session = CqlSession.builder().build()) {
// Создание таблицы
session.execute(
"CREATE TABLE IF NOT EXISTS users (" +
" id UUID PRIMARY KEY," +
" name TEXT," +
" email TEXT," +
" age INT" +
")"
);
// Вставка данных
session.execute(
"INSERT INTO users (id, name, email, age) " +
"VALUES (uuid(), 'John', 'john@example.com', 30)"
);
// Запрос данных
ResultSet rows = session.execute("SELECT * FROM users WHERE email = 'john@example.com'");
for (Row row : rows) {
System.out.println("Name: " + row.getString("name"));
}
}
}
}
4. Graph Databases (Neo4j)
Хранят данные как графы с вершинами и рёбрами.
import org.neo4j.driver.*;
public class Neo4jExample {
public static void main(String[] args) {
// Подключение к Neo4j
Driver driver = GraphDatabase.driver("bolt://localhost:7687",
AuthTokens.basic("neo4j", "password"));
try (Session session = driver.session()) {
// Создание узлов и отношений
session.executeWrite(tx -> {
tx.run(
"CREATE (user1:User {name: 'John', email: 'john@example.com'}) " +
"CREATE (user2:User {name: 'Jane', email: 'jane@example.com'}) " +
"CREATE (user1)-[:FOLLOWS]->(user2)"
);
return null;
});
// Запрос: найти подписчиков
Result result = session.run(
"MATCH (user:User)-[:FOLLOWS]->(following:User) " +
"WHERE user.name = 'John' " +
"RETURN following.name as name"
);
while (result.hasNext()) {
Record record = result.next();
System.out.println("John follows: " + record.get("name"));
}
}
driver.close();
}
}
Преимущества NoSQL
// 1. ГИБКОСТЬ СХЕМЫ
// В MongoDB можно хранить данные разной структуры
Document user1 = new Document("name", "John").append("age", 30);
Document user2 = new Document("name", "Jane")
.append("phone", "+1234567890")
.append("premium", true); // У user2 другие поля!
// 2. ГОРИЗОНТАЛЬНОЕ МАСШТАБИРОВАНИЕ
// Cassandra и MongoDB легко масштабируются на множество серверов
// Просто добавляешь ноды
// 3. ПРОИЗВОДИТЕЛЬНОСТЬ
// Redis может обрабатывать 100,000+ операций в секунду
// Идеален для кэша и очередей
// 4. СТРУКТУРИРОВАННЫЕ ДАННЫЕ
// MongoDB хранит JSON — нативно совместимо с Java
Недостатки NoSQL
// 1. ОТСУТСТВИЕ ACID ГАРАНТИЙ
// Данные могут быть в промежуточном состоянии при отказе
// Нужно самостоятельно обеспечивать консистентность
// 2. НЕТУ JOINS
// Вместо одного запроса нужно несколько запросов и merge в коде
public List<Order> getUserOrders(String userId) {
// Запрос 1: получить пользователя
Document user = usersCollection.find(new Document("_id", userId)).first();
// Запрос 2: получить его заказы
List<Document> orders = new ArrayList<>();
ordersCollection.find(new Document("userId", userId))
.into(orders);
// Merge в коде — сложнее
return orders.stream()
.map(this::documentToOrder)
.collect(Collectors.toList());
}
// 3. ДУБЛИРОВАНИЕ ДАННЫХ
// Для лучшей производительности часто дублируют данные
// Это создаёт проблемы с синхронизацией
// 4. ЛИМИТЫ ПАМЯТИ
// Redis хранит всё в памяти
// Может быть дорого для больших объёмов
Когда использовать NoSQL
// ✅ MongoDB — для документов и гибкой схемы
// Примеры: CMS, content platforms, flexible data
// ✅ Redis — для кэша и очередей
// Примеры: session store, leaderboards, rate limiting
// ✅ Cassandra — для time-series и больших объёмов
// Примеры: logs, metrics, IoT data
// ✅ Neo4j — для графов и отношений
// Примеры: social networks, recommendations, relationships
Гибридный подход: SQL + NoSQL
public class HybridDataStore {
private DataSource postgresPool; // SQL для критических данных
private MongoCollection<Document> mongoUsers; // NoSQL для гибких данных
private JedisPool redisPool; // Redis для кэша
public void saveUser(User user) {
// 1. Сохранить в PostgreSQL (source of truth)
saveToDB(user);
// 2. Кэшировать в Redis (для быстрого доступа)
cacheInRedis(user);
// 3. Сохранить расширенные данные в MongoDB
saveExtendedDataToMongo(user);
}
public User getUserWithCache(String id) {
// 1. Попробовать Redis
User cached = getFromRedis(id);
if (cached != null) return cached;
// 2. Если нет — получить из PostgreSQL
User user = getFromDB(id);
// 3. Кэшировать
cacheInRedis(user);
return user;
}
}
Примеры использования в Spring Boot
Spring Data MongoDB
import org.springframework.data.mongodb.repository.MongoRepository;
public interface UserRepository extends MongoRepository<User, String> {
User findByEmail(String email);
List<User> findByAgeGreaterThan(int age);
}
Spring Data Redis
import org.springframework.data.redis.core.RedisTemplate;
@Service
public class CacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void cacheUser(User user) {
redisTemplate.opsForValue().set("user:" + user.getId(), user);
}
}
Ключевые выводы
- NoSQL — не замена SQL, а дополнение для специфичных задач
- Выбор зависит от характера данных и требований
- Полиглотная персистентность — использование разных БД в одном приложении
- Trade-offs — в обмен на scalability теряем некоторые гарантии
- Знай оба мира — хороший разработчик должен уметь работать с SQL и NoSQL
Не думай о NoSQL как о замене SQL — это инструменты для разных задач!