1.Minio及背景
Minio是一個(gè)開(kāi)源的分布式文件存儲(chǔ)
系統(tǒng),它基于 Golang 編寫(xiě),雖然輕量,卻擁有著不錯(cuò)的高性能,可以將圖片、視頻、音樂(lè)、pdf這些文件存儲(chǔ)到多個(gè)主機(jī),可以存儲(chǔ)到多個(gè)Linux,或者多個(gè)Windows,或者多個(gè)Mac,Minio中存儲(chǔ)最大文件可以達(dá)到5TB
。任何類(lèi)型的文件都是支持
的,主要應(yīng)用在微服務(wù)
系統(tǒng)中。

1.使用Minio的背景
我們先回顧下,平時(shí)我們做文件存儲(chǔ)是普遍如何操作的,簡(jiǎn)單描述下步驟和時(shí)序,例如我們?cè)谔砑佑脩?hù)信息&上傳照片這個(gè)業(yè)務(wù)中,首先客戶(hù)端發(fā)起文件上傳
操作到API,服務(wù)將文件存儲(chǔ)到服務(wù)器本地文件夾中,生成返回一個(gè)文件摘要
,摘要包括路徑,文件ID
等一些基本信息,然后將這些摘要信息
和用戶(hù)業(yè)務(wù)數(shù)據(jù)
組裝程一個(gè)DTO,最終存儲(chǔ)到數(shù)據(jù)庫(kù)中。

此時(shí)我們只是一個(gè)單系統(tǒng)的上傳文件操作,無(wú)論是業(yè)務(wù)邏輯還是技術(shù)都比較簡(jiǎn)單,但是如果是一些分布式高并發(fā)和高訪問(wèn)量的電商網(wǎng)站面臨此類(lèi)業(yè)務(wù)應(yīng)該怎么做呢?一般電商類(lèi)都是幾十上百個(gè)微服務(wù)組成,如果按照單體系統(tǒng)的思路去實(shí)現(xiàn),如果有100個(gè)微服務(wù),那就存儲(chǔ)在100個(gè)地方,后期的維護(hù)量豈不是令人非常頭疼,加上事情做多錯(cuò)多,為了降低維護(hù)量,提升訪問(wèn)效率,我們需要將文件統(tǒng)一存儲(chǔ),基于MinIO高性能和可用性,我們選擇使用MinIO
來(lái)作為我們的文件管理中間件
,用它承載系統(tǒng)文件上傳下載。

2.MinIO實(shí)踐
我們先上手簡(jiǎn)單操作一下MinIO,先準(zhǔn)備環(huán)境,然后使用minio來(lái)進(jìn)行文件的上傳下載 ,首先我們需要下載MinIO,然后創(chuàng)建一個(gè)Api服務(wù)項(xiàng)目作為我們的文件微服務(wù)
。
1.Windows
瀏覽器在線下載MinIO和mc客戶(hù)端,官方文檔地址
2.Linux
直接創(chuàng)建對(duì)應(yīng)目錄輸入下載命令或者下到本地拷貝進(jìn)去,也可以使用Docker
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
./minio server ./data
3.準(zhǔn)備一個(gè)Api服務(wù)作為文件微服務(wù)
說(shuō)白了就是使創(chuàng)建一個(gè)控制器,訪問(wèn)這個(gè)控制器進(jìn)行文件操作,然后Nuget引入操作的Minio
包
4.創(chuàng)建一個(gè)FileUploadControll
控制器來(lái)作為我們的接口,此處只演示簡(jiǎn)單的上傳下載,當(dāng)然它還支持分片
和批量
以及拷貝
操作,具體的可以根據(jù)需要查看對(duì)應(yīng)的api,也比較簡(jiǎn)單
[ApiController]
[Route("[controller]")]
public class FileUploadController : ControllerBase
{
private readonly ILogger<FileUploadController> _logger;
public FileUploadController(ILogger<FileUploadController> logger)
{
_logger = logger;
}
[HttpPost("Upload")]
public IActionResult Upload(IFormFile formFile)
{
//1.創(chuàng)建MinioClient客戶(hù)端
MinioClient minioClient = new MinioClient("127.0.0.1:9000", "minioadmin", "minioadmin");
//2.創(chuàng)建文件桶(數(shù)據(jù)庫(kù))
if (!minioClient.BucketExistsAsync("micservice").Result)
{
minioClient.MakeBucketAsync("micservice").Wait();
}
//3.上傳文件(最大上傳5TB的數(shù)據(jù))
minioClient.PutObjectAsync("micservice", formFile.FileName, formFile.OpenReadStream(), formFile.Length).Wait();
_logger.LogInformation($"文件:{formFile.FileName}上傳到MinIO成功");
return new JsonResult("上傳文件成功");
}
[HttpGet("Download")]
public IActionResult Download(string fileName)
{
FileStreamResult fileStreamResult = null;
try
{
// 1、創(chuàng)建MioIO客戶(hù)端
MinioClient minioClient = new MinioClient("127.0.0.1:9000", "minioadmin", "minioadmin");
var imgStream = new MemoryStream();
// 2、下載圖片
minioClient.GetObjectAsync("micservice", fileName, stream => stream.CopyTo(imgStream)).Wait();
imgStream.Position = 0;
fileStreamResult = new FileStreamResult(imgStream, "image/jpg");
}
catch (MinioException e)
{
_logger.LogInformation($"文件:{fileName}下載失敗");
}
return fileStreamResult;
}
}
3.現(xiàn)在需要啟動(dòng)我們的Minio服務(wù),進(jìn)入
到我們的下載目錄
Linux一樣,然后啟動(dòng)命令行工具
minin.exe server ./data

