NoSQL数据库核心原理与电商应用实战
核心思想: NoSQL (Not Only SQL) 数据库是为了解决传统关系型数据库在超大规模数据、高并发和灵活数据模型方面的不足而设计的。它们通过牺牲部分一致性(通常是最终一致性)和事务的严格性,来换取极高的性能和可扩展性。
第1章:NoSQL核心概念与选型指南
1.1. NoSQL核心理念
NoSQL数据库的出现是为了解决传统关系型数据库在以下场景中的局限性:
- 超大规模数据存储:传统关系型数据库在处理PB级数据时性能急剧下降
- 高并发读写:关系型数据库的锁机制和事务处理在高并发场景下成为瓶颈
- 灵活数据模型:关系型数据库的严格表结构难以适应快速变化的业务需求
NoSQL通过CAP理论的权衡(通常选择AP而牺牲C),实现了极高的性能和可扩展性。
1.2. NoSQL数据库分类与选型
类型 | 代表产品 | 核心优势 | 典型应用场景 | 数据一致性 |
---|---|---|---|---|
键值存储 | Redis, Memcached | 极高的读写性能,丰富的数据结构 | 分布式缓存、会话存储、分布式锁、排行榜 | 最终一致性 |
文档数据库 | MongoDB | 灵活的类JSON数据模型,强大的查询语言 | 内容管理系统、用户画像、移动应用后端 | 最终一致性 |
搜索引擎 | Elasticsearch, Solr | 强大的全文检索和实时数据分析能力 | 日志分析(ELK)、商品搜索、应用内搜索 | 最终一致性 |
列式数据库 | HBase, Cassandra | 极佳的水平扩展能力,适合海量数据写入 | 物联网数据、用户行为日志、消息流数据 | 最终一致性/强一致性(Cassandra) |
1.3. NoSQL与关系型数据库的对比
特性 | 关系型数据库 | NoSQL数据库 |
---|---|---|
数据模型 | 严格的表结构,需要预先定义 | 灵活的数据模型,可动态调整 |
扩展性 | 垂直扩展为主,水平扩展困难 | 天然支持水平扩展 |
事务支持 | ACID事务 | BASE理论,最终一致性 |
查询语言 | SQL | 各自特定的查询语言 |
性能 | 中等 | 极高(针对特定场景) |
一致性 | 强一致性 | 最终一致性 |
第2章:Redis核心原理与电商应用
核心定位: 基于内存的高性能键值数据库,通常用作分布式缓存来降低后端数据库压力。
2.1. Redis核心数据结构
Redis支持多种数据结构,每种都有其特定的应用场景:
- String: 最基本类型,可以是字符串、整数或浮点数。用于缓存、计数器。
- Hash: 字段-值(field-value)对的集合,适合存储对象。
- List: 字符串列表,按插入顺序排序。可实现队列、栈。
- Set: 无序的唯一字符串集合。用于标签、好友关系。
- Sorted Set (ZSet): 每个元素关联一个分数,按分数排序的集合。用于排行榜、带权重的任务队列。
- Bitmaps: 位图,用于统计活跃用户等场景。
- HyperLogLog: 用于基数统计,如统计网站UV。
- Geo: 地理位置相关数据结构。
2.2. Redis持久化机制
Redis提供了两种持久化机制,可根据业务需求选择:
- RDB (Redis Database): 在指定时间间隔内生成数据集的快照。
- 优点: 文件紧凑,恢复速度快,适合备份
- 缺点: 可能丢失最后一次快照后的数据
- AOF (Append Only File): 记录所有写操作命令。
- 优点: 数据最完整,支持多种同步策略
- 缺点: 文件体积大,恢复速度慢
- 生产环境建议: RDB和AOF同时开启,结合使用
2.3. Redis高可用方案
- 主从复制: 实现读写分离和数据备份
- 哨兵模式 (Sentinel): 自动故障检测和主从切换
- 集群模式 (Cluster): 数据分片和高可用性
2.4. 缓存三大问题与对策
缓存穿透: 查询一个不存在的数据,导致请求绕过缓存,直接打到数据库。
- 对策: 1. 缓存空值: 将数据库返回的空结果也缓存起来,但设置较短的过期时间。2. 布隆过滤器: 在访问缓存前,通过布隆过滤器快速判断数据是否存在,拦截大量非法请求。
缓存击穿: 一个热点Key在失效的瞬间,大量并发请求同时涌入,直接打到数据库。
- 对策: 1. 互斥锁: 只允许一个线程去查询数据库并回写缓存,其他线程等待。2. 热点数据永不过期。
缓存雪崩: 大量Key在同一时间集中失效,导致数据库压力瞬时剧增。
- 对策: 1. 过期时间打散: 在基础过期时间上增加一个随机值。2. 服务熔断/降级: 暂时关闭非核心功能,保证核心服务可用。
2.5. Redis分布式锁实现
Redis在分布式系统中常用于实现分布式锁,主要利用SET key value NX EX seconds
原子命令:
SET lock_key random_value NX EX 30
关键要点:
- Value要唯一: value应存入一个唯一的ID,释放锁时先
GET
比对,防止误删他人的锁 - 设置过期时间: 防止客户端宕机导致死锁
- 原子性操作: 使用Lua脚本保证释放锁的原子性
生产级解决方案: 使用Redisson等成熟客户端,其提供了看门狗机制自动续期,避免业务执行时间超过锁过期时间的问题。
第3章:MongoDB核心原理与电商应用
核心定位: 面向文档的数据库,以类JSON的BSON格式存储数据,模式灵活,非常适合敏捷开发和半结构化数据。
3.1. MongoDB核心概念
- 文档 (Document): 数据基本单元,类似于JSON对象。
- 集合 (Collection): 文档的集合,类似于关系数据库的表。
- 数据库 (Database): 集合的容器,一个MongoDB实例可以包含多个数据库。
- ObjectId: MongoDB默认的主键类型,包含时间戳、机器标识、进程ID和计数器。
3.2. MongoDB索引机制
MongoDB支持多种索引类型:
- 单字段索引: 对单个字段建立索引
- 复合索引: 对多个字段建立索引,遵循最左前缀原则
- 多键索引: 对数组字段建立索引
- 文本索引: 支持文本搜索
- 地理空间索引: 支持地理位置查询
3.3. 聚合管道 (Aggregation Pipeline)
MongoDB的聚合管道是一个强大的数据处理框架,允许对文档进行多阶段的转换和分析:
db.orders.aggregate([
{
$match: { status: "completed" } // 第一阶段:筛选已完成的订单
},
{
$group: { // 第二阶段:按用户ID分组,并计算总金额
_id: "$userId",
totalAmount: { $sum: "$amount" }
}
},
{
$sort: { totalAmount: -1 } // 第三阶段:按总金额降序排序
}
])
3.4. MongoDB高可用方案
- 副本集 (Replica Set): 自动故障转移和数据冗余
- 分片集群 (Sharded Cluster): 水平扩展,处理海量数据
第4章:Elasticsearch核心原理与电商应用
核心定位: 基于Lucene库的分布式搜索引擎,提供强大的全文检索、实时分析和可扩展性。
4.1. 核心原理:倒排索引
传统的关系数据库索引是"文档 -> 单词",而倒排索引是**“单词 -> 文档列表”。ES会对文档内容进行分词**,然后为每个词条创建一个包含它的所有文档的列表。这使得基于关键词的搜索变得极其高效。
4.2. 核心概念
- 索引 (Index): 类似于关系数据库的数据库
- 类型 (Type): 类似于关系数据库的表(在ES 7.x后已废弃)
- 文档 (Document): 类似于关系数据库的行
- 字段 (Field): 类似于关系数据库的列
- 映射 (Mapping): 定义字段的数据类型和属性
- 分片 (Shard): 索引的水平分割单元
- 副本 (Replica): 分片的备份,提供高可用性
4.3. 写入与查询流程
- 写入流程: 客户端请求 -> 协调节点 -> 路由到主分片 -> 主分片写入 -> 同步到副本分片 -> 确认。
- 查询DSL (Domain Specific Language): ES提供了一套丰富的基于JSON的查询语言,可以实现从简单匹配到复杂的多条件、多层次的组合查询。
4.4. 性能优化关键点
- 避免深度分页: 使用
scroll
或search_after
来处理大量数据的分页,而不是from
+size
。 - 冷热数据分离: 将访问频繁的热数据存储在高性能的SSD节点,将不常用的冷数据存储在低成本的HDD节点。
- 合理设置分片: 分片不是越多越好,过多的分片会增加管理开销。通常建议单个分片大小在10GB到50GB之间。
第5章:HBase核心原理与电商应用
核心定位: 基于Hadoop的分布式列式数据库,适合海量数据的随机读写。
5.1. HBase核心概念
- RowKey: 行键,HBase中数据的唯一标识,按字典序存储
- Column Family: 列族,相关列的集合
- Column Qualifier: 列限定符,列族下的具体列
- Timestamp: 时间戳,用于版本控制
- Region: 表的水平分割单元
5.2. RowKey设计原则
RowKey设计是HBase性能的关键:
- 避免热点: 如果RowKey是连续的(如时间戳),会导致所有写操作集中在单个RegionServer,形成热点。通常需要散列化或反转RowKey。
- 查询效率: 将常用于查询的字段放在RowKey中,可以实现高效的范围扫描。
5.3. HBase架构
- HMaster: 管理RegionServer,处理元数据操作
- RegionServer: 存储实际数据,处理读写请求
- ZooKeeper: 协调服务,维护集群状态
第6章:电商场景NoSQL应用实践
6.1. 商品系统
- Redis: 缓存热门商品信息,存储商品库存
- MongoDB: 存储商品详情、分类信息
- Elasticsearch: 商品搜索功能
6.2. 用户系统
- Redis: 存储用户会话、Token信息
- MongoDB: 存储用户基本信息、地址信息
- HBase: 存储用户行为日志
6.3. 订单系统
- Redis: 分布式锁防止超卖,缓存订单状态
- MongoDB: 存储订单详情
- HBase: 存储订单流水日志
6.4. 推荐系统
- Redis: 存储用户实时行为数据
- MongoDB: 存储用户画像数据
- HBase: 存储用户历史行为数据
第7章:核心概念
Q: Redis的分布式锁如何实现?需要注意什么?
A: 主要利用SET key value NX EX seconds
这个原子命令。NX
保证只有键不存在时才设置成功(获取锁),EX
设置过期时间防止死锁。注意事项: 1. Value要唯一: value应存入一个唯一的ID,释放锁时先GET
比对,防止误删他人的锁。2. 锁续期: 对于长时间任务,需要一个"看门狗"机制来为锁自动续期。Redisson等客户端已完美实现这些功能。
Q: Elasticsearch的写入流程为什么是近实时的?
A: ES的写操作首先是写入内存中的buffer
和translog
(事务日志)。数据只有在refresh
操作后(默认1秒一次),才会从buffer
生成一个新的段(Segment)并刷新到文件系统缓存中,此时数据才能被搜索到。所以它不是严格的实时,而是"近实时"。
Q: HBase的RowKey为什么要精心设计?
A: HBase是围绕RowKey构建的,数据按RowKey的字典序物理存储。一个好的RowKey设计至关重要:1. 避免热点: 如果RowKey是连续的(如时间戳),会导致所有写操作集中在单个RegionServer,形成热点。通常需要散列化或反转RowKey。2. 查询效率: 将常用于查询的字段放在RowKey中,可以实现高效的范围扫描。
Q: MongoDB的副本集是如何保证高可用的?
A: MongoDB副本集通过以下机制保证高可用:
- 自动故障检测: 副本集成员间通过心跳检测彼此状态
- 选举机制: 当主节点故障时,剩余节点会进行选举产生新的主节点
- 数据同步: 从节点通过oplog同步主节点的数据变更
- 读写分离: 应用可以配置读取从节点,分担主节点压力