一、Minio介绍
Minio 是在 GNU Affero 通用公共许可证 v3.0 下发布的高性能对象存储。 它是与 Amazon S3 云存储服务兼容的 API。 非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
Minio是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
2、数据存储方式
Minio使用纠删码erasure code和校验码checksum。
纠删码是一种恢复丢失和损坏数据的数学算法, Minio采用Reed-Solomon code将对象拆分成N/2数据和N/2 奇偶校验块。 这就意味着如果是12块盘,一个对象会被 分成6个数据块、6个奇偶校验块,你可以丢失任意6块盘(不管其是存放的数据块还 是奇偶校验块),你仍可以从剩下的盘中的数据进行恢复
此种纠删码的数据恢复方式是对象级别的,恢复效率更高,速度更快。能够更好的提高性能和尽可能的使用硬件加速。
3、数据组织结构
对象:
类似于hash表中的表项:它的名字相当于关键字,它的内容相当于“值”。
桶:
是若干个对象的逻辑抽象,是盛装对象的容器。
租户:
用于隔离存储资源。在租户之下可以建立桶、存储对象。
用户:
在租户下面创建的用于访问不同桶的账号。可以使用MinIO提供的mc命令设置不用用户访问各个桶的权限。
在minio中支持多租户的访问模式
4、**minio的架构模式
minio是一个去中心化的无共享架构,,对象数据被打散存放在不同节点的多块硬盘,对外提供统一命名空间访问,并通过Web负载均衡器或DNS轮询(DNS round-robin)在各服务器之间实现负载均衡。
某个节点宕机后,并不会影响整体的使用,当宕机节点重启后,其他节点会自动重连此节点。
而统一的命名空间,决定了无论访问那一个节点,均可以采用一样的数据访问方式。
且文件自带分布式锁的管理,当获取n/2+1个节点的回应为“是”后,才能获取锁。(类似于读写锁,写锁仅能一个写入者获得)
5、**数据存储结构
文件存储于指定的bucket(桶)下,每个都会生成一个对象文件,其中包括了纠删文件和检查文件(用于存储和恢复文件信息)。同时集群会复制相关文件到各个节点的各个数据盘中。
文档地址
docs.minio.org.cn/docs/
docs.minio.org.cn/docs/master…
1、单机部署
1)下载及安装
wget
dl.min.io/server/mini…
chmod +x minio
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001"
//注:可直接使用./minio server /data启动
nohup ./minio server ./minio/data > /minio/data/minio.log 2>&1 &
2、集群部署
测试环境集群地址:192.168.0.5:9000 192.168.0.6:9000
#导入配置,账号密码需要一致,所有节点的
export MINIO_ACCESS_KEY=minioadmin
export MINIO_SECRET_KEY=minioadmin
#每个节点都需要配置文件夹,且必须是空的,每个节点都得运行此命令,注意每个节点的minio版本得一致(加& 后台启动)
./minio server
http://192.168.0.5/home/minio/data6 http://192.168.0.5/home/minio/data7
http://192.168.0.5/home/minio/data1 http://192.168.0.5/home/minio/data8]http://192.168.0.5/home/minio/data2
http://192.168.0.5/home/minio/data9
http://192.168.0.6/home/minio/data6 http://192.168.0.6/home/minio/data7
http://192.168.0.5/home/minio/data1
http://192.168.0.6/home/minio/data8
http://192.168.0.5/home/minio/data2
http://192.168.0.6/home/minio/data9
> /home/minio/minio.log --console-address ":9001" 2>&1 &
在minio中,有几个概念:
1)account
这个会生成 access_key和secret_key 是用来调用minio接口的,无法使用api接口进行生成,且不可用此账户登录后台
2)user
用户信息,自己设定access_key和secret_key,可用于登录后台管理界面,可用于调用minio接口。此账户不可以用api接口生成
3)group
用户组,用户可以不设置权限,直接使用组权限,但不可以通过接口进行创建,也不能通过接口将用户加入用户组
4)buckets
桶,用于存储文件的一个分区。可以用api接口生成,且可修改策略,设置是否允许可读、可写。
user用户可与buckets绑定,用于操作此桶,user有自己设置的策略。
1、权限设置
1)每个app或者平台首先先申请minio平台的access_key和secret_key用于调用接口
2)根据登录的用户先查找自己是否有属于自己的buckets桶(用用户code+appcode做桶名),调用public boolean bucketExists(BucketExistsArgs args) 方法,判断桶是否存在,不存在就创建public void makeBucket(MakeBucketArgs args),其中objectLock表示桶是否私有
3)上传文件上传到自己的桶里面,不能放到别人的桶里。public ObjectWriteResponse putObject(PutObjectArgs args)
4)取文件:只能取自己的桶里的文件public GetObjectResponse getObject(GetObjectArgs args)
5)可以有一个系统账户的身份,可以取所有桶的文件
2、可以单独给桶设置策略
当操作的用户没有设置策略,且不属于某个组时,桶策略生效
用户的策略权限>组的策略权限>桶策略权限
3、用户不设置权限,组设置权限
给用户组设置权限,但是用户不单独设置读写策略,使用用户调用接口时,使用组的权限进行校验。
用户的策略权限>组的策略权限
1)public:文件可以直接用 ip:port/桶名/文件名 进行访问
2)private:文件需要通过minioClient.getPresignedObjectUrl接口获取一个有使用期限的地址,默认七天(最大七天)
3)可以通过装客户端应用,使用命令配置桶的权限:
./mc config host add minio
http://ip:port 【access_key】 【secret_key】
./mc policy set 【需要的权限,如download 下载 public 共有】 minio/【bucketName】 //设置需要开放下载的bucket, 注意需要带minio 浏览器访问, 注意不需要带minio
5、policy的内容格式
"Version"
:
"2012-10-17"
,
//版本,固定的版本
"Id"
:
"ExamplePolicy01"
,
//策略id
"Statement"
:[
//策略描述主体内容
"Sid"
:
"ExampleStatement01"
,
//描述id
"Effect"
:
"Allow"
,
//Allow允许 Deny禁止
"Principal"
:{
"AWS"
:
"arn:aws:iam::123456789012:user/Dave"
//被允许访问语句中的操作和资源的帐户或用户。在存储桶策略中,委托人是作为此权限接收者的用户、账户、服务或其他实体 格式:arn:aws:iam::
account-number-without-hyphens
:user/
username
"Action"
:[ //行为没操作
"s3:GetObject"
,//获取文件对象信息
"s3:PutObject",
//上传文件对象
"s3:DeleteObject",
//删除文件对象
"s3:ListBucketMultipartUploads",
//获取桶中所有的存储对象
"s3:ListMultipartUploadParts",
//获取桶中所有部分上传的存储对象
"s3:ListBucket"
//获取所有的存储桶
"Condition"
:{
//条件限制 StringEquals StringNotEquals StringLike StringNotLike IpAddress NotIpAddress
"IpAddress"
:{
"aws:SourceIp"
:
"192.0.2.0/24"
"NotIpAddress"
:{
"aws:SourceIp"
:
"192.0.2.188/32"
"Resource"
:[
"arn:aws:s3:::awsexamplebucket1/"
,
//资源arn:partition:service:region:namespace:relative-id 如例:操作awsexamplebucket桶中的对象资源
"arn:aws:s3:::awsexamplebucket1"
详细可参考:
docs.aws.amazon.com/AmazonS3/la…
四、实现方案设计
1、流程图
2、逻辑梳理
1)minio的用户权限和桶权限(策略)都是针对外部访问minio限定的,无法实际控制业务端的处理。此部分需要业务端自我完善,遂加表dy_file用于存储文件信息
2)每个平台(或应用)层级的创建两个桶,一个public桶,一个private桶。
公有桶里的文件通过:ip:port/文件名称 可以直接访问到
私有通的文件只能通过:presignedGetObject获取临时的访问地址,或者使用有权限的user进行下载访问
3)过大的文件,整体传递到服务端会消耗大量内存(如:2G的飞车apk安装包),但是可以通过presignedPutObject方法生成一个临时上传地址,客户端可使用这个地址直接访问minio服务进行上传,不经过服务端上传。
4)可以设置桶规则,限定此桶只能开放给那个用户使用(
"AWS"
:
"arn:aws:iam::123456789012:user/Dave"
),从而在后期,对外开放能力,使每个平台可以使用自己的账户进行维护文件信息。
1)用户上传文件,通过不同的接口标识上传的文件是上传到public桶还是private桶(桶名:平台code/应用code - public/private)
2)每个用户的文件在桶下建立一个文件夹,文件名为:用户code
3)上传完成后的文件统一返回文件code保存,若有特殊要求,可返回文件地址(私有的生成临时访问地址)
4、代码实现
1)创建minio客户端对象
MinioClient minioClient = MinioClient.builder().endpoint(server).credentials(accessKey, secretKey).build();
2)
判断桶是否存在
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketTemp).build());
3)
创建桶
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketTemp).objectLock(true).build());
4)
上传文件
minioClient.putObject(PutObjectArgs
.builder()
.bucket(bucketTemp)
.object("多层级的目录可以用这样的方式:first/second/"+newFileName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());
5)
下载文件
InputStream stream =
minioClient.getObject(
GetObjectArgs.builder()
.bucket("my-bucketname")
.object("my-objectname")
.offset(offset)
.length(len)
.ssec(ssec)
.build()
6)
设置桶策略
String config="{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["
"]},"Action":["s3:GetObject"],"Resource":["arn:aws:s3:::"+bucketsName+"/
"]}]}\n";
minioClient.setBucketPolicy( SetBucketPolicyArgs.builder().bucket(bucketsName).config(config).build());
7)
查询桶策略
String config = minioClient.getBucketPolicy(GetBucketPolicyArgs.builder().bucket(bucketsName).build());
8)
临时访问文件的地址
String url = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketsName)
.object(objectName)
.expiry(2, TimeUnit.DAYS)
.build());
9)
临时上传文件的地址
Map<String, String> reqParams = new HashMap<String, String>();
reqParams.put("response-content-type", "application/json");
String url = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.PUT)
.bucket(bucketsName)
.object(objectName)
.expiry(1, TimeUnit.DAYS)
.extraQueryParams(reqParams)
.build());
1、
桶名名称规则
l 存储桶名称的长度必须介于 3 到 63 个字符之间。
l 存储桶名称只能由小写字母、数字、点 (.) 和连字符 (-) 组成。
l 存储桶名称必须以字母或数字开头和结尾。
l 存储桶名称不得格式化为 IP 地址(例如,192.168.5.4)。
l 存储桶名称不得以前缀 开头xn--。
l 存储桶名称不得以后缀 结尾-s3alias。此后缀是为接入点别名保留的。有关更多信息,请参阅
为访问点使用存储桶式别名
。
l Bucket 名称在一个分区内必须是唯一的。分区是一组 Region。AWS 目前有三个分区:(aws标准区域)、 aws-cn(中国区域)和aws-us-gov(AWS GovCloud [美国] 区域)。
l 与 Amazon S3 Transfer Acceleration 一起使用的存储桶的名称中不能包含点 (.)
2、
遇到的问题
Q1:导入配置的方法
A1:使用export MINIO_ACCESS_KEY=<ACCESS_KEY export MINIO_SECRET_KEY=<SECRET_KEY> 命令可以设置默认的access_key和secret_key
在/root/.minio目录下,创建config.json的文件,内容为
"version": "10",
"aliases": {
"local": {
"url": "
http://localhost:9000
",
"accessKey": "",
"secretKey": "",
"api": "S3v4",
"path": "auto"
Q2:集群模式下的存储盘的创建
A2:在命令后面加&进行后台运行,但是集群运行时,需要每个盘都是空的,所以在外部创建一个同意的minio.log文件记录日志,这样每个盘都是空的,创建集群时不会报错
Q3:集群创建,不同节点之间连接不上
A3:当时两个节点的minio版本不一致,导致连接不上,重新下载后可连接
Q4:本地代码JVM内存不足,导致大文件(>1G时)本地无法完整的接取文件,导致JVM崩了
A4:可以使用接口生成一次性上传地址,这样可以直接从 客户端——>minio服务端进行文件传输,不用在经过业务服务端
Q5:桶策略、用户策略还有用户组策略的设置和生效优先级
A5:通过控制变量,设置不用权限的桶、用户、用户组得到结论:用户>用户组>桶策略
策略内容和设置基本一致,请参考policy的内容格式的内容
Q6:如何使部分文件可以直接对外访问,另外一部分有访问限制
A6:public属性策略的桶,可以直接使用服务的ip:port+文件地址访问 private的只能通过接口生成临时地址进行访问,最大有效期7天
Q7:断点续传和分片传输是否可以实现
A7:单个对象的最大大小限制在5TB。putObject在对象大于5MiB时,自动使用multiple parts方式上传。这样,当上传失败时,客户端只需要上传未成功的部分即可(类似断点上传)。
Q8:文件传输的大小和传输的速率
A8:单个文件最大可传输5TB的文件,功能强大。 效率:
通过接口传输:
5713ms(200M+的文件)
14608ms(450M+的文件)
客户端直接传输:
大概一分半钟(2GB文件)
Q9:文件存储格式及集群中的数据同步
A9:小文件只有一个xl.mate文件,包括了数据和纠偏码校验码 大文件会存在 数据片:part.1 和 xl.mate文件,且数据片被均分到不同的存储空间。在上传完文件后,集群个数据存储盘会同步相关数据,生成等分的校验块和数据块
且删除一般的内容后,数据正常访问,且可恢复(此处使用了8个盘,删除4个后,正常访问,删除5个后,文件无法访问)
Q10:设置minio的启动端口和后台端口
A10: --console-address=”:9001” 设置后台界面的端口 --address = “IP:PORT”设置访问端口
参考文章:
www.sohu.com/a/391960620…
blog.csdn.net/shijinghan1…