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; } });
參考: