告别慢速Java I/O,顺序和随机读写磁盘

共 8204字,需浏览 17分钟

 ·

2024-11-30 20:14

你知道的越多,不知道的就越多,业余的像一棵小草!

你来,我们一起精进!你不来,我和你的竞争对手一起精进!

编辑:业余草

来源:juejin.cn/post/7247044423023673404

推荐:https://t.zsxq.com/h35nK

Java 生态中有很多非常优秀的框架,它们实现了高效的 io 读写。其中用的比较多的就是顺序读写。今天,我们稍微花一点时间,来学习学习 Java 中的一些高效 io 读写知识。

什么是磁盘顺序写?

  • 磁盘顺序写是将数据按顺序依次写入磁盘的过程,也就是将数据块从内存直接传输到磁盘上相邻的物理位置。在磁盘顺序写的过程中,磁盘驱动器可以高效地预读下一个数据块,提高磁盘读写效率,降低磁盘寻道和旋转延迟对IO性能的影响。
  • 磁盘顺序写的优点在于能够使磁盘将数据集中写入,减少了寻道操作和磁盘旋转的等待时间,进而提高磁盘 IO 的效率。因此,磁盘顺序写在处理大量数据的时候表现优异,尤其适用于批处理任务等数据量较大、需要顺序写入的场景。

什么是磁盘随机写?

  • 磁盘随机写指的是将数据随机地写入磁盘的过程,即将数据块从内存传输到磁盘上不相邻的物理位置。磁盘随机写与磁盘顺序写相对应,磁盘随机写通常需要在磁盘上进行多次跳跃和定位操作,频繁改变磁头的位置,这使得磁盘的读写速度相对顺序写更慢。
  • 磁盘随机写主要应用于需要随机访问或修改数据的场景。例如,当应用程序需要快速地更新数据库的某个记录时,就需要进行磁盘随机写入操作。此时,磁盘的写入速度可能会影响整个应用程序的性能,因为随机写操作往往比较耗时,特别是在大规模数据集的情况下。

什么是磁盘顺序读?

  • 磁盘顺序读是指从磁盘上按照顺序读取数据块的过程,也就是将磁盘上相邻的物理位置的数据块依次读入内存
  • 在磁盘顺序读的过程中,磁盘驱动器可以进行预读,提高磁盘读取数据的效率,因为磁盘驱动器可以预测下一次要读取哪个数据块,并开始准备该数据块的读取,从而避免了磁盘寻道和旋转等待时间的影响。此外,磁盘顺序读可以有效缓解磁盘读取的瓶颈,提高磁盘 IO 的吞吐量。
  • 磁盘顺序读的应用场景非常广泛,尤其适合处理大数据量的工作负载,例如批量数据处理、日志分析等。同时,许多数据存储和处理系统都会采用磁盘阵列或者分布式存储等技术来提高磁盘 IO 吞吐量,进一步优化磁盘顺序读的性能。

什么是磁盘随机读?

  • 磁盘随机读是指从磁盘上按照随机顺序读取数据块的过程,也就是从磁盘中任意位置读取数据块
  • 与磁盘顺序读不同,磁盘随机读需要进行频繁的磁盘寻道和旋转等待操作,因为需要根据读取的数据块位置将磁头移动到正确的磁道位置,并等待磁盘旋转到正确的扇区位置才能读取数据。这些磁盘 IO 操作对系统性能会产生较大的影响,因此磁盘随机读的速度通常比磁盘顺序读慢得多。

java顺序写和随机写

顺序写

