一、分布式文件系统
问题引出
- 对于一个网站系统,若为降低成本投入,将文件存储服务和网站系统部署在同一台服务器中,访问量不大,基本不会有问题,但访问量逐渐升高,网站文件资源读取逐渐频繁,单机服务器可能难以承载较大的请求量,可能会出现网站打不开,甚至系统异常等问题。
- 解决方案:采用云存储服务,将访问很频繁的文件资源服务,由本地改成云厂商提供的文件存储服务,比如阿里云 OSS、腾讯云、等等,迁移之后,网站的访问压力会得到极大的释放,服务也会变得更加稳定。
- 采用免费开源的 fastDFS 工具来作为文件存储服务器,虽然性能不错,但软件安装环境非常复杂,且没有完整的技术文档,大部分都是公司或者网友自己总结的文档,维护起来非常困难。
- 问题:云存储服务大部分都是收费的,日积月累也是一笔巨款。
分布式文件系统
定义:分布式文件系统(Distributed File System,DFS)是一种允许文件通过网络在多台主机上共享的文件系统,它通过计算机网络将若干计算机组织起来共同存储海量文件,并接收海量用户的请求。
优点:
- 高性能:文件的数据分片允许系统并行读写数据,提高数据访问性能。多个节点同时处理不同的数据块,加快数据的传输和处理速度。
- 可扩展性:分布式存储在多个节点上分布存储文件块,当需要增加存储容量时,可以简单地添加更多的节点,实现系统的无缝扩展。
- 容错性:数据的冗余备份保证了系统的容错性。即使某个节点发生故障,文件的数据仍然可以从其他节点中恢复,确保数据的可用性和完整性。
二、MinIO简介
1、官方定义
MinIO 是一种高性能、S3 (Simple Storage Service)(亚马逊,类似与国内的oss)兼容的对象存储。它专为大规模 AI/ML、数据湖和数据库工作负载而构建,并且它是由软件定义的存储。不需要购买任何专有硬件,就可以在云上和普通硬件上拥有分布式对象存储。MinIO拥有开源 GNU AGPL v3 (开源许可证)和商业企业许可证的双重许可。
2、MinIO特点
- 简单
简单性是百万兆次级数据基础设施的基础 - 无论是在技术上还是在操作上。MinIO使用和部署非常简单,没有其他对象存储可以让您在最快的时间内实现下载到生产环境的部署。 - 高性能
MinIO 是世界上最快的对象存储,没有之一。在 32 个 NVMe 驱动器节点和 100Gbe 网络上发布的 GET/PUT 结果超过 325 GiB/秒和 165 GiB/秒。 - Kubernetes云原生
通过原生 Kubernetes 运营商集成,MinIO 支持公共云、私有云和边缘云上所有主要的 Kubernetes 发行版。
三、SpringBoot集成MinIO
1、Linux环境部署MinIO
- 下载可执行文件:
wget https://dl.minio.io/server/minio/release/linux-amd64/minio
- 赋予可执行权限:
chmod +x minio
- 启动MinIO服务:
启动方式1:
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001"
MINIO_ROOT_USER 指定minio用户名
MINIO_ROOT_PASSWORD 指定minio密码
/mnt/data 数据上传的数据目录
--console-address ":9001" minio控制台监听的地址和端口,ip可以省略
启动方式2:
./minio server /mnt/data --console-address ":9001"
默认的密码是:minioadmin、minioadmin
启动方式3:(后台启动)
./minio server /mnt/data --console-address ":9001" &
可能出现的问题
问题①WARN: Detected Linux kernel version older than 4.0 release, there are some known potential performance problems with this kernel version. MinIO recommends a minimum of 4.x linux kernel version for best performance
警告:检测到的Linux内核版本早于4.0版本,此内核版本存在一些已知的潜在性能问题。MinIO建议至少使用4.x linux内核版本以获得最佳性能。
问题②打不开minio管理页面的原因:未对端口开放防火墙
解决办法:关闭防火墙或者开放端口
放行端口:firewall-cmd --zone=public --add-port=9001/tcp --permanent
查看端口开放情况:firewall-cmd --list-ports
重新加载防火墙:firewall-cmd --reload(放行后要重新加载防火墙)
关闭NinIO服务
- 前台启动:ctrl+c关闭
- 后台启动:查看正在运行的minio进程信息:
ps -ef | grep minio
kill 进程
2、docker环境部署MinIO
- 拉取Minio镜像:
docker pull minio/minio
- 启动minio服务:
docker run -p 9000:9000 --name minio \ -p 9001:9001 \ -e "MINIO_ACCESS_KEY=minio" \ -e "MINIO_SECRET_KEY=minio123" \ -v /opt/minio/data:/data \ -v /opt/minio/config:/root/.minio \ minio/minio server /data \ --console-address ":9001"
3、SpringBoot集成MinIO
1. 导入minio依赖:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.14</version>
</dependency>
maven仓库地址:https://mvnrepository.com/
2. 配置Minio客户端信息
MinioConfig类
java
@Configuration
public class MinioConfig {
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint("http://ip:9000")
.credentials("minio", "minio123")
.build();
}
}
3. 对bucket(文件夹)的操作
1、判断一个bucket是不是存在,返回true或false
minioClient.bucketExists(BucketExistsArgs.builder().bucket("bucket发的名字").build());
2、创建一个bucket,创建失败会抛出异常
minioClient.makeBucket(MakeBucketArgs.builder().bucket("文件夹的名称").build());
3、查看所有的bucket
List<Bucket> buckets = minioClient.listBuckets(); buckets.forEach(bucket -> { System.out.println(bucket.name() + "-----" + bucket.creationDate()); });
4、删除bucket,删除失败会抛异常
minioClient.removeBucket(RemoveBucketArgs.builder().bucket("bucket名字").build());
注意事项:
minIO时间与主机时间不一致导致bug :
The difference between the request time and the current time is too large
date
查看当前的时间客户端和服务端时间同步:
安装 utpdate
yum install ntpdate -y
通过命令进行同步
nptdate pool.ntp.org
或通过修改时区让时间同步
执行两条命令:
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
hwclock
- 对object(文件)常见的操作
java
1、上传一个文件
minioClient.putObject(PutObjectArgs.builder().
bucket("bucket的名字").
object(filename). //这里的file为MultipartFile类型的文件
//文件流,文件的大小,缓冲区填-1
stream(file.getInputStream(), file.getSize(), -1).
build();//上传文件
//第二种方法上传文件
minioClient.uploadObject(UploadObjectArgs.builder(). bucket("bucket桶的名称").object("文件名称").filename("文件url").build())
2、检查文件的状态,判断文件是不是存在指定的bucket中,不存在就报错
minioClient.statObject(StatObjectArgs.builder()
.bucket("test")
.object("testFile2.jpg")
.build());
3、生成可以访问的路径,带后缀的签名串
如果bucket是私有的,要是想访问就要加上后缀签名,不然不能访问
String presignedObjectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.bucket("")
.object("")
.expiry(10, TimeUnit.SECONDS)//设置10秒内有效
//.method必须带上,不然报错
.method(Method.GET)
.build());
4、下载指定bucket中的文件,GetObjectResponse 就是一个输入流
GetObjectResponse object = minioClient.getObject(GetObjectArgs.builder()
.bucket("test")
.object("testFile2.jpg")
.build());
5、删除指定bucket中的文件
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket("test")
.object("testFile2.jpg")
.build());//删除指定bucket中的object
四、MinIO集群部署
Minio集群搭建步骤:
1、准备4台机器(至少4台机器,根据minio的架构设计,只要有N/2个节点在正常,可以读数据,(N/2)+1个节点正常可以写数据。这里用4台虚拟机。使用xshell连上4台虚拟机。
2、每台机器添加一块磁盘(minio不能使用linux的root磁盘)
3、将添加的磁盘进行格式化为xfs格式:mkfs.xfs /dev/sdb
使用
lsblk
命令查看磁盘情况,可以看到4台机器都有/dev/sdb磁盘,执行格式化命令mkfs.xfs /dev/sdb
4、挂载磁盘(mount将sdb磁盘挂载到minio的存储目录)
mkdir -p /opt/minio/data
创建文件夹
mount /dev/sdb /opt/minio/data
挂载磁盘
lsblk
查看是不是成功
如果不挂载后面会报错:
Error: Drive http://192.168.80.145:9000/opt/minio/data/data2 returned an unexpected error: major: 8: minor: 3: drive is part of root drive, will not be used, please investigate - drive will be offline (*fmt.wrapError)
5、每台机器安装好minio(安装在/usr/local/minio目录下)
参考上面linux的安装命令
6、编写shell脚本(确保/opt/minio/data/data1和data2存在)
powershell
#!/bin/bash
export MINIO_ROOT_USER=minioadmin
export MINIO_ROOT_PASSWORD=minioadmin
/usr/local/minio/minio server --config-dir /etc/minio --address ":9000" --console-address ":9001" \
http://192.168.80.145/opt/minio/data/data1 \
http://192.168.80.145/opt/minio/data/data2 \
http://192.168.80.132/opt/minio/data/data1 \
http://192.168.80.132/opt/minio/data/data2 \
http://192.168.80.134/opt/minio/data/data1 \
http://192.168.80.134/opt/minio/data/data2 \
http://192.168.80.147/opt/minio/data/data1 \
http://192.168.80.147/opt/minio/data/data2
脚本内容复制到start.sh中,并赋予start.sh可执行权限,chmod +x start.sh
注意事项:
1、防火墙要开放9001端口(或者关闭防火墙)
systemctl status firewalld
查看防火墙的状态
systemctl stop firewalld
关闭防火墙start.sh文件脚本的内容不能出现错误
7、运行脚本在/opt/minio目录下执行
./start.sh
命令启动脚本
启动成功,可以访问这四个控制台。
整体的架构就是这样的: