写点什么

NoSQL 到底怎么用?

作者:Java高工P7
  • 2021 年 11 月 11 日
  • 本文字数:1755 字

    阅读完需:约 6 分钟

  • 随机 IO


随机 IO 就需花费时间做昂贵磁盘寻道,读写效率比顺序 IO 小两到三数量级,想要提升写入性能就要尽量减少随机 IO。


  • 顺序 IO


MySQL 更新 binlog、redolog、undolog 都是在做顺序 IO。而更新 datafile 和索引文件则是在做随机 IO,为减少随机 IO,关系 DB 做了很多优化,比如写入时先写入内存,然后批量刷盘,但还是会产生随机 IO。


索引在 InnoDB 引擎中是 B+树,MySQL 主键是聚簇索引(数据与索引数据在一起),在数据插入或更新时,需找到要插入位置,再把数据写到特定位置,这就产生了随机 IO。一旦发生页分裂,就会做数据移动,极大损耗写性能。


而很多 NoSQL 使用基于 LSM 树的存储引擎,LSM 树(Log-Structured Merge Tree)牺牲一定读性能换取写入数据的高性能,Hbase、Cassandra、LevelDB 都是用这种算法作为存储的引擎。


数据首先会写入到 MemTable 内存结构,在 MemTable 中数据按写入的 Key 排序。为防止 MemTable 数据因为机器掉电或者重启而丢失,一般会写 Write Ahead Log 将数据备份在磁盘。


MemTable 在累积到一定规模时,会被刷新生成一个新的文件,叫 SSTable(Sorted String Table)。


当 SSTable 达到一定数量时,会将这些 SSTable 合并,减少文件数量,因为 SSTable 有序,所以合并快。


当从 LSM 树里面读数据时,我们首先从 MemTable 中查找数据,如果数据没有找到,再从 SSTable 中查找数据。因为存储的数据都是有序的,所以查找的效率是很高的,只是因为数据被拆分成多个 SSTable,所以读效率低于 B+树索引。



类似算法有很多,如 TokuDB 使用的名为 Fractal tree 的索引结构,它们的核心思想就是将随机 IO 变成顺序的 IO,从而提升写入的性能。


适用场景


===================================================================


除了提升性能,NoSQL 还可在某些场景下弥补传统关系型 DB 的不足,假设要设计商品搜索功能,需支持按照商品的名称模糊搜索到对应的商品。


这不就是:



此类语句并非总能走索引,只有后模糊匹配语句才走索引。比如



就没有走 name 索引,而



使用了“name”上的索引。而一旦没有使用索引就会扫描全表数据。


于是发现 Elasticsearch 支持搜索,基于“倒排索引”来实现,将记录中的某些列做分词,然后形成的分词与记录 ID 之间的映射关系。


比如电商项目有以下记录:



将商品名称做分词,然后建立起分词和商品 ID 的对应关系:



用户搜索电冰箱,就可以给他展示商品 ID 为 1 和 3 的两件商品。


而 Elasticsearch 提供了分布式的全文搜索服务,这在传统的关系型数据库中使用 SQL 语句是很难实现。所以 NoSQL 可以在某些业务场景下代替传统数据库提供数据存储服务。


提升扩展性




电商系统增加评论系统,评估比较乐观,觉得电商系统评论量级不会增长很快,就简单分了 8 个库,每个库分 16 张表。


但是评论系统上线之后,存储量级增长异常迅猛,不得不拆分更多库表,而数据也要重新迁移到新库表。


这时,你考虑是否可以考虑使用 NoSQL 数据库来彻底解决扩展性的问题,经过调研你发现它们在设计之初就考虑到了分布式和大数据存储的场景,比如像 MongoDB 就有三个扩展性方面的特性。

Replica

副本集,可理解为主从分离,也就是通过将数据拷贝成多份来保证当主挂掉后数据不会丢失。同时呢,Replica 还可以分担读请求。Replica 中有主节点来承担写请求,并且把对数据变动记录到 oplog 里(类似于 binlog);从节点接收到 oplog 后就会修改自身的数据以保持和主节点的一致。一旦主节点挂掉,MongoDB 会从从节点中选取一个节点成为主节点,可以继续提供写数据服务。

Shard

分片,分库分表,即将数据按照某种规则拆分成多份,存储在不同的机器上。MongoDB 的 Sharding 特性一般需要三个角色来支持,一个是 Shard Server,它是实际存储数据的节点,是一个独立的 Mongod 进程;二是 Config Server,也是一组 Mongod 进程,主要存储一些元信息,比如说哪些分片存储了哪些数据等;最后是 Route Server,它不实际存储数据,仅仅作为路由使用,它从 Config Server 中获取元信息后,将请求路由到正确的 Shard Server 中。

负载均衡

当 MongoDB 发现 Shard 之间数据分布不均匀,会启动 Balance


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


r 进程对数据做重新的分配,最终让不同 Shard Server 的数据可以尽量的均衡。当我们的 Shard Server 存储空间不足需要扩容时,数据会自动被移动到新的 Shard Server 上,减少了数据迁移和验证的成本。

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
NoSQL到底怎么用?