存储工具(三)非关系数据库解决了什么问题,又产生了什么问题?
背景介绍
曾经我们可以一条SQL走遍天下,而随着业务开发,不同层面和不同方向都出现了不同情况的困难,比如
上一节的存储工具(二)数据库的表与字段尾声,我们留下了几个问题。
- 如果遇到一个热点数据,读取量很大,怎么实现热点数据读取时间快速?
- 如果遇到一类数据,存储结构经常变更,如何存放?
- 若遇到多篇文章,文字量很大,如何实现全文高效搜索?
- 如果引入新的存储组件,又会带来什么问题,该如何解决?
问题一
如果我们存在一份热点数据,那么最快能想到的就是将数据存储在操作系统里最快响应的存储介质————内存里(注:由于从操作系统指令来说,不能直接操作CPU高速缓存,所以暂时忽略)。
- 若是单机且无并发问题,则将固定常量,枚举值等存入
map(小规模)。 - 若只是单机,存在并发或者配置缓存容量,过期策略等逻辑,可以选择引入第三方库,
Caffeine(单机、中等规模)。 - 若存在分布式情况,可以引入分布式内存型存储组件
Redis(分布式规模)。
注:在生产环境中,单机本地缓存和分布式缓存往往会联合使用。他们不是非此即彼。
问题二
- 若是单机且无并发问题,则可以将数据存入关系数据库的
JSON类型。这个结构天然支持半结构化数据,且对前端友好,在接口传递中用户可以无缝使用。 - 若存在复杂的搜索要求或者结构变化极大且频繁的情况,可以引入分布式文档型存储组件
MongoDB。
注:在生产环境中,一些核心信息比如用户信息,权限信息一般存在关系型数据库,比如浏览历史,评论等非核心信息可以存放在MongoDB方便查询和拓展。
问题三
- 若数据量很小,且搜索逻辑简单,可以在业务上给各个文章人工主动添加标签实现,或者在数据库层面通过
FULLTEXT全文索引实现。 - 若数据量大,且分词逻辑复杂,则可以选用分布式文档存储组件
Elasticsearch。
注意:mysql只有5.7以后才支持FULLTEXT全文索引,而PostgreSQL的全文索引很强大,小规模完全够用。
问题四
引入了新的存储组件存在多个不同维度的问题
- 数据一致性问题,比如多套存储之间数据不同步,出现双写失败、数据错位等问题。
- 数据复杂度问题,每引入一个存储组件,开发和管理都需要成本。
- 出现数据故障时,排查故障的链路周期变长。
针对数据一致性问题
- 所有的数据都需要先写入关系型数据库。
- 其他数据源在关系型数据库更新后可以按照业务需要走手动更新(低频,小数据量)、异步消息更新(中频,中数据量)或者监听
Binlog异步同步(高频,大数据量)。 - 核心表可以新增版本号或其他机制防止异常写入。
针对数据复杂度问题
- 首先需要明确需求背景以及合理运用工具,不要做过早的优化和引入多余的复杂度。
- 如果性能出现瓶颈,必须引入非关系型数据库时,需要合理运用各个存储组件,做好开发和管理工作。
针对数据故障问题
- 对于中间件极多的工程项目,开发过程中需要引入
traceId,出现数据故障时通过traceId定位整个链路的故障节点。
尾声
我们新增了非关系型数据库,解决了上面三个问题。然而存储之路并没有走完。
比如以下两个典型场景,你会选择什么方案。
- 需要秒级展示,多维度聚合的千万乃至上亿的数据。
- 需要对外展示的t+1海量离线数据,且需要支持任意天数的历史数据查询。

浙公网安备 33010602011771号