我們啟動(dòng)后控制臺(tái)會(huì)輸出如下信息,首先第一部分中是我們和Minio,進(jìn)程通信的服務(wù)地址
和用戶(hù)名密碼
API: http://192.168.0.102:9000 http://127.0.0.1:9000
RootUser: minioadmin
RootPass: minioadmin
第二部分就是minio提供給我們查看和運(yùn)維的可視化界面,包含地址和用戶(hù)名密碼,密碼賬號(hào)是支持修改的
Console: http://192.168.0.102:52429 http://127.0.0.1:52429
RootUser: minioadmin
RootPass: minioadmin
3.MinIO文件高可用
在MinIO中目前我們上傳的文件存儲(chǔ)在服務(wù)器的磁盤(pán)中,我們?cè)趩?dòng)時(shí)默認(rèn)創(chuàng)建了一個(gè)目錄來(lái)存儲(chǔ)文件bucket(文件桶,理解為存儲(chǔ)文件的容器)
,這時(shí)如果刪除
了目錄中的文件
,可想而知會(huì)發(fā)生什么
,所以保證文件高可用
首要需求就是防止誤刪
引發(fā)的數(shù)據(jù)丟失,直接導(dǎo)致用戶(hù)使用文件失效。
1.常用的部署架構(gòu)
在進(jìn)行MInio文件高可用
應(yīng)對(duì)策略學(xué)習(xí)之前,我們先了解下保證系統(tǒng)和存儲(chǔ)高可用
層面的一些部署方式。
單機(jī)部署(stand-alone):只有一個(gè)服務(wù)實(shí)例提供服務(wù),服務(wù)只部署一份。
集群部署(cluster):有多個(gè)服務(wù)實(shí)例同時(shí)提供服務(wù),服務(wù)冗余部署,每個(gè)冗余的服務(wù)都對(duì)外提供服務(wù) 。
熱備部署(hot-swap):只有一個(gè)服務(wù)提供服務(wù),另一個(gè)服務(wù)stand-by,在服務(wù)掛掉時(shí)自動(dòng)熱替換。
服務(wù)冗余部署:只有一個(gè)主服務(wù)對(duì)外提供服務(wù),影子服務(wù)在主服務(wù)掛掉時(shí)頂上
磁盤(pán)陣列RAID(Redundant Arrays of independent Disks)
RAID0:存儲(chǔ)性能高的磁盤(pán)陣列,又稱(chēng)striping,它的原理是,將連續(xù)的數(shù)據(jù)分散到不同的磁盤(pán)上存儲(chǔ),這些不同的磁盤(pán)能同時(shí)并行存取數(shù)據(jù)
RAID1:安全性高的磁盤(pán)陣列,又稱(chēng)mirror,它的原理是,將數(shù)據(jù)完全復(fù)制到另一個(gè)磁盤(pán)上,磁盤(pán)空間利用率只有50%
RAID0+1:RAID0和RAID1的綜合方案,速度快,安全性又高,但是很貴,這也是國(guó)企用的比較多的存儲(chǔ)方案
RAID5:RAID0和RAID1的折衷方案,讀取速度比較快(不如RAID0,因?yàn)槎啻鎯?chǔ)了校驗(yàn)位),安全性也很高(可以利用校驗(yàn)位恢復(fù)數(shù)據(jù)),空間利用率也不錯(cuò)(不完全復(fù)制,只冗余校驗(yàn)位),這也是互聯(lián)網(wǎng)公司用的比較多的存儲(chǔ)方案
2.多副本
通常面對(duì)這種防止誤刪的問(wèn)題,我們使用的策略就是使用冗余
多個(gè)目錄來(lái)存儲(chǔ)多個(gè)副本文件,多副本技術(shù)比較簡(jiǎn)單直接,要冗余
保護(hù)關(guān)鍵數(shù)據(jù)
,就干脆多存幾份,單個(gè)數(shù)據(jù)的損壞不要緊,還有備份可以使用。同理多個(gè)目錄不行,加入多個(gè)主機(jī)來(lái)存儲(chǔ),這種做法在很多場(chǎng)景下適用。
但這種方法的優(yōu)缺點(diǎn)也比較明顯,優(yōu)點(diǎn)
是寫(xiě)入效率高,無(wú)需多余的計(jì)算,直接存多份即可,數(shù)據(jù)恢復(fù)快,從副本復(fù)制就好了。缺點(diǎn)
就是存儲(chǔ)效率低、占用空間以前需要的磁盤(pán)容量直接 X2 或者 X3 倍了,對(duì)于Minio來(lái)說(shuō),文件最大可以支持5TB,那如果按照這種做法對(duì)磁盤(pán)的消耗是巨大的,就成本方面
而言是不可行的,所以MinIO實(shí)現(xiàn)了另外一種保證文件高可用的機(jī)制,核心思想和集群方式差不多,但是對(duì)文件存儲(chǔ)的方式跟簡(jiǎn)副本拷貝不同,Minio使用了糾刪碼
的策略來(lái)保證我們的文件高可用。

