文件系统
文件系统
是操作系统用于组织管理存储设备(磁盘)或分区
上文件信息的方法和数据结构,负责对文件存储设备空间进行组织和分配,并对存入文件进行保护和检索
文件系统是负责管理和存储文件的系统软件,操作系统通过文件系统提供的接口去存取文件,用户通过操作系统访问磁盘上的文件
一个计算机无法存储海量的文件,通过网络将若干计算机组织起来共同去存储海量的文件,这些组织起来的计算机之间通过网络进行通信
文件系统处理能力
: 由一台计算机扩充到多台计算机同时处理文件副本
: 一台计算机挂了还有其他的副本计算机提供数据访问速度
: 每台计算机可以放在不同的地域方便用户就近访问从而提高访问速度分布式文件系统(Distributed File System)
是若干不同的逻辑磁盘分区或卷标组合在一起而形成的完整的有层次的文件系统
网络文件系统(NFS)
网络文件系统(NFS)是文件系统之上的一个网络抽象,它允许多个用户通过网络共享文件系统,并提供数据集中的优势,来最小化所需的存储空间
NFS文件系统
基于UDP/IP协议
,其实现主要是采用远程过程调用RPC机制,RPC提供了一组与机器、操作系统以及低层传送协议无关的存取远程文件的操作
RPC采用了XDR的支持
: XDR是一种与机器无关的数据描述编码协议,以独立于任意机器体系结构的格式对网络传送数据编码和解码,支持在异构系统间的数据传送分布式文件系统GFS
GoogleFS
运行于廉价的普通硬件上并提供容错功能,用于大型的、分布式的、对大量数据进行访问的应用.可以给大量的用户提供总体性能较高的服务
GFS采用主从结构
: 一个GFS集群由一个master和大量的chunkserver组成分布式文件系统HDFS
Hadoop Distributed File System
是Hadoop抽象文件系统的一种实现,它是一个高容错性((fault-tolerant))的系统,适合部署在廉价通用的机器上
HDFS采用主从结构,一个HDFS集群由一个名称节点和若干数据节点组成
云计算厂家
阿里云对象存储服务OOS(Object Storage Service)是阿里云提供的海量、安全、低成本、高可靠的云存储服务
百度对象存储服务BOS是百度提供的稳定、安全、高效、高可扩展的云存储服务
MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合使用,它兼容亚马逊S3云存储服务
接口,非常适合于存储大容量非结构化的数据
在大数据领域通常的设计理念都是无中心和分布式,MinIO集群采用去中心化
共享架构即每个结点是对等关系,通过Nginx可对MinIO进行负载均衡访问
Minio将分布在不同服务器上的多块硬盘组成一个对象存储服务,由于硬盘分布在不同的节点上,分布式Minio避免了单点故障
纠删码
是一种恢复丢失和损坏数据的数学算法,Minio使用该技术将数据分块
并冗余的分散存储在各个节点的磁盘上,所有的可用磁盘组成一个集合
测试数据恢复
第一步: 首先在本地创建4个目录表示4个硬盘,下载minio解压即可使用,在有minio.exe
的目录执行命令
minio.exe server D:\develop\minio_data\data1 D:\develop\minio_data\data2 D:\develop\minio_data\data3 D:\develop\minio_data\data4
第二步: 访问http://localhost:9000进行登录,账号和密码均为minioadmin/minioadmin
第三步: 创建bucket
即存储文件的目录(可创建多个)并选择上传的文件
第四步: 查看本地创建的四个目录观察文件的存储情况,测试minio的数据恢复情况
删除一个/两个目录
: 在web控制台中仍然可以上传文件和下载文件并且删除的目录可以恢复删除三个目录
: 由于集合中共有4块硬盘,当有大于一半的硬盘损坏时数据无法恢复,此时报Insufficient number of drives online(驱动不足)
错误Docker部署
开发阶段和生产阶段统一使用Docker安装镜像,容器启动后访问http://IP:9000查看是否正常
连接Minio服务
第一步: 在media-service
工程中添加此依赖,MinIO提供多个语言版本SDK的支持,对于Java版本要求最低Java 1.8或更高版本
<dependency>
<groupId>io.miniogroupId>
<artifactId>minioartifactId>
<version>8.4.3version>
dependency>
<dependency>
<groupId>com.squareup.okhttp3groupId>
<artifactId>okhttpartifactId>
<version>4.8.1version>
dependency>
第二步: 指定连接minio服务的三个参数
参数 | 说明 |
---|---|
Endpoint | 对象存储服务所在的IP地址,如127.0.0.1:9000 |
Access Key | Access key可以唯一标识你的账户,就像用户ID如minioadmin |
Secret Key | Secret key是你账户的密码,如minioadmin |
public class FileUploader {
public static void main(String[] args)
throws IOException, NoSuchAlgorithmException, InvalidKeyException {
try {
// 指定连接的三个参数创建MinIO客户端
MinioClient minioClient =
MinioClient.builder()
.endpoint("https://play.min.io")
.credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG")
.build();
// 创建bucket即存储文件的目录,如果手动创建了可以不用再创建
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket("asiatrip").build());
if (!found) {
// 创建一个桶并命名为asiatrip
minioClient.makeBucket(MakeBucketArgs.builder().bucket("asiatrip").build());
} else {
System.out.println("Bucket 'asiatrip' already exists.");
}
}
MinioClient
中上传/删除/查询/下载文件的方法
方法名 | 参数 | 描述 |
---|---|---|
uploadObject | UploadObjectArgs | 上传文件 |
removeObject | RemoveObjectArgs | 删除文件 |
getObject | GetObjectArgs | 查询文件 |
获取content-type
在base工程中simplemagic
依赖,使用它提供的方法根据文件扩展名得到资源的content-type
<dependency>
<groupId>com.j256.simplemagicgroupId>
<artifactId>simplemagicartifactId>
<version>1.17version>
dependency>
ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(文件扩展名);
String contentType = extensionMatch.getMimeType();
不同文件扩展名对应的MimeType媒体类型的枚举类
public class MediaType extends MimeType implements Serializable {
private static final long serialVersionUID = 2069937152339670231L;
public static final MediaType ALL = new MediaType("*","*");
public static final String ALL_VALUE ="*/*"
public static final MediaType APPLICATION_ATOM_XML = new MediaType("application","atom+xml");
public static final String APPLICATIONATOM_XML_VALUE ="application/atom+xml";
public static final MediaType APPLICATION_CBOR = new MediType("application","cbor");
public static final String APPLICATION_CBOR_VALUE = "application/cbor";
public static final MediaType APPLICATION_FORM URLENCODED = new Mediatype("application","x-wm-fomm-urlencoded");
public static final String APPLICATION_FORM_URLENCODED_VALUE = "application/x-Www-form-urlencoded";
public static final MediaType APPLICATION JSON = new MediaType("application","json");
public static final String APPLICATION_JSON_VALUE = "application/json";
public static final MediaType APPLICATION_XHTML_XML;
public static final String APPLICATION_XHTML_XML_VALUE = "application/xhtml+xmL";
public static final MediaType APPLICATION_XML;
public static final String APPLICATION_XML_VALUE = "application/xml";
public static final MediaType IMAGE_GIF;
public static final String IMAGE_GIF_VALUE = "image/gif";
public static final MediaType IMAGE_JPEG;
public static final String IMAGE_JPEG_VALUE = "image/jpeg";
public static final MediaType IMAGE_PNG;
public static final String IMAGE_PNG_VALUE = "image/png";
public static final MediaType MULTIPART_FORM_DATA;
public static final String MULTIPART_FORM_DATA_VALUE = "multipart/form-data";
public static final MediaType MULTIPART_MIXED;
public static final String MULTIPART_MIXED_VALUE = "multipart/mixed";
//........
}
上传文件
第一步: 创建一个名为testbucket
的桶,然后将其访问权限修改为public
,这样就可以直接通过http://127.0.0.1:9000/testbucket/pic01.png访问桶内存储的文件
第二步: 执行upload方法向桶的根目录或其子目录
中上传文件,上传成功后访问http://127.0.0.1:9000/查看上传的文件并预览文件
@SpringBootTest
public class MinIOTest {
// 创建MinioClient对象
static MinioClient minioClient =
MinioClient.builder()
.endpoint("http://127.0.0.1:9000")
.credentials("minioadmin", "minioadmin")
.build();
//上传文件
@Test
public void upload() {
//根据扩展名取出mimeType
ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4");
// 对于不含文件扩展名或文件扩展名未知的文件,字节流是通用的mimeType
String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
if(extensionMatch!=null){
mimeType = extensionMatch.getMimeType();
}
try {
UploadObjectArgs testbucket = UploadObjectArgs.builder()
.bucket("testbucket")
//.object("test001.mp4") // 在桶的根目录中指定上传的文件名及其扩展名
.object("001/test001.mp4") // 在桶的根目录下的子目录中指定上传文件的文件名及其扩展名,文件名不能重复
.filename("D:\\develop\\upload\\1mp4.temp")// 上传的源文件
//.contentType("video/mp4")// 默认会根据扩展名确定文件内容类型,也可以手动指定
.build();
minioClient.uploadObject(testbucket);
System.out.println("上传成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("上传失败");
}
}
}
删除文件
@Test
public void delete(){
try {
minioClient.removeObject(
RemoveObjectArgs.builder().bucket("testbucket").object("001/test001.mp4").build());
System.out.println("删除成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("删除失败");
}
}
查询文件
通过查询文件查看文件是否存在minio
文件系统中
// IO流的读取简化
@Test
public void getFile() {
GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket("testbucket").object("test001.mp4").build();
try(
FilterInputStream inputStream = minioClient.getObject(getObjectArgs);
FileOutputStream outputStream = new FileOutputStream(new File("D:\\develop\\upload\\1_2.mp4"));
) {
IOUtils.copy(inputStream,outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
查询并下载文件
查看文件是否存在minio
文件系统中,并且可以将查询到的字节流写入到本地文件中
@Test
public void getFileTest() {
try {
InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
.bucket("testbucket")
.object("pic01.png")
.build());
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\15863\\Desktop\\tmp.png");
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer,0,len);
}
inputStream.close();
fileOutputStream.close();
System.out.println("下载成功");
} catch (Exception e) {
System.out.println("下载失败");
}
}
// IO流的读取简化
@Test
public void getFile() {
GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket("testbucket").object("test001.mp4").build();
try(
FilterInputStream inputStream = minioClient.getObject(getObjectArgs);
FileOutputStream outputStream = new FileOutputStream(new File("D:\\develop\\upload\\1_2.mp4"));
) {
IOUtils.copy(inputStream,outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}