使用 Java 实现顺序写通常可以选择使用 FileWriter 和 BufferedWriter 等 I/O 流。其中,FileWriter 将文本内容写入文件,而 BufferedWriter 可以封装 FileWriter 实现更高效的写入操作。以下是一个简单的例子:

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class SequentialWriteExample {
    public static void main(String[] args) {
        String filePath = "test.txt";
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath))) {
            for (int i = 0; i < 100000; i++) {
                bw.write("Hello World " + i + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

随机写

使用 Java 实现随机写通常可以选择使用 RandomAccessFile 或者 FileChannel 等 I/O 流。下面提供一个使用 RandomAccessFile 的简单示例:

import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomWriteExample {
    public static void main(String[] args) {
        String filePath = "test.txt";
        try (RandomAccessFile raf = new RandomAccessFile(filePath, "rw")) {
            for (int i = 0; i < 10; i++) {
                raf.write(("Hello World " + i + "\n").getBytes());
            }
            //RandomAccessFile 的 seek 方法来随机定位文件中的位置,并向该位置进行写入操作
            raf.seek(5);
            raf.write("Java".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

顺序读

Java 实现顺序读通常可以选择使用 FileReader 和 BufferedReader 等 I/O 流。其中,FileReader 读取文本文件的内容,而 BufferedReader 可以封装 FileReader 实现更高效的读取操作。以下是一个简单的例子:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class SequentialReadExample {
    public static void main(String[] args) {
        String filePath = "test.txt";
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

随机读

使用 Java 实现随机读通常可以选择使用 RandomAccessFile 或者 FileChannel 等 I/O 流。下面提供一个使用 RandomAccessFile 的简单示例:

import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomReadExample {
    public static void main(String[] args) {
        String filePath = "test.txt";
        try (RandomAccessFile raf = new RandomAccessFile(filePath, "r")) {
            //RandomAccessFile 的 seek 方法来随机定位文件中的位置,并从该位置读取数据
            raf.seek(5);
            byte[] buffer = new byte[4];
            raf.read(buffer, 04);
            System.out.println(new String(buffer));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

总结

  1. 顺序读写通过按顺序读取或写入数据的方式进行操作,一般适用于处理大量数据的场景。在 Java 中,可以使用 FileReader、FileWriter、BufferedReader、BufferedWriter 等流进行顺序读写操作。
  2. 随机读写可以随意在文件中移动指针,并读取或写入指定位置的数据。适用于需要随机访问文件的场景。在 Java 中,可以使用 RandomAccessFile 或者 FileChannel 等流进行随机读写操作。

开源软件中的顺序写随机读模式

  1. Apache Kafka:Kafka 是一个分布式流处理平台,支持高吞吐量、低延迟等特点。Kafka 的生产者使用顺序写方式将消息写入指定分区的末尾,消费者则使用偏移量进行随机读取。
  2. Apache Hadoop:Hadoop 是一个分布式计算框架,包括 Hadoop MapReduce 和 Hadoop Distributed File System (HDFS)。其中,MapReduce 的结果以顺序写方式输出到文件系统中,而 HDFS 支持基于块的分布式文件存储,并且支持顺序写操作。
  3. Apache Flume:FileChannel组件既支持顺序写操作,又支持随机读操作,是一种顺序写、随机读的混合模式。
  4. Apache Parquet:Parquet 是一种列式存储格式,底层采用的是基于 HDFS 的分布式存储。Parquet 文件在写入时采用顺序写方式,同时也支持随机行读取和列读取。
  5. Apache ORC:ORC 也是一种列式存储格式,类似于 Parquet,底层采用基于 HDFS 的分布式存储。ORC 文件在写入时采用顺序写方式,同时也支持随机行读取和列读取。
  6. RocksDB:RocksDB 是一个快速的键值存储引擎,在写入时采用顺序写方式写入 SST 文件(Sorted String Table),同时支持根据键值进行随机读取。
  7. LevelDB:LevelDB 是一个高性能的键值存储引擎,底层采用类似 RocksDB 的 SST 文件格式。在写入数据时,LevelDB 也使用了顺序写操作,并支持基于键值的随机读取。总之,这些开源软件都采用了顺序写和随机读模式,利用了磁盘和内存的优势,具有高吞吐量、低延迟等优良特点,广泛应用于分布式计算、存储和消息传输等领域。

浏览 46
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报