分布式文件系統
什么是分布式文件系統
一個計算機無法存儲海量的文件,通過網絡將若干計算機組織起來共同去存儲海量的文件,去接收海量用戶的請求,這些組織起來的計算機通過網絡進行通信,如下圖:
好處:
1、一臺計算機的文件系統處理能力擴充到多臺計算機同時處理。
2、一臺計算機掛了還有另外副本計算機提供數據。
3、每臺計算機可以放在不同的地域,這樣用戶就可以就近訪問,提高訪問速度。
Minlo
介紹
MinIO構建分布式文件系統,MinIO 是一個非常輕量的服務,可以很簡單的和其他應用的結合使用,它兼容亞馬遜 S3 云存儲服務接口,非常適合于存儲大容量非結構化的數據,例如圖片、視頻、日志文件、備份數據和容器/虛擬機鏡像等。
它一大特點就是輕量,使用簡單,功能強大,支持各種平臺,單個文件最大5TB
,兼容 Amazon S3
接口,提供了 Java、Python、GO等多版本SDK支持。
官網:https://min.io
中文:https://www.minio.org.cn/,http://docs.minio.org.cn/docs/
MinIO集群采用去中心化共享架構,每個結點是對等關系,通過Nginx可對MinIO進行負載均衡訪問。
去中心化有什么好處?
在大數據領域,通常的設計理念都是無中心和分布式。Minio分布式模式可以幫助你搭建一個高可用的對象存儲服務,你可以使用這些存儲設備,而不用考慮其真實物理位置。
它將分布在不同服務器上的多塊硬盤組成一個對象存儲服務。由于硬盤分布在不同的節點上,分布式Minio避免了單點故障。如下圖:
Minio使用糾刪碼技術來保護數據,它是一種恢復丟失和損壞數據的數學算法,它將數據分塊冗余的分散存儲在各各節點的磁盤上,所有的可用磁盤組成一個集合,上圖由8塊硬盤組成一個集合,當上傳一個文件時會通過糾刪碼算法計算對文件進行分塊存儲,除了將文件本身分成4個數據塊,還會生成4個校驗塊,數據塊和校驗塊會分散的存儲在這8塊硬盤上。
使用糾刪碼的好處是即便丟失一半數量(N/2)的硬盤,仍然可以恢復數據。 比如上邊集合中有4個以內的硬盤損害仍可保證數據恢復,不影響上傳和下載,如果多于一半的硬盤壞了則無法恢復。
SDK
上傳文件
MinIO提供多個語言版本SDK的支持,下邊找到java版本的文檔:
地址:https://docs.min.io/docs/java-client-quickstart-guide.html
最低需求Java 1.8或更高版本:
maven依賴如下:
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.4.3</version>
</dependency>
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.8.1</version>
</dependency>
參數說明:
需要三個參數才能連接到minio服務。
參數 | 說明 |
---|---|
Endpoint | 對象存儲服務的URL |
Access Key | Access key就像用戶ID,可以唯一標識你的賬戶。 |
Secret Key | Secret key是你賬戶的密碼。 |
然后我們來看官方示例
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.UploadObjectArgs;
import io.minio.errors.MinioException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class FileUploader {public static void main(String[] args)throws IOException, NoSuchAlgorithmException, InvalidKeyException {try {// Create a minioClient with the MinIO server playground, its access key and secret key.MinioClient minioClient =MinioClient.builder().endpoint("https://play.min.io").credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG").build();// Make 'asiatrip' bucket if not exist.boolean found =minioClient.bucketExists(BucketExistsArgs.builder().bucket("asiatrip").build());if (!found) {// Make a new bucket called 'asiatrip'.minioClient.makeBucket(MakeBucketArgs.builder().bucket("asiatrip").build());} else {System.out.println("Bucket 'asiatrip' already exists.");}// Upload '/home/user/Photos/asiaphotos.zip' as object name 'asiaphotos-2015.zip' to bucket// 'asiatrip'.minioClient.uploadObject(UploadObjectArgs.builder().bucket("asiatrip").object("asiaphotos-2015.zip").filename("/home/user/Photos/asiaphotos.zip").build());System.out.println("'/home/user/Photos/asiaphotos.zip' is successfully uploaded as "+ "object 'asiaphotos-2015.zip' to bucket 'asiatrip'.");} catch (MinioException e) {System.out.println("Error occurred: " + e);System.out.println("HTTP trace: " + e.httpTrace());}}
}
那么基于這個我們來創建個測試類,測試是否能夠上傳文件
public class MinioTest {MinioClient minioClient =MinioClient.builder().endpoint("http://192.168.101.65:9001").credentials("minioadmin", "minioadmin").build();@Testpublic void test_upload() throws Exception{//上傳參數設置UploadObjectArgs testbucket = UploadObjectArgs.builder().bucket("testbucket") //桶.filename("F:\\BaiduNetdiskDownload\\2023新版JavaWeb開發教程\\視頻\\day01-HTML-CSS\\1.mp4") //指定本地文件路徑.object("test/01/1.mp4") //存放的文件名 放在子目錄下 直接寫文件名是放在根目錄下.build();//上傳文件minioClient.uploadObject(testbucket);}
}
注意這里我們需要在網頁控制臺設置桶,并給它改成公共屬性
然后我們運行測試樣例,看看是否上傳到我們的minio中
可以看到已經上傳到minio中了,我們可以點擊2進行預覽
刪除文件
然后我們來進行文件刪除測試
//刪除文件@Testpublic void test_delete() throws Exception{//刪除參數構建RemoveObjectArgs testbucket1 = RemoveObjectArgs.builder().bucket("testbucket").object("1.mp4").build();//上傳文件minioClient.removeObject(testbucket1);}
查詢文件
查詢文件的意思就是下載文件
//查詢文件@Testpublic void test_getFile() throws Exception{//根據擴展名取出mimeTypeContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4");String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;//通用mimeType,字節流if (extensionMatch!=null){mimeType = extensionMatch.getMimeType();}//查詢參數構建GetObjectArgs testbucket = GetObjectArgs.builder().bucket("testbucket").object("test/01/1.mp4").build();//下載文件 遠程流FilterInputStream inputStream = minioClient.getObject(testbucket);//指定輸出流 FileOutputStream outputStream = new FileOutputStream(new File("F:\\BaiduNetdiskDownload\\2023新版JavaWeb開發教程\\視頻\\day01-HTML-CSS\\2.mp4"));//拷貝到輸出流IoUtils.copy(inputStream,outputStream);}
這樣我們就可以從桶中下載文件下來,然后我們看是否成功
補充-文件校驗問題
我們在上傳和下載的時候由于分布式文件系統是基于網絡傳輸,萬一用戶正在處于網絡波動狀態,造成文件丟包,那么我們怎么判斷下載下來的內容和上傳上去的內容是否完整
這里沒找到以后補充,我沒搜索到資料
補充-拿取擴展名
一般情況,我們需要指定媒體文件的類型,那么我們怎么能知道要傳什么呢
可以參考這個源碼
這里面就有很么枚舉類型 例如我傳圖片
這些東西我們可以根據擴展名得到,所以可以調用工具類
設置contentType可以通過com.j256.simplemagic.ContentType枚舉類查看常用的mimeType(媒體類型)
<!--根據擴展名取mimetype--><dependency><groupId>com.j256.simplemagic</groupId><artifactId>simplemagic</artifactId><version>1.17</version></dependency>
//根據擴展名取出mimeTypeContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4");String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;//通用mimeType,字節流
那么我們就可以修改上傳文件的代碼來試一下
public void test_upload() throws Exception{//根據擴展名取出mimeTypeContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4");String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;//通用mimeType,字節流if (extensionMatch!=null){mimeType = extensionMatch.getMimeType();}//上傳參數設置UploadObjectArgs testbucket = UploadObjectArgs.builder().bucket("testbucket") //桶.filename("F:\\BaiduNetdiskDownload\\2023新版JavaWeb開發教程\\視頻\\day01-HTML-CSS\\1.mp4") //指定本地文件路徑.object("test/01/1.mp4") //存放的文件名 放在子目錄下 直接寫文件名是放在根目錄下.contentType(mimeType) //設置文件類型.build();//上傳文件minioClient.uploadObject(testbucket);}