🗄️ NoSQL数据库
掌握现代NoSQL数据库的分类、特点和应用场景,学习MongoDB、Redis、Cassandra和Neo4j的使用
学习目标
- 理解NoSQL数据库的概念和分类
- 掌握文档数据库MongoDB的特点和应用
- 学习键值数据库Redis的使用场景
- 了解列族数据库Cassandra的架构
- 认识图数据库Neo4j的优势和应用
NoSQL分类
NoSQL(Not Only SQL)数据库是为了解决传统关系型数据库在处理大数据、高并发、分布式场景下的局限性而产生的。NoSQL数据库具有高可扩展性、高性能、灵活的数据模型等特点。
NoSQL并不是要完全替代SQL数据库,而是在特定场景下提供更好的解决方案。选择合适的数据库类型是架构设计的重要决策。
NoSQL数据库分类
NoSQL vs SQL对比
特性 | SQL数据库 | NoSQL数据库 |
---|---|---|
数据模型 | 关系型,表结构 | 多样化:文档、键值、列族、图 |
扩展性 | 垂直扩展为主 | 水平扩展友好 |
ACID特性 | 强一致性 | 最终一致性 |
查询语言 | 标准SQL | 各自的查询API |
适用场景 | 复杂事务、关系查询 | 大数据、高并发、灵活模式 |
文档数据库(MongoDB)
MongoDB是最流行的文档数据库,使用BSON(Binary JSON)格式存储数据。它提供了丰富的查询功能、自动分片、副本集等企业级特性。
MongoDB核心特性
- 灵活的文档模型:支持嵌套文档和数组,无需预定义schema
- 强大的查询能力:支持复杂查询、索引、聚合管道
- 水平扩展:内置分片功能,支持自动数据分布
- 高可用性:副本集提供自动故障转移
- ACID事务:4.0版本开始支持多文档事务
MongoDB基本操作
// 插入文档
db.users.insertOne({
name: "张三",
age: 25,
email: "zhangsan@example.com",
address: {
city: "北京",
district: "朝阳区"
},
hobbies: ["读书", "游泳", "编程"]
});
// 查询文档
db.users.find({ age: { $gte: 18 } });
// 更新文档
db.users.updateOne(
{ name: "张三" },
{ $set: { age: 26 }, $push: { hobbies: "旅行" } }
);
// 聚合查询
db.users.aggregate([
{ $match: { age: { $gte: 18 } } },
{ $group: { _id: "$address.city", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
]);
适用场景
键值数据库(Redis)
Redis(Remote Dictionary Server)是一个高性能的键值存储系统,支持多种数据结构,常用作缓存、消息队列和会话存储。
Redis数据类型
Redis基本操作
# 字符串操作
SET user:1:name "张三"
GET user:1:name
INCR user:1:visits
# 列表操作
LPUSH tasks "task1" "task2" "task3"
RPOP tasks
LLEN tasks
# 集合操作
SADD tags "redis" "nosql" "database"
SMEMBERS tags
SINTER tags1 tags2
# 哈希操作
HSET user:1 name "张三" age 25 city "北京"
HGET user:1 name
HGETALL user:1
# 有序集合操作
ZADD leaderboard 100 "player1" 200 "player2" 150 "player3"
ZRANGE leaderboard 0 -1 WITHSCORES
ZREVRANK leaderboard "player2"
Redis应用场景
- 缓存系统:提高数据访问速度,减少数据库压力
- 会话存储:分布式系统中的用户会话管理
- 消息队列:使用List实现简单的消息队列
- 计数器:网站访问量、点赞数等实时计数
- 排行榜:游戏排行榜、热门文章排序
- 分布式锁:在分布式环境中实现互斥锁
列族数据库(Cassandra)
Apache Cassandra是一个高度可扩展的分布式列族数据库,设计用于处理大量数据和高并发访问。它提供了线性扩展能力和高可用性。
Cassandra核心特性
数据模型
Cassandra使用列族(Column Family)作为数据组织单位,类似于关系数据库的表,但更加灵活。每行可以有不同的列,列按列族分组。
-- 创建键空间
CREATE KEYSPACE ecommerce
WITH REPLICATION = {
'class': 'SimpleStrategy',
'replication_factor': 3
};
-- 创建表
CREATE TABLE ecommerce.orders (
user_id UUID,
order_date timestamp,
order_id UUID,
total_amount decimal,
status text,
PRIMARY KEY (user_id, order_date, order_id)
) WITH CLUSTERING ORDER BY (order_date DESC);
-- 插入数据
INSERT INTO ecommerce.orders
(user_id, order_date, order_id, total_amount, status)
VALUES
(uuid(), '2024-01-15 10:30:00', uuid(), 299.99, 'completed');
-- 查询数据
SELECT * FROM ecommerce.orders
WHERE user_id = ? AND order_date >= '2024-01-01';
适用场景
- 时序数据:IoT传感器数据、日志数据、监控指标
- 用户活动跟踪:用户行为日志、点击流数据
- 消息系统:聊天记录、通知历史
- 金融数据:交易记录、价格历史
图数据库(Neo4j)
Neo4j是领先的图数据库,专门用于存储和查询图形数据。它使用节点、关系和属性来表示和存储数据,特别适合处理复杂的关系查询。
图数据模型
Cypher查询语言
Cypher是Neo4j的声明式查询语言,使用ASCII艺术风格的语法来表示图形模式,直观易懂。
// 创建节点
CREATE (alice:Person {name: 'Alice', age: 30})
CREATE (bob:Person {name: 'Bob', age: 25})
CREATE (company:Company {name: 'TechCorp'})
// 创建关系
CREATE (alice)-[:WORKS_FOR {since: 2020}]->(company)
CREATE (bob)-[:WORKS_FOR {since: 2021}]->(company)
CREATE (alice)-[:KNOWS {since: 2019}]->(bob)
// 查询朋友的朋友
MATCH (person:Person)-[:KNOWS]->(friend)-[:KNOWS]->(friendOfFriend)
WHERE person.name = 'Alice'
RETURN friendOfFriend.name
// 查找最短路径
MATCH path = shortestPath(
(start:Person {name: 'Alice'})-[*]-(end:Person {name: 'Charlie'})
)
RETURN path
// 推荐算法:找到共同朋友最多的人
MATCH (person:Person {name: 'Alice'})-[:KNOWS]->(friend)-[:KNOWS]->(recommendation)
WHERE NOT (person)-[:KNOWS]->(recommendation)
RETURN recommendation.name, count(friend) as mutualFriends
ORDER BY mutualFriends DESC
LIMIT 5
Neo4j应用场景
NoSQL数据库选择指南
选择合适的NoSQL数据库需要考虑数据模型、性能要求、扩展性需求、一致性要求等多个因素。
- 数据结构:根据数据的复杂度和关系选择合适的数据模型
- 查询模式:考虑主要的查询类型和频率
- 扩展需求:评估未来的数据量和并发量增长
- 一致性要求:权衡一致性和可用性的需求
- 团队技能:考虑团队的技术栈和学习成本
决策矩阵
场景 | 推荐数据库 | 原因 |
---|---|---|
内容管理系统 | MongoDB | 灵活的文档结构,丰富的查询功能 |
缓存层 | Redis | 极高的读写性能,丰富的数据类型 |
时序数据 | Cassandra | 优秀的写入性能,时间序列优化 |
社交网络 | Neo4j | 天然的图形数据模型,关系查询优化 |
实时分析 | MongoDB + Redis | 组合使用,发挥各自优势 |