系统架构教程第12章:NoSQL数据库
章节头部 第12章
🗄️ NoSQL数据库
掌握现代NoSQL数据库的分类、特点和应用场景,学习MongoDB、Redis、Cassandra和Neo4j的使用
学习目标
学习目标
- 理解NoSQL数据库的概念和分类
- 掌握文档数据库MongoDB的特点和应用
- 学习键值数据库Redis的使用场景
- 了解列族数据库Cassandra的架构
- 认识图数据库Neo4j的优势和应用
NoSQL分类
NoSQL分类
NoSQL(Not Only SQL)数据库是为了解决传统关系型数据库在处理大数据、高并发、分布式场景下的局限性而产生的。NoSQL数据库具有高可扩展性、高性能、灵活的数据模型等特点。
核心理解
NoSQL并不是要完全替代SQL数据库,而是在特定场景下提供更好的解决方案。选择合适的数据库类型是架构设计的重要决策。
NoSQL数据库分类
文档数据库以文档为存储单位,支持复杂的数据结构,如JSON、BSON等。代表:MongoDB、CouchDB。键值数据库最简单的NoSQL模型,通过键值对存储数据,性能极高。代表:Redis、DynamoDB。列族数据库按列存储数据,适合大数据分析和时序数据。代表:Cassandra、HBase。图数据库专门处理图形数据和复杂关系查询。代表:Neo4j、ArangoDB。
NoSQL vs SQL对比
| 特性 | SQL数据库 | NoSQL数据库 |
|---|---|---|
| 数据模型 | 关系型,表结构 | 多样化:文档、键值、列族、图 |
| 扩展性 | 垂直扩展为主 | 水平扩展友好 |
| ACID特性 | 强一致性 | 最终一致性 |
| 查询语言 | 标准SQL | 各自的查询API |
| 适用场景 | 复杂事务、关系查询 | 大数据、高并发、灵活模式 |
文档数据库(MongoDB)
文档数据库(MongoDB)
MongoDB是最流行的文档数据库,使用BSON(Binary JSON)格式存储数据。它提供了丰富的查询功能、自动分片、副本集等企业级特性。
MongoDB核心特性
- 灵活的文档模型:支持嵌套文档和数组,无需预定义schema
- 强大的查询能力:支持复杂查询、索引、聚合管道
- 水平扩展:内置分片功能,支持自动数据分布
- 高可用性:副本集提供自动故障转移
- ACID事务:4.0版本开始支持多文档事务
MongoDB基本操作
MongoDB查询示例
// 插入文档
db.users.insertOne({
name: "张三",
age: 25,
email: "[email protected]",
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)
Redis(Remote Dictionary Server)是一个高性能的键值存储系统,支持多种数据结构,常用作缓存、消息队列和会话存储。
Redis数据类型
字符串(String)最基本的数据类型,可以存储文本、数字、二进制数据,最大512MB。列表(List)有序的字符串列表,支持从两端插入和弹出,适合实现队列和栈。集合(Set)无序的字符串集合,自动去重,支持集合运算。有序集合(ZSet)带分数的有序集合,支持范围查询和排行榜功能。哈希(Hash)键值对的集合,适合存储对象的属性。
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)
列族数据库(Cassandra)
Apache Cassandra是一个高度可扩展的分布式列族数据库,设计用于处理大量数据和高并发访问。它提供了线性扩展能力和高可用性。
Cassandra核心特性
线性扩展添加节点即可线性提升性能,无单点故障。高可用性数据自动复制到多个节点,支持跨数据中心部署。高性能写入优化的写入路径,支持高并发写入操作。
数据模型
Cassandra使用列族(Column Family)作为数据组织单位,类似于关系数据库的表,但更加灵活。每行可以有不同的列,列按列族分组。
Cassandra CQL示例
-- 创建键空间
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)
Neo4j是领先的图数据库,专门用于存储和查询图形数据。它使用节点、关系和属性来表示和存储数据,特别适合处理复杂的关系查询。
图数据模型
节点(Nodes)表示实体,如人、产品、公司等,可以有标签和属性。关系(Relationships)连接节点的有向边,表示实体间的关系,也可以有属性。属性(Properties)节点和关系的键值对数据,存储具体信息。
Cypher查询语言
Cypher是Neo4j的声明式查询语言,使用ASCII艺术风格的语法来表示图形模式,直观易懂。
Cypher查询示例
// 创建节点
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 | 组合使用,发挥各自优势 |