但這種方法的優(yōu)缺點(diǎn)也比較明顯,優(yōu)點(diǎn)
是寫(xiě)入效率高,無(wú)需多余的計(jì)算,直接存多份即可,數(shù)據(jù)恢復(fù)快,從副本復(fù)制就好了。缺點(diǎn)
就是存儲(chǔ)效率低、占用空間以前需要的磁盤(pán)容量直接 X2 或者 X3 倍了,對(duì)于Minio來(lái)說(shuō),文件最大可以支持4個(gè)G,那如果按照這種做法對(duì)磁盤(pán)的消耗是巨大的,就成本方面
而言是不可行的,所以Minio實(shí)現(xiàn)了另外一種保證文件高可用的機(jī)制,核心思想和集群方式差不多,但是對(duì)文件存儲(chǔ)的方式跟簡(jiǎn)副本拷貝不同,Minio使用了糾刪碼
的策略來(lái)保證我們的文件高可用。
3.糾刪碼
在這里我們需要搞清楚的問(wèn)題有好幾個(gè),先列出來(lái)吧,當(dāng)然只是簡(jiǎn)單的介紹,具體深入還是需要自己去了解一下。
1.什么是RAID?
RAID中文簡(jiǎn)稱(chēng)為獨(dú)立磁盤(pán)冗余磁盤(pán)陣列。簡(jiǎn)單的說(shuō),RAID是一種把多塊獨(dú)立的物理硬盤(pán))按不同的方式組合起來(lái)形成一個(gè)硬盤(pán)組(邏輯硬盤(pán)),從而提供比單個(gè)硬盤(pán)更高的存儲(chǔ)性能和提供數(shù)據(jù)備份
技術(shù)。
2.什么是糾刪碼?
一種數(shù)據(jù)冗余保護(hù)技術(shù),RAID的延伸,糾刪碼不僅具備識(shí)別錯(cuò)碼和糾正錯(cuò)碼的功能,而且當(dāng)錯(cuò)碼超過(guò)糾正范圍時(shí)可把無(wú)法糾錯(cuò)的信息刪除。
我們使用一個(gè)簡(jiǎn)單的例子來(lái)理解糾刪碼
,首先從冗余思想來(lái)著手,假設(shè)我們?cè)诖鎯?chǔ)一份大小為2M的文件時(shí),按照4份副本冗余
的做法,占用的空間就是 2Mx4的空間,先將文件分片為2份,我們?nèi)∶麨?strong>Sharding1、Sharding2,然后再做冗余
就是4份數(shù)據(jù),如果我們刪除A1和A2那么A3和A4可以繼續(xù)組合成一個(gè)完整的文件,同理刪除A3和A4它依然可以組合成完整文件。

這時(shí)我們思考,如果我們同時(shí)刪除分片1的數(shù)據(jù)A1和A3,剩下A2和A4中都是分片2的數(shù)據(jù),不就組合不成了嗎?

