第7集:'Join'税 vs. 'Storage'税
Source: Dev.to
SQL vs NoSQL 取舍
当我们在系统设计中讨论 SQL 与 NoSQL 时,已经超越了语法层面,进入核心取舍。 在真实系统中,你选择数据库并不是因为喜欢它的查询语言,而是因为它处理流量、一致性和故障的方式。
- SQL(规范化) – 最小化冗余。更新用户姓名只需在一个位置完成。你付出的“代价”是 JOIN:如果仪表盘需要来自五个表的数据,数据库必须在读取时进行大量工作来把数据拼接在一起。
- NoSQL(反规范化) – 接受冗余。你可能会在五个不同的文档集合中存储用户的姓名。这里的“代价”是 存储和更新复杂度。读取速度极快,因为数据已经是“预先拼接”的,但一次姓名更改需要在多个地方更新。
自问一下: 应用是读密集型还是写密集型?对于一次写入、数百万次读取的社交媒体信息流,NoSQL 的读就绪格式往往更占优势。
CAP 定理
CAP 定理是分布式系统的终极现实检验。
- 一致性 (C): 每个节点在同一时间看到相同的数据。
- 可用性 (A): 每个请求都会得到响应(即使是陈旧的)。
- 分区容错性 (P): 即使节点之间的网络出现分区,系统仍能继续工作。
在分布式环境中,你必须选择 P。剩下的就是在 CP(类似 SQL 的严格性)和 AP(类似 NoSQL 的速度)之间取舍。
- SQL (CP): 适用于银行或库存系统。宁可系统不可用,也不愿报告错误的余额。
- NoSQL (AP): 适用于帖子点赞等场景。轻微的不一致(例如 100 与 102 个赞)是可以接受的。
这种取舍往往是高级设计面试中最大的考量因素。
扩展
SQL 扩展(垂直扩展)
垂直扩展就像给同一辆车换更大的发动机。 当你达到最大服务器的极限后,只能诉诸手动分片——这是一场架构复杂性的噩梦。
NoSQL 扩展(水平扩展)
NoSQL 数据库天生支持分片。 只需向集群添加更多廉价服务器(节点),数据库会自动把数据分布到这些节点上。
实际案例
金融系统(SQL)
当一分钱的缺失都可能引发法律灾难时,SQL 是唯一可行的选择。 金融系统依赖 ACID 特性来保证事务要么完整成功,要么全部失败,绝不存在“中间状态”。
示例: JPMorgan Chase 在核心账本上大量使用调优的关系型数据库(PostgreSQL 或 Oracle)。严格的模式和强一致性至关重要;余额必须立即正确,而不是“最终一致”。
社交媒体信息流(NoSQL)
社交媒体是读密集型的,并且处理海量非结构化数据(文本、图片、标签、互动)。NoSQL 的优势在于水平扩展并且可以提供预先计算好的文档,响应时间在毫秒级。
示例: Instagram 采用混合方案,但其信息流使用了类似 NoSQL 的架构。滚动时,应用会拉取一个预先计算好的文档,里面包含照片、说明和点赞数,避免了跨多个表的复杂 JOIN。
键值存储(Redis)
有时你需要一个临时、极速的存储,仅用于几分钟。键值型 NoSQL 存储如 Redis 非常适合用户会话、购物车或排行榜。将会话令牌存入 Redis 可以避免每次请求都访问主 SQL 数据库。
示例: 如 Riot Games(《英雄联盟》)等游戏平台使用 NoSQL 键值存储来管理实时排行榜和玩家会话。成千上万的玩家同时结束比赛,需要即时的排名更新,而传统 SQL 锁的延迟无法满足此需求。