软件开发兼职网站,wordpress 多站点 用户,飞扬世纪网站建设,wordpress项目管理主题背景
上篇介绍了文件读写框架设计与实现#xff0c;同时顺便说明了本地磁盘存储模式的实现模式。 今天来说下基于文件读写框架#xff0c;如何集成对象存储组件minio#xff0c;集成之前#xff0c;需要对minio进行必要的了解#xff0c;本篇是minio的技术预研。
minio简…背景
上篇介绍了文件读写框架设计与实现同时顺便说明了本地磁盘存储模式的实现模式。 今天来说下基于文件读写框架如何集成对象存储组件minio集成之前需要对minio进行必要的了解本篇是minio的技术预研。
minio简介
minio是一套小而美的开源的对象存储系统Object Storage System简称OSS优点如下
支持存储海量非结构化数据单个文件从几十kb到最大5T不等性能高在标准硬件上读/写速度高达183GB/秒和171GB/秒完全兼容Amazon S3接口增配存储资源易于实现原有存储不变
基本概念
Object对象实际就是非结构化的文件如office文档、图片、音频、视频等。 Bucket桶是一个用来管理对象的逻辑空间称之为对象仓库更合适。其作用相当于磁盘上的一个顶级文件夹并且桶与桶之间的数据是相互隔离的。桶的意义在于可以更好地分门别类管理存储的对象避免把整个系统所有的文件一股脑都存放在一个仓库里可以从租户、业务模块、年度等维度进一步细分。 Drive磁盘实际就是底层存储了对应着磁盘或磁盘上的目录。 Set阵列磁盘的集合这地方我认为很多网上的资料实际都是错的或描述不完整不准确完整的说法应该是纠删阵列即在部分磁盘块不可用的情况下通过冗余和算法实现数据恢复从而能正常读写数据而划分的磁盘阵列。
纠删码机制
minio在可靠性方面做了一个优秀的设计实现了低冗余与高容错该方案是通过纠删码Erasure Code来实现的详见官方文档https://min.io/docs/minio/linux/operations/concepts/availability-and-resiliency.html#minio-availability-resiliency。
这部分比较难理解以下是个人阅读思考后整理处理的供参考。 大概的原理就是对于一个存储对象将其分成K块数据碎片同时增加M块奇偶校验碎片所有的碎片块所在的磁盘组成一个纠删磁盘阵列。 N (ERASURE SET SIZE) K (DATA) M (PARITY) 其中M值默认设置为4可以调整设置最小为0最大为n/2。 M值越小则用于存储的空间越大当其为0时意味着没有附加的奇偶校验碎片虽然可用于存储的容量最大但丧失了数据容错任何一块数据碎片损坏整个文件不再可读取。 M值越大则用于存储的空间越小当其为最大值为n/2时意味着一个1M的文件实际使用2M的存储空间其中1M用于数据本身另外1M用于奇偶校验块实现容错的目的。 从上面可以推论出来minio存储文件最大占用空间是其原始体积的两倍。 若N取16M取默认值4则数据块K为12即12M的文件实际占用存储空间是16M多使用了约33%的存储空间而不是极限情况下多占用100%空间。
关于容错性对于读数据在ERASURE SET中只要无效块总量小于等于M则都可以恢复数据并读取对于写数据分两种情况如M值小于N/2则规则同读取只要无效块总量小于等于M即可以写若M值刚好为N/2,则要求有效块要大于等于n/21。 若N取16M取默认值4则数据块K为12无效块小于等于4仍然可正常读取和写入数据。 若N取16M取默认值8则数据块K为8无效块小于等于8仍然可正常读取数据但有效块至少为9才能写入数据。
官方给了一张图说明在1个Set中挂载了16块磁盘的情况下M取值分别为4、6、8情况下可用于存储数据的块存储比率以及多少块处于有效时才可进行读操作和写操作。 注存储比率指的是数据占用空间与总占用空间数据奇偶校验的比例比如8数据块8奇偶校验块只有50%是用来存储数据的余下50%用于冗余和恢复的。
minio集群会根据节点和磁盘数自动计算NERASURE SET SIZE的取值N最大值为16即最常见的4个minio server节点每个节点挂载4块磁盘的情况下刚好组成1个阵列并且M取值是4。因此一个规模较大的集群中会存在多个相互独立的阵列。
部署模式
minio的部署模式分为两大类单节点部署和分布式部署。 其中单节点部署模式下minio会根据挂载的磁盘的数量自动决定是否启用纠删码模式。
单节点单磁盘
最简单的情况就是单节点挂载单个磁盘此时不会启用纠删码模式也不存在高可用磁盘文件损坏无法恢复官方建议用于开发和测试不可用于生产环境。个人认为对于中小型系统这种部署架构用于生产也是可接受的简单实用。一方面从业务角度而言文件通常是用户上传的附件重要程度较低损坏或丢失影响有限另一方面磁盘的可靠性相当高磁盘产生坏道的故障率低到可以忽略。 执行如下命令创建容器
docker run -p 9000:9000 --name minio -d --restartalways -e MINIO_ACCESS_KEYadmin -e MINIO_SECRET_KEY12345678 -v E:\dockerVolume\minio\data:/data minio/minio:RELEASE.2021-04-22T15-44-28Z server /data使用控制台上传文件磁盘上存放的实际就是文件本身。
单节点多磁盘
如想提升文件的可靠性和容错则仍可以部署单节点然后挂载多个磁盘该情况下自动启用纠删码模式。 执行如下命令只挂两块磁盘
docker run -p 9000:9000 --name minio -d --restartalways -e MINIO_ACCESS_KEYadmin -e MINIO_SECRET_KEY12345678 -v E:\dockerVolume\minio\data1:/data1 -v E:\dockerVolume\minio\data2:/data2 minio/minio:RELEASE.2021-04-22T15-44-28Z server /data1 /data2容器启动时报错 从报错可以看出磁盘要求至少为4块更改下命令挂载4块磁盘如下
docker run -p 9000:9000 --name minio -d --restartalways -e MINIO_ACCESS_KEYadmin -e MINIO_SECRET_KEY12345678 -v E:\dockerVolume\minio\data1:/data1 -v E:\dockerVolume\minio\data2:/data2 -v E:\dockerVolume\minio\data3:/data3 -v E:\dockerVolume\minio\data4:/data4 minio/minio:RELEASE.2021-04-22T15-44-28Z server /data1 /data2 /data3 /data4容器顺利启动并显示4块磁盘在线 同时显示初始化了1个服务池1个磁盘阵列每个磁盘阵列中有4块磁盘。 通过控制台上传1张图片查看文件情况 每个磁盘下都多了一个以文件名命名的目录下挂一个xl.meta文件实际是文件碎片或奇偶校验块占用空间约为实际文件的一半进而推断出这四块磁盘是两块做数据两块做奇偶校验。
进行破坏性试验依次删除data2、data3下的xl.meta文件来模拟磁盘失效控制台依旧能正常显示和下载文件继续删除data4下的文件则控制台中该文件不再显示与minio的容错机制一致。
多节点多磁盘
分布式部署通常用于中大型系统是最复杂的一种部署方式。通常至少部署4个minio节点每个节点挂载4块磁盘这样组成了一个16块磁盘的启用了纠删码功能的阵列。上文说过默认设置的奇偶校验块数量是4即这16块磁盘中有12块用于数据存储4块用于容错。在分布式部署的场景下minio是去中心化的所有节点是对等的没有主从的概念。而很多集群部署的中间件是有主从概念的基于选举算法来产生主节点。因此minio集群需要通过NGINX来实现负载均衡。 扩展集群
对于分布式部署如发现原存储资源不够了增加新的存储资源很多同类组件往往需要重新均衡各存储节点上数据。均衡意味着要做数据迁移不仅复杂而且耗时较长。对于该问题minio的处理方案则是另辟蹊径保持原服务池不变增加新服务池只有一点要求新增的服务池需要跟之前规划的磁盘数量一致这里的一致并不是相等而是可以是倍数关系。 比如原来得服务池是这样的 minio server http://host{1…8}/export{1…8} 可以通过以下方式扩展 minio server http://host{1…8}/export{1…8} http://host{9…16}/export{1…8} 原来的服务池保持不变数据不需要重新均衡新上传的文件会自动找寻负载低的服务池。 minio将复杂的增配资源问题转换成了一个部署问题非常巧妙。
安装部署
基于虚拟机的部署比较简单无非是获取安装包然后运行这里就不多说了。 接下来说下基于docker的安装部署。 直接通过docker 拉取镜像 docker pull minio/minio:RELEASE.2021-04-22T15-44-28Z 创建容器
docker run -p 9000:9000 --name minio -d --restartalways -e MINIO_ACCESS_KEYadmin -e MINIO_SECRET_KEY12345678 -v E:\dockerVolume\minio\data:/data -v E:\dockerVolume\minio\cofig:/root/.minio minio/minio:RELEASE.2021-04-22T15-44-28Z server /data启动成功后访问9000端口 登录后界面如下 就是一个很简单的页面新建桶和上传文件都通过右下角按钮实现相比当前的最新版本的UI和功能相当的简陋。
新版本的登录页面 新版本的功能菜单
集成验证
基于java验证常用API的使用。
引入依赖
dependencygroupIdio.minio/groupIdartifactIdminio/artifactIdversion8.5.7/version
/dependency新建控制器
新建一个控制器用于测试路径设置为file为了测试方便直接在控制器里调用API不再转调service了。
package miniodemo.controller;import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** author wqliu* date 2023-11-17*/
RestController
RequestMapping(/file/)
Slf4j
public class FileController {}
构建客户端
所有API调用的前提是构建minioClient客户端调用MinioClient的建造器方法传入服务地址和身份认证即可。
/*** 获取客户端* return*/
private MinioClient getClient(){// 创建客户端MinioClient minioClient MinioClient.builder()// 服务地址.endpoint(http://127.0.0.1:9000)// 身份认证.credentials(admin, 12345678).build();return minioClient;
}创建桶
新加方法通过参数传入桶名内部简单判断是否存在不存在则新建。同样为了测试方便未使用post而是用了get方法。
/*** 新建桶* param bucketName 桶名*/
GetMapping(/addBucket)
public void addBucket(String bucketName) {try {MinioClient client getClient();// 创建桶BucketExistsArgs bucketExistsArgs BucketExistsArgs.builder().bucket(bucketName).build();boolean exists client.bucketExists(bucketExistsArgs);if (!exists) {// 不存在创建MakeBucketArgs makeBucketArgs MakeBucketArgs.builder().bucket(bucketName).build();client.makeBucket(makeBucketArgs);}}catch (Exception ex){log.error(ex.getMessage());}}浏览器中输入地址http://localhost:8080/file/addBucket?bucketNameabc 使用minio自带控制台可以看到已经成功创建了桶。
上传文件
实现如下控制器方法
/*** 上传文件*/
GetMapping(/upload)
public void upload() {try {MinioClient client getClient();UploadObjectArgs uploadObjectArgs UploadObjectArgs.builder().bucket(abc).object(1.png).filename(e:/1.png).build();client.uploadObject(uploadObjectArgs);}catch (Exception ex){log.error(ex.getMessage());}}执行http://localhost:8080/file/upload 查看minio控制台文件已上传 查看docker挂载的磁盘在单节点单磁盘情况下实际就是把桶映射成文件夹把文件放到文件夹下
下载文件
实现如下控制器方法
/*** 下载文件*/
GetMapping(/download)
public void download() {try {MinioClient client getClient();DownloadObjectArgs downloadObjectArgs DownloadObjectArgs.builder().bucket(abc).object(1.png).filename(e:/2.png).build();client.downloadObject(downloadObjectArgs);}catch (Exception ex){log.error(ex.getMessage());}}浏览器中访问http://localhost:8080/file/download查看本地磁盘文件被下载。
获取文件流
上面方法是把文件固定下载到磁盘某个目录下实际系统使用的时候是问minio要文件流实现如下控制器方法
/*** 获取文件流*/
GetMapping(/getFileStream)
public InputStream getFileStream() {try {MinioClient client getClient();GetObjectArgs args GetObjectArgs.builder().bucket(abc).object(1.png).build();GetObjectResponse response client.getObject(args);return response;}catch (Exception ex){log.error(ex.getMessage());return null;}
}浏览器中访问http://localhost:8080/file/getFileStream通过调试模式可以看到拿到了文件流。 注意API返回的类型GetObjectResponse实际是InputStream的子类因此可以用InputStream来接收。
总结
上文构建了基于java和springboot实现的API测试完成了创建桶、上传文件、下载文件和获取文件流等常用操作像删除桶、删除文件等操作也高度类似未再一一列出。 从测试代码可以看出minio的api做了高度统一的封装每个方法对应着一个参数对象并且该参数对象内置了建造器模式。处理过程也高度类似先构建一个minio的客户端然后使用该客户端调用API方法。
坑点开源协议的变动
MinIO比较特别初早期版本的开源协议是Apache 2.0这是一种相对友好的协议可以商用。后来变更成了AGPL V3.0虽然仍然可以商用且无需付费但该协议要求使用该组件的系统必须开源这就有点…… 所以选用minio时需要慎重选择版本如自己本身就是开源软件那么使用minio的新版本更适合否则请选用老版本的minio来规避版权问题。 通过Git库查看修改日志最后一个基于apache 2.0协议的版本是2021-04-22T15-44-28Z源码下载地址 https://github.com/minio/minio/tree/RELEASE.2021-04-22T15-44-28Z 因为是源码不能直接使用需要编译而minio是使用go语言开发的需要go编译环境。
多说一句MinIO的版本号命名也独具特色惨不忍睹没有按照大多数的三段数字如3.1.2或者用某系列英文来区分如Spring Cloud而是大多以发布时间命名的版本不信你看……
开源平台资料
平台名称一二三开发平台 简介 企业级通用开发平台 设计资料csdn专栏 开源地址Gitee 开源协议MIT 欢迎收藏、点赞、评论你的支持是我前行的动力。