此時(shí)如果使用糾刪碼的做法就是,A1和A2分片數(shù)據(jù)還是保持不變,A3=分片1+分片2,A4 = 分片1+ 2*分片2,這樣任意兩份數(shù)據(jù)丟失,都可以恢復(fù)出分片1 和 分片2的數(shù)據(jù)了

1.使用傳統(tǒng)副本冗余至少2個(gè)數(shù)據(jù)目錄,如果分片后就需要最少4份數(shù)據(jù)。
2.Minio按照最少分片2個(gè)的話,至少需要4個(gè)數(shù)據(jù)目錄,必須有一半數(shù)據(jù),數(shù)據(jù)不丟失,才能恢復(fù)(N/2)。
3.糾刪碼可以恢復(fù)任何磁盤(pán)損壞的數(shù)據(jù),包括人為刪除、磁盤(pán)信道丟失、磁盤(pán)中毒。
4.MinIO文件監(jiān)聽(tīng)及多租戶(hù)
1.文件監(jiān)聽(tīng)
有時(shí)我們想把客戶(hù)端上傳下載文件的一些操作,存儲(chǔ)起來(lái),方便以后做數(shù)據(jù)分析,最簡(jiǎn)單的做法我們可以使用寫(xiě)日志的方式,但是目前要做的不是介紹這種,而是使用MioIO自帶的文件監(jiān)聽(tīng)機(jī)制,MinIO允許我們配置存儲(chǔ)操作日志的存儲(chǔ)介質(zhì),例如Mysql、Redis、Elastic Search、Kafka、WebHook等等,MinIO可以設(shè)置對(duì)某一個(gè)Bucket實(shí)現(xiàn)事件監(jiān)聽(tīng)。
1.首先我們需要在Console中配置存儲(chǔ)介質(zhì),此處選擇 Mysql
1.在mysql中創(chuàng)建一個(gè)可供MinIO存儲(chǔ)操作的數(shù)據(jù)庫(kù)。
2.在MinIO中配置數(shù)據(jù)庫(kù)名稱(chēng)、表以及其他連接信息。

2.重啟MinIO服務(wù),并指定Console地址為9001,
minio server --address :9000 --console-address ":9001" ./data
重啟后控制臺(tái)會(huì)給出操作Mysql的隊(duì)列名arn:minio:sqs::_:mysql
3.啟動(dòng)MinIO自帶的命令客戶(hù)端mc.exe,給MinIO的Api地址取一個(gè)別名為minio_queue
,方便后續(xù)使用
mc.exe alias set minio_queue http://127.0.0.1:9000 minioadmin minioadmin
4.然后執(zhí)行客戶(hù)端命令。用于告訴MinIO服務(wù)將文件Bucket 和 Mysql隊(duì)列事件注冊(cè)綁定
下面命令的意思是對(duì)minio_queue服務(wù)中的micservice這個(gè)Bucket添加增、刪、改、查的監(jiān)聽(tīng)事件到arn:minio:sqs::_:mysql中,說(shuō)白了就是如果對(duì)這個(gè)桶中的文件進(jìn)行操作,那么就會(huì)寫(xiě)入日志到Mysql中
mc event add --event "put,delete" minio_queue/micservice arn:minio:sqs::_:mysql
2.MinIO多租戶(hù)
Minio默認(rèn)會(huì)給一個(gè)客戶(hù)使用,當(dāng)客戶(hù)變多了之后,所有客戶(hù)的數(shù)據(jù)都集中在Minio內(nèi)部的時(shí)候,導(dǎo)致數(shù)據(jù)沖突的問(wèn)題。例如客戶(hù)A的數(shù)據(jù),可能會(huì)修改成客戶(hù)B的數(shù)據(jù),客戶(hù)B可能查詢(xún)客戶(hù)C的數(shù)據(jù)。所以解決客戶(hù)數(shù)據(jù)沖突問(wèn)題,我們采用多租戶(hù)來(lái)實(shí)現(xiàn),說(shuō)白了就是系統(tǒng)運(yùn)行多個(gè)實(shí)例給多個(gè)不同的客戶(hù)使用,為不同的客戶(hù)端提供服務(wù)。

執(zhí)行如下命令,創(chuàng)建3個(gè)minio實(shí)例,為三個(gè)不同租戶(hù)提供服務(wù)
minio server --address :8001 --console-address ":9001" ./MinIO/tenant1
minio server --address :8002 --console-address ":9001" ./MinIO/tenant2
minio server --address :8003 --console-address ":9001" ./MinIO/tenant3
?轉(zhuǎn)自https://www.cnblogs.com/yuxl01/p/16226701.html
該文章在 2025/8/1 10:10:34 編輯過(guò)