Kafak采用内存映射文件、硬盘顺序写入技术提示性能。即使是顺序写入硬盘,硬盘的访问速度仍是不可能追上内存。因此Kafka的数据并不是实时的写入硬盘,html
它充分利用了现代操做系统分页存储来利用内存提升I/O效率。java
1、顺序写入ios
1. 机械硬盘app
机械硬盘的结构你能够想象成一个唱片机,它有一个旋转的盘片和一个能沿半径方向移动的磁头。处理读取和写入请求时,性能
2. 固态硬盘
java io操做中一般采用BufferedReader,BufferedInputStream等带缓冲的IO类处理大文件,不过java nio中引入MappedByteBuffer操做大文件的方式,其读写性能极高。this
File.read()将文件从硬盘拷贝到内核空间的一个缓冲区,再将这些数据拷贝到用户空间,实际上进行了两次数据拷贝。spa
FileChannal.map()直接将文件从硬盘拷贝到用户空间,只进行了一次数据拷贝。操作系统
1.code
public class MapMemeryBuffer { public static void main(String[] args) throws Exception { ByteBuffer byteBuf = ByteBuffer.allocate(14 * 1024 * 1024); byte[] bytes = new byte[14 * 1024 * 1024]; FileInputStream fis = new FileInputStream("d:\\java_transactions_book.pdf"); FileOutputStream fos = new FileOutputStream("d:\\java_transactions_book_copy.pdf"); FileChannel fileChannel = fis.getChannel(); long timeStar = System.currentTimeMillis(); // 读取 //fileChannel.read(byteBuf); MappedByteBuffer mbb = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size()); long timeEnd = System.currentTimeMillis(); System.out.println("Read time :" + (timeEnd - timeStar) + "ms"); timeStar = System.currentTimeMillis(); // 写入 //fos.write(bytes); // After a sequence of channel-read or put operations, // invoke this method to prepare for a sequence of channel-write or relative get operations. mbb.flip(); timeEnd = System.currentTimeMillis(); System.out.println("Write time :" + (timeEnd - timeStar) + "ms"); fos.flush(); fileChannel.close(); fis.close(); } }
2.注意htm
A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.
The content of a mapped byte buffer can change at any time, for example if the content of the corresponding region of the mapped file
is changed by this program or another. Whether or not such changes occur, and when they occur, is operating-system dependent and
therefore unspecified.
All or part of a mapped byte buffer may become inaccessible at any time, for example if the mapped file is truncated. An attempt to access an
inaccessible region of a mapped byte buffer will not change the buffer's content and will cause an unspecified exception to be thrown either at
the time of the access or at some later time. It is therefore strongly recommended that appropriate precautions be taken to avoid the manipulation
of a mapped file by this program, or by a concurrently running program, except to read or write the file's content.
Mapped byte buffers otherwise behave no differently than ordinary direct byte buffers.
解决:
AccessController.doPrivileged(newPrivilegedAction() { publicObject run() { try{ Method getCleanerMethod = buffer.getClass().getMethod("cleaner",newClass[0]); getCleanerMethod.setAccessible(true); sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod.invoke(byteBuffer,newObject[0]); cleaner.clean(); } catch(Exception e) { e.printStackTrace(); } returnnull; } });
参考: