MinIO分布式文件存儲(從入門到飛翔)
MinIO簡介與核心優(yōu)勢
MinIO是一款高性能的分布式對象存儲系統(tǒng),專為云原生環(huán)境設(shè)計,兼容Amazon S3協(xié)議。其核心優(yōu)勢在于輕量級、易部署、高可用以及可擴展性。無論是單機測試環(huán)境,還是多節(jié)點分布式集群,MinIO都能通過**糾刪碼(Erasure Coding)**技術(shù)實現(xiàn)數(shù)據(jù)冗余與高容錯性,確保數(shù)據(jù)持久化。對于開發(fā)者而言,MinIO可作為私有云存儲、大數(shù)據(jù)分析存儲層或靜態(tài)資源托管服務(wù)的理想選擇。
0、前言
對象存儲是一種數(shù)據(jù)存儲架構(gòu),設(shè)計用于管理和處理大量非結(jié)構(gòu)化數(shù)據(jù)。與傳統(tǒng)的文件存儲和塊存儲不同,對象存儲通過將數(shù)據(jù)分解為離散的、獨立的單元或“對象”來存儲每個對象包含數(shù)據(jù)本身、相關(guān)的元數(shù)據(jù)和一個唯一的標識符。
對象存儲對比:
存儲方式
優(yōu)點
缺點
服務(wù)器磁盤
開發(fā)便捷,成本低
擴展困難
分布式文件系統(tǒng)
容易實現(xiàn)擴容
復雜度高
第三方存儲
開發(fā)簡單,功能強大,免維護
收費
1、分布式文件系統(tǒng)
分布式文件系統(tǒng)(Distributed File System, DFS)是一種文件系統(tǒng),它使文件可以跨越多個服務(wù)器或存儲設(shè)備存儲和訪問。DFS 通過網(wǎng)絡(luò)將多個存儲資源組合成一個統(tǒng)一的文件系統(tǒng),使用戶和應(yīng)用程序可以像訪問本地文件一樣透明地訪問遠程文件。
分布式文件系統(tǒng)的關(guān)鍵特性:
- 透明性:用戶和應(yīng)用程序可以像訪問本地文件一樣訪問遠程文件,感受不到底層的復雜性。
- 高可用性:通過復制和冗余機制,確保即使某些節(jié)點或硬件發(fā)生故障,數(shù)據(jù)仍然可用。
- 可擴展性:能夠處理隨著數(shù)據(jù)量和用戶數(shù)增加而增長的需求。
- 容錯性:通過數(shù)據(jù)冗余和錯誤檢測機制,保證系統(tǒng)能繼續(xù)運行,即使發(fā)生部分硬件或網(wǎng)絡(luò)故障。
- 性能:通過分布式架構(gòu),能夠有效地處理大量并發(fā)訪問請求。
2、MinIO 介紹
MinIO 是一個高性能的分布式對象存儲系統(tǒng),兼容 Amazon S3 云存儲服務(wù),Min10基于Apache License v2.0開源協(xié)議的對象存儲服務(wù),可以做為云存儲的解決方案用來保存海量的圖片,視頻,文檔。它專為大規(guī)模存儲基礎(chǔ)設(shè)施設(shè)計,能夠高效地存儲海量非結(jié)構(gòu)化數(shù)據(jù),如圖片、視頻、日志文件等。MinIO 提供了一組簡單的 API,用戶可以方便地進行數(shù)據(jù)存儲和管理。
MinIO 的關(guān)鍵特性
兼容性:
- 完全兼容 Amazon S3 API,使用戶可以使用現(xiàn)有的 S3 客戶端和工具。
高性能:
- 設(shè)計為高性能對象存儲系統(tǒng),能夠支持每秒數(shù)十GB的數(shù)據(jù)吞吐量。
可擴展性:
- 支持橫向擴展,允許用戶通過添加更多的存儲節(jié)點來擴展存儲容量和性能。
簡易部署:
- 提供簡單的安裝和配置過程,可以在幾分鐘內(nèi)啟動和運行。
數(shù)據(jù)保護:
- 通過糾刪碼(Erasure Coding)和位衰減(Bit Rot)保護機制確保數(shù)據(jù)完整性和持久性。
多租戶支持:
- 支持多用戶和多租戶環(huán)境,提供隔離和權(quán)限管理。
Kubernetes 集成:
- 提供原生的 Kubernetes Operator,方便在 Kubernetes 集群中部署和管理 MinIO。
3、 MinIO安裝(docker)
如果你有 Docker 環(huán)境,可以通過以下命令快速拉取并運行 MinIO 容器:
拉取鏡像
docker pull minio/minio
創(chuàng)建容器
docker run -p 9000:9000 --name minio -d --restart=always -e "MINIO_ACCESS_KEY=minio" -e "MINIO_SECRET_KEY=minio123" -v /home/data:/data -v /home/config:/root/.minio minio/minio server /data
訪問minio系統(tǒng):
http://<your_server_ip>:9000
如:http://192.168.200.130:9000
4、基本概念
- bucket – 類比于文件系統(tǒng)的目錄
- Object – 類比文件系統(tǒng)的文件
- Keys – 類比文件名
5、通過代碼上傳文件到MinIO
新建項目,導入pom文件
<dependencies> <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>7.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>com.heima</groupId> <artifactId>heima-file-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
創(chuàng)建test測試文件
package com.heima.minio.test; import com.heima.file.service.FileStorageService; import io.minio.MinioClient; import io.minio.PutObjectArgs; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.io.FileInputStream; import java.io.FileNotFoundException; public class MinIOTest { public static void main(String[] args) { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream("E:\list.html");; //1.創(chuàng)建minio鏈接客戶端 MinioClient minioClient = MinioClient.builder().credentials("minio", "minio123").endpoint("http://192.168.200.130:9000").build(); //2.上傳 PutObjectArgs putObjectArgs = PutObjectArgs.builder() .object("list.html")//文件名 .contentType("text/html")//文件類型 .bucket("leadnews")//桶名詞 與minio創(chuàng)建的名詞一致 .stream(fileInputStream, fileInputStream.available(), -1) //文件流 .build(); minioClient.putObject(putObjectArgs); System.out.println("http://192.168.200.130:9000/leadnews/list.html"); } catch (Exception ex) { ex.printStackTrace(); } } }
上傳文件,點擊控制臺連接即可訪問list.html文件
若不能訪問,在minio控制系統(tǒng)中,打開訪問權(quán)限
6、封裝MinIO為starter
在項目中封裝:
導入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>7.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
添加minio配置文件
package com.heima.file.config; import com.heima.file.service.FileStorageService; import io.minio.MinioClient; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Data @Configuration @EnableConfigurationProperties({MinIOConfigProperties.class}) //當引入FileStorageService接口時 @ConditionalOnClass(FileStorageService.class) public class MinIOConfig { @Autowired private MinIOConfigProperties minIOConfigProperties; @Bean public MinioClient buildMinioClient() { return MinioClient .builder() .credentials(minIOConfigProperties.getAccessKey(), minIOConfigProperties.getSecretKey()) .endpoint(minIOConfigProperties.getEndpoint()) .build(); } }
在spring管理的bean中注入MinIOFileStorageService(在spring.factories中)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.heima.file.service.impl.MinIOFileStorageService
MinIOFileStorageService文件詳情(大概就實現(xiàn)了對于文件資源上傳的操作)
package com.heima.file.service.impl; import com.heima.file.config.MinIOConfig; import com.heima.file.config.MinIOConfigProperties; import com.heima.file.service.FileStorageService; import io.minio.GetObjectArgs; import io.minio.MinioClient; import io.minio.PutObjectArgs; import io.minio.RemoveObjectArgs; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Import; import org.springframework.util.StringUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.Date; @Slf4j @EnableConfigurationProperties(MinIOConfigProperties.class) @Import(MinIOConfig.class) public class MinIOFileStorageService implements FileStorageService { @Autowired private MinioClient minioClient; @Autowired private MinIOConfigProperties minIOConfigProperties; private final static String separator = "/"; /** * @param dirPath * @param filename yyyy/mm/dd/file.jpg * @return */ public String builderFilePath(String dirPath,String filename) { StringBuilder stringBuilder = new StringBuilder(50); if(!StringUtils.isEmpty(dirPath)){ stringBuilder.append(dirPath).append(separator); } SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); String todayStr = sdf.format(new Date()); stringBuilder.append(todayStr).append(separator); stringBuilder.append(filename); return stringBuilder.toString(); } /** * 上傳圖片文件 * @param prefix 文件前綴 * @param filename 文件名 * @param inputStream 文件流 * @return 文件全路徑 */ @Override public String uploadImgFile(String prefix, String filename,InputStream inputStream) { String filePath = builderFilePath(prefix, filename); try { PutObjectArgs putObjectArgs = PutObjectArgs.builder() .object(filePath) .contentType("image/jpg") .bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1) .build(); minioClient.putObject(putObjectArgs); StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath()); urlPath.append(separator+minIOConfigProperties.getBucket()); urlPath.append(separator); urlPath.append(filePath); return urlPath.toString(); }catch (Exception ex){ log.error("minio put file error.",ex); throw new RuntimeException("上傳文件失敗"); } } /** * 上傳html文件 * @param prefix 文件前綴 * @param filename 文件名 * @param inputStream 文件流 * @return 文件全路徑 */ @Override public String uploadHtmlFile(String prefix, String filename,InputStream inputStream) { String filePath = builderFilePath(prefix, filename); try { PutObjectArgs putObjectArgs = PutObjectArgs.builder() .object(filePath) .contentType("text/html") .bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1) .build(); minioClient.putObject(putObjectArgs); StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath()); urlPath.append(separator+minIOConfigProperties.getBucket()); urlPath.append(separator); urlPath.append(filePath); return urlPath.toString(); }catch (Exception ex){ log.error("minio put file error.",ex); ex.printStackTrace(); throw new RuntimeException("上傳文件失敗"); } } /** * 刪除文件 * @param pathUrl 文件全路徑 */ @Override public void delete(String pathUrl) { String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/",""); int index = key.indexOf(separator); String bucket = key.substring(0,index); String filePath = key.substring(index+1); // 刪除Objects RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(filePath).build(); try { minioClient.removeObject(removeObjectArgs); } catch (Exception e) { log.error("minio remove file error. pathUrl:{}",pathUrl); e.printStackTrace(); } } /** * 下載文件 * @param pathUrl 文件全路徑 * @return 文件流 * */ @Override public byte[] downLoadFile(String pathUrl) { String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/",""); int index = key.indexOf(separator); String bucket = key.substring(0,index); String filePath = key.substring(index+1); InputStream inputStream = null; try { inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minIOConfigProperties.getBucket()).object(filePath).build()); } catch (Exception e) { log.error("minio down file error. pathUrl:{}",pathUrl); e.printStackTrace(); } ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buff = new byte[100]; int rc = 0; while (true) { try { if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break; } catch (IOException e) { e.printStackTrace(); } byteArrayOutputStream.write(buff, 0, rc); } return byteArrayOutputStream.toByteArray(); } }
具體模塊下載:
7、在其他項目中集成封裝好的模塊
在第5步創(chuàng)建的項目中進行測試使用:
導入文件管理依賴(自己封裝好的,第6步的模塊)
<dependency> <groupId>com.heima</groupId> <artifactId>heima-file-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
添加minio配置文件(application.yml文件中)
minio: accessKey: minio secretKey: minio123 bucket: leadnews endpoint: http://192.168.200.130:9000 readPath: http://192.168.200.130:9000
在spring管理的bean中注入FileStorageService
package com.heima.minio.test; import com.heima.file.service.FileStorageService; import io.minio.MinioClient; import io.minio.PutObjectArgs; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.io.FileInputStream; import java.io.FileNotFoundException; @SpringBootTest( classes = MinIOApplication.class) @RunWith(SpringRunner.class) public class MinIOTest { public static void main(String[] args) { @Autowired private FileStorageService fileStorageService; @Test public void testUpdateImgFile() { try { FileInputStream fileInputStream = new FileInputStream("E:\test.jpg"); String filePath = fileStorageService.uploadImgFile("", "test.jpg", fileInputStream); System.out.println(filePath); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
查看上傳
到此這篇關(guān)于MinIO分布式文件存儲(從入門到飛翔)的文章就介紹到這了,更多相關(guān)MinIO文件存儲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
kubernetes k8s 存儲動態(tài)掛載配置詳解
這篇文章主要為大家介紹了kubernetes k8s 存儲動態(tài)掛載配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11基于云服務(wù)MRS構(gòu)建DolphinScheduler2調(diào)度系統(tǒng)的案例詳解
這篇文章主要介紹了基于云服務(wù)MRS構(gòu)建DolphinScheduler2調(diào)度系統(tǒng),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05Istio 自動注入 sidecar 失敗導致無法訪問webhook服務(wù)的解決方法
最近工作中在部署Istio環(huán)境的過程中發(fā)現(xiàn)官方示例啟動的pod不能訪問不到Istio的webhook,這個問題也是困擾了我一天,我把他歸類到sidecar注入失敗的情況下,本文給大家分享問題解決方法,感興趣的朋友跟隨小編一起看看吧2023-10-10一文解析Kubernetes使用PVC后數(shù)據(jù)丟失
這篇文章主要為大家介紹了Kubernetes使用PVC后數(shù)據(jù)丟失原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03