MinIO 是一款高性能、分布式的对象存储系统。它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。MinIO 在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等 9000 多家企业也都在使用 MinIO 产品
本文链接:https://ddddddddd.top/archives/135
看官网的简介,是不是吹得很厉害,确实很厉害! 
1.MINIO 是什么
如果有同学用过阿里云的 OOS (Object Storage Service) 产品,或者腾讯云的 COS (Cloud Object Storage) 产品, 那么你将很快理解 MINIO 是什么,minio 能够提供的功能与 OOS 和 COS 无异~是一个开源的分布式对象文件存储系统。
1.1 为什么要用 minio?
我们平常接触的业务难免会有些文件上传下载的功能,如果公司有钱的话~那么可能就会去买大厂的产品,直接使用,这样的好处就是花钱买服务,也有售后,如果公司的资料文件很重要 (游戏策划素材、合同发票...),那么就可能不允许存储到外网之上,这个时候你或许会搞一台服务器,文件存到物理盘上,通过一些服务器(nginx)来实现上传 or 下载的功能,也不是不行,但肯定不好,例如你要考虑备份,容灾,性能... 等等一系列问题,这个时候你就可以选择使用 minio 来快速部署一个文件服务器来开发你的应用!
1.2 为什么要选择 minio?
首先肯定是开源免费,可以自己部署使用,其次呢社区活跃度也很高,毕竟东西好用~和其它开源的文件服务器 (fastDFS、MogileFS...) 对比来说,minio 用起来真的是很方便,仅需一点运维知识,就可以快速上手开发。
2. 部署前的准备
文件服务器搭建单机版的没有意思,我们直接搭建 4 个节点 (官网推荐最低 4 个) 4 块盘的集群。
2.1 环境准备
先准备四台服务器
192.168.152.128192.168.152.129192.168.152.130192.168.152.131
在每台服务器上都创建一个存储目录
root@machine1:~# mkdir /opt/data
使每台服务器都同步一下时间 我这里使用的是 ubuntu server 所以使用 apt 下载了 ntpdate 工具,按需更换
root@machine1:~# apt install ntpdateroot@machine1:~# ntpdate -u time.pool.aliyun.com
很重要的一点,分布式部署最好使用裸机部署,存储目录一定要求是空的
3. 开始部署
minio 提供了二进制、docker、k8s、源码方式部署。我这里就演示下二进制和 docker 的部署方式,其它的可以参考文末的链接自己部署一下。
3.1 二进制方式部署
个人习惯还是先从二进制部署,因为查问题比较方便~
以下步骤在四台服务器都要执行
下载二进制文件
root@machine1:~# wget http://dl.minio.org.cn/server/minio/release/linux-amd64/minio
给二进制文件授权
root@machine1:~# chmod +x minio
设置密钥
root@machine1:~# export MINIO_ACCESS_KEY=minioroot@machine1:~# export MINIO_SECRET_KEY=minio123456
做完上边三步之后,就可以通过一行命令启动了~ 很简单,server 后边跟着四台机器的存储盘目录就 OK 了~四台机器都要执行这串命令的。
root@machine1:~# ./minio server http://192.168.152.128/opt/data \http://192.168.152.129/opt/data \http://192.168.152.130/opt/data \http://192.168.152.131/opt/data
通过上边命令启动的话是前台启动的~我写了个脚本 启动方式可以变成这样 记得把二进制文件和脚本放在同级目录
root@machine1:~# ./minio.sh startroot@machine1:~# ./minio.sh stoproot@machine1:~# ./minio.sh restart
下载脚本:minio.sh 下载之后记得把里边的挂载目录修改一下~
WebConsole
minio 为我们提供了 web 页面,直接集成到了二进制文件中 启动之后你就会看到输出以下信息,
Waiting for all MinIO sub-systems to be initialized.. lock acquiredVerifying if 3 buckets are consistent across drives...All MinIO sub-systems initialized successfullyWaiting for all MinIO IAM sub-system to be initialized.. lock acquiredIAM initialization completeStatus: 4 Online, 0 Offline.Endpoint: http://192.168.152.128:9000 http://127.0.0.1:9000Browser Access:http://192.168.152.128:9000 http://127.0.0.1:9000Object API (Amazon S3 compatible):Go: https://docs.min.io/docs/golang-client-quickstart-guideJava: https://docs.min.io/docs/java-client-quickstart-guidePython: https://docs.min.io/docs/python-client-quickstart-guideJavaScript: https://docs.min.io/docs/javascript-client-quickstart-guide.NET: https://docs.min.io/docs/dotnet-client-quickstart-guide
随便复制一个节点的链接到浏览器中打开 非常简洁的登录界面~账号密码就是上边我们设置的密钥
主页也很简洁,通过右下角的按钮创建一个桶,便可直接上传文件
同时它还支持分享文件和预览
到这里我们就部署完成了~
3.2docker 部署
docker 部署,其实是单节点伪分布式部署的,节点挂了那整个分布式集群就挂了~当然它也可以多节点容器部署,不过我没去细看
下载 docker-compose.yaml
如果机器上没有 docker,是需要提前安装的。
root@machine1:~# wget https://raw.githubusercontent.com/minio/minio/master/docs/orchestration/docker-compose/docker-compose.yaml
修改配置
修改下载的配置文件,修改里边的挂载目录和密钥即可
root@machine1:~# vi docker-compose.yaml
拉取镜像
root@machine1:~# docker-compose pull
启动 minio
root@machine1:~# docker-compose up
启动之后 是和二进制启动之后一样的效果,挂载端口是 9000,页面访问就行了
4. 分布式存储
我们随便打开一个节点上传文件然后你去另外一个节点查看文件 你会发现每一个节点的控制台里都有这个文件,都可以进行查看 
去机器上看存储的目录 逆回发现每一个机器上都有这个文件 (目录) 
看下边这张图 数据对象在 MinIO 集群中进行存储时,先进行纠删分片,后打散存储在各硬盘上。具体为:MinIO 自动在集群内生成若干纠删组,每个纠删组包含一组硬盘,其数量通常为 4 至 16 块;对数据对象进行分片,默认策略是得到相同数量的数据分片和校验分片;而后通过哈希算法计算出该数据对象对应的纠删组,并将数据和校验分片存储至纠删组内的硬盘上。 
高可用 这个时候,即使你宕掉一台机器,仍然可以进行上传或者下载。
5. 数据恢复
如果其中一个节点 down 掉,那再启动的话,是不是这段时间内这台节点就没这个文件的数据了?实践出真理
5.1 关掉节点
们把 130 节点关掉 其它节点就会检测到 130 出现故障 这个时候我们可以通过接入 Prometheus 来监控告警 (后边会写个 Prometheus 的文章) 
5.2 上传文件
我们在 130down 掉的时候向集群中上传文件 
5.3 启动节点
重新启动 130 机器 可以发现,在宕机过程中上传的文件数据,自动恢复了~ 
4. 负载均衡
我们通过分布式部署集群后,会出现四台节点端口,我没找到官网给出的解释,但是当我宕掉其中一台,集群是正常的,但是我就无法使用这台的端口来进行服务,所以我们需要把这四台机器的端口做一下负载,应该另外起一台服务器来负载,我这里为了方便,直接在 128 机器上做负载了
4.1 配置 ngxin
配置一下 nginx.conf 的 http 内容
...http {upstream minio {server 192.168.152.128:9000;server 192.168.152.129:9000;server 192.168.152.130:9000;server 192.168.152.131:9000;}server {listen 80;server_name testminio.com;location / {# 反向代理地址,注意 /proxy_pass http://minio;}}}...
修改本地 host 有条件的直接域名解析,我这里就修改本地的 host 做下映射来验证下 参考文末
...# For example:## 102.54.94.97 rhino.acme.com # source server# 38.25.63.10 x.acme.com # x client host# localhost name resolution is handled within DNS itself.# 127.0.0.1 localhost# ::1 localhost192.168.152.128 testminio.com
这样就可以实现负载了,其中一个宕掉,也可以通过域名访问其它的服务 
5.Demo 开发
minio 提供了 js、java、go、python、.net、hs 的客户端 sdk 包,可以更快速的开发程序
我在这里就使用 go 来简单使用下 sdk,其它语言大家可以自己去看看,链接在文末
package mainimport ("github.com/minio/minio-go/v6""log""time")func main() {//endpoint := "testminio.com"endpoint := "192.168.152.128:9000"accessKeyID := "minio"secretAccessKey := "minio123456"useSSL := false// 初使化minio client对象。minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, useSSL)if err != nil {log.Fatalln(err)}log.Printf("初始化客户端 %s\n",minioClient)// 创建一个叫mymusic的存储桶。bucketName := "myapp"location := "cn-north-1"err = minioClient.MakeBucket(bucketName, location)if err != nil {// 检查存储桶是否已经存在。exists, err := minioClient.BucketExists(bucketName)if err == nil && exists {log.Printf("We already own %s\n", bucketName)} else {log.Fatalln(err)}}log.Printf("Successfully created %s\n", bucketName)// 上传一个zip文件。objectName := "ubuntu-20.04.2-live-server-amd64.iso"filePath := "D:\\install\\ubuntu-20.04.2-live-server-amd64.iso"contentType := ""// 使用FPutObject上传一个zip文件。log.Printf("开始上传 ")timeUnix:=time.Now().Unix()n, err := minioClient.FPutObject(bucketName, objectName, filePath, minio.PutObjectOptions{ContentType:contentType})if err != nil {log.Fatalln(err)}endTimeUnix:=time.Now().Unix()diff := endTimeUnix - timeUnixlog.Printf("Successfully uploaded %s of size %d time %d ", objectName, n,diff)log.Printf("开始下载 ")timeUnix=time.Now().Unix()err = minioClient.FGetObject("mymusic", objectName, "C:\\Users\\fangpengbo.101\\Desktop\\ubuntu-20.04.2-live-server-amd64.iso", minio.GetObjectOptions{})if err != nil {log.Fatalln(err)return}endTimeUnix=time.Now().Unix()diff = endTimeUnix - timeUnixlog.Printf("Successfully download %s of size %d time %d ", objectName, n,diff)}
这里我使用了 IP + 端口来进行创建客户端,因为使用域名的话需要 https 协议。可以看到,上传 1.13G 的文件,大概在 10s 以内,下载在 15s 左右。速度还是非常快的~
我们刷新下浏览器,就可以看到了。 
有兴趣的同学可以尝试使用下 minio~
参考资料
1. 部署 minio 2.host 解析 3.MINIO SDKS




