两招提升硬盘存储数据的写入效率

JSON 2022-06-16 10:27:57 5850

如今存储数据的方式有很多,而硬盘因为价格和数据保护方面的优势,是大部分用户的首选。但是,硬盘和内存相比在 IO 读写上慢了好几个数量级,那为什么会更偏好硬盘呢?

首先需要提到的是,操作磁盘之所以慢主要是因为对磁盘的读写耗时。读写主要有三部分耗时:寻道时间+旋转时间+传输时间,其中寻道时间是最久的。因为寻道需要移动磁头到对应的磁道上,通过马达驱动磁臂移动,是一种机械运动因此耗时较长。同时我们对磁盘的操作通常都是随机读写,也就需要频繁移动磁头到对应的磁道,这就让耗时延长了,显得性能比较低。

这样看来如果要让磁盘读写速度变快,只要不使用随机读写,或者减少随机的次数,就可以有效提升磁盘读写速度了。那具体要如何操作呢?

顺序读写

先来聊聊第一个方法,如何使用顺序读写,而不是随机读写?上面提到寻道时间是耗时最久的,所以最直观的思路就是省去这部分时间,而顺序 IO 正好可以满足需求。

追加写就是一种典型的顺序 IO,使用这个思路优化的典型的产品就是消息队列。以热门的 Kafka 为例,Kafka 为了实现高性能 IO,用了很多优化的方法,其中就使用了顺序写这种优化方法。


Kafka 以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 TB 级以上数据也能保证常数时间复杂度的访问性能。对于每个分区,它把从 Producer 收到的消息,顺序地写入对应的 log 文件中,一个文件写满后,才开启一个新的文件。消费的时候,也是从某个全局的位置开始,也就是某一个 log 文件中的某个位置开始,按顺序地读出消息。

减少随机次数

看完了顺序方式,我们再来看看减少随机写次数的方法。在很多场景中,为了方便我们后续对数据的读取和操作,我们要求写入硬盘的数据是有序的。比如在 MySQL 中,索引在 InnoDB 引擎中是以 B+ 树方式来组织的,而 MySQL 主键是聚簇索引(一种索引类型,数据与索引数据放在一起),既然数据和索引数据放在一起,那么在数据插入或者更新的时候,我们需要找到要插入的位置,再把数据写到特定的位置上,这就产生了随机的 IO。所以,如果我们每次插入、更新数据都把数据写入至 .ibd  文件的话,然后磁盘也要找到对应的那条记录,然后再更新,整个过程 IO 成本、查找成本都很高,数据库的性能和效率都会大打折扣。

为了解决写入性能问题,InnoDB 引入了 WAL 机制,更确切的说,就是 redo log。下面我再简单介绍下 Redo Log。

InnoDB redo log 是一个顺序写入的、大小固定的环形日志。主要作用有两个:

  • 提高 InnoDB 存储引擎写入数据的效率
  • 保证 crash-safe 能力

在这里我们只关心它是如何提高写入数据的效率的。下图是 redo log 的示意图。


从图中可以看出,red olog 的写入是顺序写入的,不需要找到某一个具体的索引位置,而是简单地从 write-pos 指针位置追加。

其次当一个写事务或者更新事务执行时,InnoDB 首先取出对应的 Page,然后进行修改。当事务提交时,将位于内存中的 redo log buffer 强制刷新至硬盘中,如果不考虑 binlog 的话,我们可以认为事务执行可以返回成功了,写入 DB 的操作由另外的线程异步进行。

再然后,可由 InnoDB 的 Master Thread 定时地将缓冲池中的脏页,也就是上面儿我们修改的页,刷新至磁盘,此时被修改数据真正的写入至 . ibd 文件。

总结

很多时候,我们不得不把数据存储到硬盘上,但是由于硬盘相对于内存来说实在是太“慢”了。所以我们就得想办法提升性能。文章里总结了两个方法,第一个是追加写,利用顺序 IO 来实现快速写;第二个是很多数据库中为了提升性能都会引入的 WAL 机制。文章里分别拿了 Kafka 和 MySQL 的 InnoDB 存储引擎举例。除了这两个,感兴趣的同学也可以看下 LSM 树,etcd 等是怎么实现快速写的。


文章来自又拍云投稿


版权所属:SO JSON在线解析

原文地址:https://www.sojson.com/blog/393.html

转载时必须以链接形式注明原始出处及本声明。

本文主题:

如果本文对你有帮助,那么请你赞助我,让我更有激情的写下去,帮助更多的人。

关于作者
一个低调而闷骚的男人。
相关文章
MySQL数据库存储过程字符集问题,乱码的解决办法
Elasticsearch Date类型,时间存储相关说明。
Java 集成阿里云消息队列,日志消息存储
SpringBoot 集成Spring-data-redis,redis对象序列化存储
使用七牛云存储实现图片API,自动删除图片方案合集
MySQL无法存储Emoji表情,IPhone表情问题 。
又拍云(Upyun)CDN、云存储刷新链接缓存,API实例讲解
又拍云(Upyun)刷新CDN,云存储缓存 —JavaAPI
恭喜那个做云存储的七牛云完成 F 轮 10 亿人民币的融资,开启新的云旅程
Oracle与Mysql删除重复的数据,Oracle和Mysql数据去重复
最新文章
PHP回显语句 36
Linux—文件树 83
C语言while循环和do while循环 127
Python元组剖析 151
MySQL触发器教程 262
sql使用布尔运算符和关系运算符 235
C语言的变量和常量 291
PHP变量剖析 193
SQL全外连接剖析 339
SQL自然连接剖析 223
最热文章
最新MyEclipse8.5注册码,有效期到2020年 (已经更新) 681687
苹果电脑Mac怎么恢复出厂系统?苹果系统怎么重装系统? 674703
免费天气API,全国天气 JSON API接口,可以获取五天的天气预报 601610
免费天气API,天气JSON API,不限次数获取十五天的天气预报 575081
Jackson 时间格式化,时间注解 @JsonFormat 用法、时差问题说明 552740
我为什么要选择RabbitMQ ,RabbitMQ简介,各种MQ选型对比 509309
Elasticsearch教程(四) elasticsearch head 插件安装和使用 479847
Jackson 美化输出JSON,优雅的输出JSON数据,格式化输出JSON数据... ... 264119
Java 信任所有SSL证书,HTTPS请求抛错,忽略证书请求完美解决 244246
Elasticsearch教程(一),全程直播(小白级别) 225502
支付扫码

所有赞助/开支都讲公开明细,用于网站维护:赞助名单查看

查看我的收藏

正在加载... ...