Minio 基本使用与原理
- 2022 年 4 月 22 日
本文字数:6326 字
阅读完需:约 21 分钟
@[toc]
一、MinIo 核心概念
概念分布式文件系统,简称为 OSS 对象存储【文件,图片.......】。如图:
二、MinIo 应用场景
应用场景主要是在微服务系统中使用。如图:
三、MinIo 项目落地
条件
Demo 项目
MinIO 下载地址:链接:https://pan.baidu.com/s/1x-xETi3hkmxbniJEFJkFyg 提取码:tbz9
步骤
Demo 项目
步骤
添加 Nuget 包
//添加 Nuget包
Minio
- 建立MinIo客户端连接
MinioClient minioClient = new MinioClient("Ip地址:端口号","用户名","密码");
- 创建文件桶
// 判断是否有文件桶
if(!minioClient.BucketExistsAsync("文件桶名称").Result)
{
minioClient.MakeBucketAsync("文件桶名称");
}
- 上传对象
minioClient.PutObjectAsync("文件桶名称",上传的文件名称,文件流,文件长度).Wait();
minioClient.PutObjectAsync("文件桶名称","上传的文件名称","文件路径【D://...路径到文件名称.后缀】").Wait();
//生成上传文件链接,返回一个生成文件的路径,需要后端系统中新建一个Access Key和Secret Key,才能使用,
//将客户端连接的用户名和密码改为Access Key和Secret Key,并设置读和写的权限
minioClient.PresignedPutObjectAsync("文件桶名称",上传的文件名称,过期时间【单位:秒】).Result;
如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/59852a2c8a464b75ae919d52566ebc9a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
- 下载对象
minioClient.GetObjectAsync("文件桶名称",文件名称,输出流地址).Wait();
minioClient.GetObjectAsync("文件桶名称",文件名称,从什么地方开始【0】,下载的长度,输出流地址).Wait();//分段下载对象
- 刪除对象
- 单个删除
minioClient.RemoveObjectAsync("文件桶名称", 对象名称.后缀);
- 多个删除
minioClient.RemoveObjectAsync("文件桶名称", 对象名称.后缀集合).Wait();
- 对象拷贝
minioClient.CopyObjectAsync("原文件桶名称", 源文件名称.后缀, "目的地文件桶名称", 新文件名称.后缀).Wait();
- 整体代码如下
- 文件上传
//文件上传
public IActionResult Upload(IFormFile fromFile)
{
//建立MinIo客户端连接
MinioClient minioClient = new MinioClient("127.0.0.1:9000","minioadmin","minioadmin");
// 判断是否有文件桶
if(!minioClient.BucketExistsAsync("test").Result)
{
minioClient.MakeBucketAsync("test");
}
//上传文件
minioClient.PutObjectAsync("test",fromFile.FileName,fromFile.OpenReadStream,fromFile.Length).Wait();
return Ok ("文件上传成功!");
}
- 文件上传链接生成【网站服务端不建议使用】
目的:MinIo 支持上传5TB的对象,但是网站不支持上传5TB对象,所以采用生成文件上传链接方式来解决,不建议使用网站服务端的方式来实现【网站服务端没有设置key和签名的api方法】,建议使用js直接连接MinIo客户端的方式来实现上传大文件。
新建Access Key 和Secret Key,并设置读和写的权限,如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/183a0c5163554934af6cc196d5bdff35.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
代码如下:
//文件上传
public IActionResult UploadBigFile(IFormFile fromFile)
{
//建立MinIo客户端连接
MinioClient minioClient = new MinioClient("127.0.0.1:9000","Access Key","Secret Key");
// 判断是否有文件桶
if(!minioClient.BucketExistsAsync("test").Result)
{
minioClient.MakeBucketAsync("test");
}
//生成大文件上传链接,返回一个文件上传路径
string Url = minioClient.PresignedPutObjectAsync("test",fromFile.FileName,60*60*24).Result;
return Ok ("文件路径生成成功!");
}
- 批量文件上传
public IActionResult Upload(IFormFile[] formFiles)
{
foreach (var formFile in formFiles)
{
//建立MinIo客户端连接
MinioClient minioClient = new MinioClient("127.0.0.1:9000", "minioadmin", "minioadmin");
// 判断是否有文件桶
if (!minioClient.BucketExistsAsync("test").Result)
{
minioClient.MakeBucketAsync("test");
}
//生成大文件上传链接,返回一个文件上传路径
minioClient.PutObjectAsync("test", formFile.FileName, formFile.OpenReadStream(), formFile.Length);
}
return Ok("文件上传成功!");
}
- 文件下载
- 单文件下载
//文件下载
public IActionResult DownLoad(string fileName)
{
FileStreamResult fileStreamResult = null;
try
{
//建立MinIo客户端连接
MinioClient minioClient = new MinioClient("127.0.0.1:9000","minioadmin","minioadmin");
var imaStream = new MemortStream()
//下载文件
minioClient.GetObjectAsync("test",fileName,stream=>{stream.CopyTo(imaStream)}).Wait();
imaStream.Position = 0;
//指定对象类型
fileStreamResult = new FileStreamResult(imaStream,"img/jpg");
}
catch(Exception ex)
{
}
return Ok ("文件下载成功!");
}
- 分段文件下载
//文件下载
public IActionResult DownLoadShard(string fileName)
{
FileStreamResult fileStreamResult = null;
try
{
//建立MinIo客户端连接
MinioClient minioClient = new MinioClient("127.0.0.1:9000","minioadmin","minioadmin");
var imaStream = new MemortStream()
//分段下载文件 注意: 数字是字节单位
minioClient.GetObjectAsync("test",fileName,0,100,stream=>{stream.CopyTo(imaStream)}).Wait();
minioClient.GetObjectAsync("test",fileName,101,1000,stream=>{stream.CopyTo(imaStream)}).Wait();
imaStream.Position = 0;
//指定对象类型
fileStreamResult = new FileStreamResult(imaStream,"img/jpg");
}
catch(Exception ex)
{
}
return Ok ("文件下载成功!");
}
- 删除文件
/// <summary>
/// 删除文件
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
[HttpDelete("{fileName}")]
public IActionResult DeleteFile(string fileName)
{
//建立MinIo客户端连接
MinioClient minioClient = new MinioClient("127.0.0.1:9000", "minioadmin", "minioadmin");
// 判断是否有文件桶
if (!minioClient.BucketExistsAsync("test").Result)
{
minioClient.MakeBucketAsync("test");
}
//生成大文件上传链接,返回一个文件上传路径
minioClient.RemoveObjectAsync("test", fileName);
return Ok("删除成功!");
}
- 批量删除文件
/// <summary>
/// 删除文件
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
[HttpDelete("DeleteBatchFile")]
public IActionResult DeleteBatchFile(string[] fileNames)
{
//建立MinIo客户端连接
MinioClient minioClient = new MinioClient("127.0.0.1:9000", "minioadmin", "minioadmin");
// 判断是否有文件桶
if (!minioClient.BucketExistsAsync("test").Result)
{
minioClient.MakeBucketAsync("test");
}
//生成大文件上传链接,返回一个文件上传路径
minioClient.RemoveObjectAsync("test", fileNames.ToList()).Wait();
return Ok("删除成功!");
}
- 拷贝文件
/// <summary>
/// 复制文件
/// </summary>
/// <param name="fileName">原始文件名称</param>
/// <param name="destFileName">复制的文件名称</param>
/// <returns></returns>
[HttpPost("FileCopy")]
public IActionResult FileCopy(string fileName,string destFileName)
{
MinioClient minioClient = new MinioClient("127.0.0.1:9000", "minioadmin", "minioadmin");
if (!minioClient.BucketExistsAsync("testnew").Result)
{
minioClient.MakeBucketAsync("testnew");
}
minioClient.CopyObjectAsync("test", fileName, "testnew", destFileName).Wait();
return Ok("复制成功!");
}
启动 MinIO
运行命令
#在根目录下执行命令启动
#minio.exe :服务启动命令
#server:是以服务端的方式启动
#--console-address ":9001":将动态端口改为静态端口
#D:\MinIo\data:数据目录
minio.exe server --console-address ":9001" D:\MinIo\data
执行结果如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/8af974ade5a84909a5d2d7e70c676ed5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
- 验证是否启动成功
访问 http://10.1.57.35:9001,如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/c4e0eaf959bb4935829e8083e7adfc71.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
四、MinIo 文件高可用
场景
如果文件误删后,如何实现文件的高可用性
步骤使用多个数据目录来存储。新建 4 个数据目录。
命令
minio.exe server --console-address ":9001" D:/Assembly/MinIo/data1 D:/Assembly/MinIo/data2 D:/Assembly/MinIo/data3 D:/Assembly/MinIo/data4
运行结果如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/f951804eb316470b8f7b5ea970a823d7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
纠删码
概念纠删码是一种数据保护方法,它将数据分割成片段,把冗余数据块扩展、编码,并将其存储在不同的位置,比如磁盘、存储节点或者其它地理位置,通俗的说就是一个数据编码而已。可以理解为将对象文件进行拆分,然后进行编码,防止任意两份数据丢失。
实现过程先将对象文件拆分成多份,进行编码(2 种编码:数据编码和扩展编码)。
目的降低对象文件的存储空间。
纠删码如何保证对象文件的恢复如图:
假如有一个文件对象,在 minIO 中会拆分成 A1 和 A2 两份相同的数据,再将数据存储为 X1、X2、X3、X4 数据文件中,让其分别等于 A1,A2,A1,A2;这样假设数据 X1 和 X2 数据丢失了,那么数据可以从 X3 和 X4 中恢复。但是这样存储会出现问题:如果数据 X1 和 X3 数据丢失了,那么原先的数据 A1 就彻底找回来了;但是可以使用下面的一种存储方式 X1 和 X2 还是不变,X3 = A1+A2;X4=A1+2*A2,这样任意两份数据丢失,都可以恢复 A1 和 A2 了,如图:
MinIo 使用纠删码 MinIo 的数据目录至少有四个,并且是偶数目录数。
规则四个数据目录中必须有一半数据目录数据不丢失才能恢复。
纠删码的特征可以恢复任何的损坏的数据,比如:误删除,磁盘损坏,磁盘中毒等。
五、MinIo 文件监听
工具
Mysql 数据库
MinIo
步骤 1、打开 MinIo 后台管理系统 2、点击 Setting 目录 3、点击 Notification 目录 4、点击 Add Notification Target 按钮 5、选择 Mysql 数据库或者其他数据库(前提是手动建好数据库),然后输入:数据库的 IP 地址,数据库名称,数据库端口号,数据库用户名和密码,数据库表名(可以不用手动新建);6、再点击保存 7、再次重新启动 MinIo8、关联文件桶并往队列中发送消息命令:
#在MinIo根目录下执行
#建立连接
mc.exe alias set 连接地址别名【随意起】 http://10.1.57.35:9000 minioadmin minioadmin
#监听单个关联文件桶
mc event add --event "put,delete" 连接地址别名/文件桶名称 arn:minio:sqs::_:mysql
如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/1faa7568def04ef096127c1f6365c326.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
实现原理在 MinIo 内部会有一个内存队列,通过队列发给数据库;Mino 相当于生产者--->MinIo 内部队列<---监听--Mysql 数据库(消费者)
六、MinIo 多租户
多个服务对应多个 MinIO 就是使用不同的端口,并且数据目录是不一样的才可以;
#在MinIo根目录下执行
#9002 Minio API连接端口号
#9003 MinIo后台管理系统端口号
#Window 环境中
minio.exe server --address :9002 --console-address ":9003" 数据目录 数据目录1
#Linux 环境中
#注意:在Linux系统中创建数据目录,有几个数据目录就得有几个磁盘才行
minio.exe server --address :9002 --console-address ":9003" 数据目录{1..4}
版权声明: 本文为 InfoQ 作者【神秘码农】的原创文章。
原文链接:【http://xie.infoq.cn/article/a5ca9003f20f65d443430c896】。未经作者许可,禁止转载。
神秘码农
还未添加个人签名 2022.03.14 加入
好好学习,天天向上!
评论