当前位置: 首页 > news >正文

高阶面试-存储系统的设计

概述

分类

  • 块存储 block storage
  • 文件存储 file storage
  • 对象存储 object storage

区别:

块存储

概述

位于最底层,块,是物理存储设备上数据存储的最小单位。硬盘(Hard Disk Drive,HDD)就属于块存储。常见的还有固态硬盘(SSD)、存储区域网络(SAN),操作系统和应用程序可以通过块级接口来访问这些数据。主要应用程序:数据库。

生产上,除了磁盘挂载,要么就是用云厂商提供的块存储,如AWS EBS,要么就是Ceph这种文件存储系统的块存储。

如何存储?

将数据分成固定大小的块(或扇区),每个块都有唯一的地址或编号标识。

假设有个硬盘,被分割为大小1MB的块,来存储数据。

硬盘初始化(10GB分为1w个1MB的块)–>数据写入(系统给数据分配一个或多个空闲的块)–>块分配(系统维护映射表记录块是否空闲)–>数据读取(应用程序请求包含数据的块的地址,系统检索后返回给应用程序)–>块管理(垃圾回收、压缩空间、快照、克隆、备份等)

物理磁盘 (Disk)
└── 分区 (Partition)├── 主分区 (Primary Partition)└── 扩展分区 (Extended Partition)└── 逻辑分区 (Logical Partition)└── 物理卷 (Physical Volume)└── 卷组 (Volume Group)└── 逻辑卷 (Logical Volume)└── 文件系统 (Filesystem)└── 块 (Block)
磁盘挂载示例
  1. 使用 fdisk 创建分区

    [root@72agent ~]# fdisk /dev/xvde
    

    进入 fdisk 工具,开始对 /dev/xvde 设备进行分区操作。

  2. 创建新的分区

    • 输入 n 创建新分区
      Command (m for help): n
      
    • 选择分区类型 p (主分区)
      Select (default p): p
      
    • 设置分区编号,默认是 1
      Partition number (1-4, default 1): 1
      
    • 设置起始扇区,默认是 2048
      First sector (2048-629145599, default 2048): 
      
    • 设置结束扇区,默认是最大值
      Last sector, +sectors or +size{K,M,G} (2048-629145599, default 629145599): 
      
  3. 更改分区类型

    • 输入 t 更改分区类型
      Command (m for help): t
      
    • 选择分区 1
      Selected partition 1
      
    • 输入类型代码 83 (Linux原生分区,可以格式化为 ext4、xfs 等 Linux 文件系统并用于普通的数据存储)
      Hex code (type L to list all codes): 83
      
  4. 保存分区表并退出

    Command (m for help): w
    
  5. 创建物理卷 (验证设备、写入LVM元数据包括物理卷标识符UUID、卷组信息、数据区描述、更新设备信息)

    [root@72agent ~]# pvcreate /dev/xvde1
    
  6. 创建卷组(将一个或多个物理卷PV组合成一个卷组VG,会写入LVM卷组元数据,包括卷组名、物理卷列表、物理扩展块大小等)

    [root@72agent ~]# vgcreate appvg /dev/xvde1
    
  7. 创建逻辑卷(将卷组中的物理存储空间组织成灵活易用的逻辑卷)

    [root@72agent ~]# lvcreate -l 100%VG -n applv appvg
    
  8. 格式化逻辑卷为 XFS 文件系统(在逻辑卷上创建必要的文件系统结构如超级块、块组、inode表)

    [root@72agent ~]# mkfs.xfs /dev/appvg/applv
    
  9. 创建挂载点(访问文件系统的路径,用于组织和管理文件)

    [root@72agent ~]# mkdir /app
    
  10. 挂载逻辑卷到挂载点

    [root@72agent ~]# mount /dev/appvg/applv /app/
    
  11. 添加挂载信息到 /etc/fstab,以便开机自动挂载

    [root@72agent ~]# echo "/dev/mapper/appvg-applv /app xfs defaults 0 0" >> /etc/fstab
    
  12. 验证挂载情况

    [root@72agent ~]# df -h
    

以上步骤依次执行,可以成功将 /dev/xvde 挂载到 /app 目录,并确保系统重启后自动挂载。请注意检查每个步骤的输出,以确保没有错误发生。

当然,也可以挂载逻辑卷

# 安装必要的工具(例如,使用LVM管理块存储)
sudo apt-get update
sudo apt-get install lvm2# 使用fdisk或parted创建新的分区
sudo fdisk /dev/sdx
# 创建一个新的分区并退出# 创建物理卷
sudo pvcreate /dev/sdx1# 创建卷组
sudo vgcreate vg_myvolume /dev/sdx1# 创建逻辑卷
sudo lvcreate -l 100%FREE -n lv_mydata vg_myvolume# 格式化逻辑卷
sudo mkfs.ext4 /dev/vg_myvolume/lv_mydata# 挂载逻辑卷
sudo mount /dev/vg_myvolume/lv_mydata /mnt/mydata# 写入数据到挂载的卷
echo "Hello, block storage!" | sudo tee /mnt/mydata/hello.txt# 查看数据
cat /mnt/mydata/hello.txt# 卸载卷
sudo umount /mnt/mydata

如上,可写数据到挂载的卷

文件存储

在块存储的基础上,提供更高层次的抽象。最常见,相关协议如ftp、nfs、smb、scp、rsync等

文件存储的分类:

  • 基于磁盘的普通本地文件系统,如ext4、xfs等
  • 网络文件系统,如nfs
  • 分布式文件系统 如ceph、glusterFS等
读取 /home/user/document.txt 文件
  1. 查找目录 /home/user

    • 查找根目录 /,找到 home 目录的 inode。
    • 读取 home 目录的数据块,找到 user 目录的 inode。
    • 读取 user 目录的数据块,找到 document.txt 文件的 inode 编号。
  2. 读取 inode

    • 根据 document.txt 文件的 inode 编号,从 inode 表中读取 inode 元数据。
  3. 读取数据块

    • 读取 inode 中指向的数据块,获取文件的实际内容
      如果目录项和 inode 信息已经在内存中缓存,则可以减少磁盘访问次数

主要优化:

  • 缓存 目录项和 inode 信息放入内存
  • 预读 读取文件,系统会预读后续的数据块,提高顺序读性能
  • 写回 文件系统缓冲区会延迟将写操作的数据写入磁盘,减少磁盘写操作次数
  • 索引优化 ext4采用B+树的变体做目录索引,inode索引沿用unix系统的inode结构

对象存储

文件存储系统的特点,对文件访问,需要先访问元数据inode,再访问用户数据也就是存储文件的数据。整个过程涉及2-3次的磁盘访问,而互联网领域有大量的图片等存储需求,多次磁盘访问会显著降低性能;文件系统的方式,应用访问数据的整个访问路径较长,用户无法直接访问,必须经过nginx-应用(接口、权限、文件系统接口)-远程文件系统,而随着互联网应用的发展,有海量图片等资源,和文件存储系统不同,只需要一次存储多次访问,不需要文件锁、对文件内容的修改等,因此对象存储应运而生。如AWS S3、七牛云、腾讯云对象存储等。

如何设计对象存储

需求
mindmaproot((需求))功能性需求创建bucketbucket上传下载bucket版本控制列出bucket的对象非功能性需求大文件和很多小文件一年数据量100PB数据持久性6个9,服务可用性4个9

需求如上,假设20%小对象(小于1MB),60%中等对象(1MB-64MB),20%大对象(大于64MB)。计算得到对象总数大概0.68 billion个,一个对象的元数据1KB,那需要0.68TB空间存储元数据。

对象存储:metadata(ObjectName->ObjectId) dataStorage(objectId->Object)

分离元数据和对象数据,数据存储包含不可变数据,元数据存储包含可变数据

![[Pasted image 20240605212521.png]]

架构图

![[Pasted image 20240605213257.png]]

上传

![[Pasted image 20240605214007.png]]

对象必须在桶里面

  1. http put请求创建桶–>LB–>API–>IAM确保授权且有写权限–>metadata存储,db中创建bucket_info
  2. http put请求创建script.txt的对象–>LB–>API–>IAM–>将payload的对象数据发送到数据存储,返回对象uuid
  3. API调用metadataDB存储record,包含object_name、object_id(uuid)、bucket_id
下载

![[Pasted image 20240605231357.png]]

client-(GET /bucket-to-share/script.txt)->LB–>API–>IAM验证是否有读权限–>metadataDB检索uuid–>从数据存储中检索对象数据–>返回给client

数据存储服务

![[Pasted image 20240605233125.png]]

三个部分:

  • 数据路由 data routing service,提供restfulAPI访问数据节点集群,无状态服务,查询placement service获取最佳数据节点读写
  • 存储分布服务 placement service,负责将对象放置在不同的存储节点和数据中心,如下虚拟集群图,实现冗余存储和高可用 通过心跳监控所有数据节点。集群的话,使用paxos或raft协议构建5到7个节点的集群,保证服务的高可用。
  • 数据节点 data node,也叫复制组,通过将数据复制到多个数据节点确保可靠性和持久性。每个数据节点都运行一个数据服务守护进程,给存储分布服务发送心跳,包含数据节点管理多少个磁盘驱动器,每个驱动器存储多少数据。存储分布服务给数据节点分配ID,添加到虚拟集群映射中,并返回唯一id、虚拟集群map、去哪复制数据

![[Pasted image 20240605233813.png]]

流程:

API-对象数据->dataStorage
data routing service 生成对象的uuid,请求placement service存储
placement service检查虚拟集群map,返回主节点
data routing service将数据和uuid发给主节点
主节点保存并复制给两个副本节点(CAP的三种取舍),返回响应给data routing service
uuid返回给API

数据的管理

最简单:每个对象存储到单独的文件
缺点:很多小文件,性能受影响,1.浪费数据块,典型的块是4KB,对于小文件也是占用整个磁盘块;2.inode会太多,有耗尽inode的风险;3.操作系统对大量inode的处理不好

采用方案:在一个大文件中存储多个小对象
注意:读写文件的写入访问必须串行化。现代多核处理,为每个传入请求提供专用的读写文件
![[Pasted image 20240605235652.png]]

需要知道:

  • 包含小对象的数据文件
  • 对象在文件中的开始下标

需要object_mapping表,object_id、file_name、start_offset、object_size

可以部署单个大型集群支持所有数据节点,但没必要,因为映射数据在每个数据节点都是孤立的,不需要共享,每个数据节点部署一个简单的RDB如sqlite
更新后如下:
![[Pasted image 20240606105245.png]]

如何保证高可用

多数据中心复制

擦除编码(erasure coding) 创建奇偶校验,对应数学公式保证在最多4个节点宕机的情况下可以重建原始数据。假设i个节点每年0.81%的故障率,根据backblaze计算,擦出编码可实现11个9的高可用。缺点:极大的复杂了数据节点的设计。

校验和checksum,在每个对象的末尾附加校验和,在将文件标记为只读之前,在末尾添加整个文件的校验和,如下
![[Pasted image 20240606133808.png]]

metadata schema

需要支持3个查询:

  • find object_id by object_name
  • insert and delete object by object_name
  • list objects in a bucket sharing the same prefix

需要两个表
![[Pasted image 20240606134349.png]]

规模:假设100w客户,每个客户10个bucket,每个记录1kb,也就是需要 100w*10*1kb=10GB的存储空间

上规模最好不要单个数据库实例,分片扩展对象表

分片方案:

  • 按bucket_id,但bucket可能包含数十亿个对象,导致热点分片hotspot shard
  • 按object_id,无法快速执行1和2了
  • 按bucket_name和object_name组合的hash分片呢,前两个快速,但最后一个查询不好

最后一个怎么处理?
select * from object where bucket_id='123' and object_name like 'a/b/%'
元数据服务聚合每个分片的所有对象,再将结果返回给调用者。

分页有点复杂,单个的可以用offset和limit限制,但分片的话要跟踪每个分片的游标,每个分片偏移量也可能不一样。

解决方案:将列表数据放入一个由bucket_id分片的表,仅用来列出对象,简化实现。

版本控制

![[Pasted image 20240606140115.png]]

object_version,这个字段控制,用户删除特定版本的对象时,增加删除标记

优化大文件上传

![[Pasted image 20240606141500.png]]

client-调用InitiateMultipartUpload->object storage,返回唯一标识uploadId
client-UploadPart->object storage,返回etag,也就是该部分的md5校验和
全部上传完成,client-(uploadId、part No,ETags)->object storage
data store重新组装,返回成功消息

问题:
重新组装后,旧部件没用了,需要GC

  • 惰性对象回收
  • 孤儿数据,如一半上传的数据

具体回收过程:

  1. gc将对象从/data/b复制到/data/d 的列表,跳过object2和object5,因为他们删除标志是true
  2. 更新object_mapping表,更新object3的file_name和start_offset,通常是有大量的只读文件时才会压缩

![[Pasted image 20240606165718.png]]

背景

当时用的是moosefs,选型很简单,就是考虑支持 POSIX 接口,方便查看

文件系统 --》网络文件系统 --》分布式文件存储系统 --》S3等对象存储系统

ceph

架构

相关文章:

高阶面试-存储系统的设计

概述 分类 块存储 block storage文件存储 file storage对象存储 object storage 区别: 块存储 概述 位于最底层,块,是物理存储设备上数据存储的最小单位。硬盘(Hard Disk Drive,HDD)就属于块存储。常见的还有固态硬盘(SSD)、…...

柔性测斜仪:土木工程与地质监测的得力助手

在现代土木工程和地质工程领域,精确监测土壤和岩石的位移情况对于确保工程安全至关重要。柔性测斜仪作为一种高精度、稳定性和灵活性兼备的测量设备,已逐渐成为工程师和研究人员的得力助手。本文将深入探讨柔性测斜仪在多个关键领域的应用及其重要性。 点…...

数字资产和数据资产你真的了解吗?

数据作为新型生产要素,是数字化、网络化、智能化的基础,已快速融入生产、分配、流通、消费和社会服务管理等各环节,深刻改变着生产方式、生活方式和社会治理方式。 何为数据资产?即由个人或企业拥有或控制的,能为企业带…...

【每日一练】python运算符

1. 算术运算符 编写一个Python程序,要求用户输入两个数,并执行以下运算:加法、减法、乘法、求余、除法、以及第一个数的第二个数次方。将结果打印出来。 a input("请输入第一个数:") b input("请输入第二个数&…...

CesiumJS【Basic】- #032 绘制虚线(Primitive方式)

文章目录 绘制虚线(Primitive方式)1 目标2 代码2.1 main.ts绘制虚线(Primitive方式) 1 目标 使用Primitive方式绘制虚线 2 代码 2.1 main.ts // 定义线条的起点和终点var start = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)...

海尔智家:科技优秀是一种习惯

海尔智家:科技优秀是一种习惯 2024-06-28 15:19代锡海 6月24日,2023年度国家科学技术奖正式揭晓。海尔智家“温湿氧磁多维精准控制家用保鲜电器技术创新与产业化”项目荣获国家科学技术进步奖,成为家电行业唯一牵头获奖企业。 很多人说&…...

【Android】实现图片和视频混合轮播(无限循环、视频自动播放)

目录 前言一、实现效果二、具体实现1. 导入依赖2. 布局3. Banner基础配置4. Banner无限循环机制5. 轮播适配器6. 视频播放处理7. 完整源码 总结 前言 我们日常的需求基本上都是图片的轮播,而在一些特殊需求,例如用于展览的的数据大屏,又想展…...

VLAN基础

一、什么是Vlan VLAN(Virtual Local Area Network)是虚拟局域网的简称,是一种将单一物理局域网(LAN)在逻辑层面上划分为多个独立的广播域的技术。每个VLAN都是一个独立的广播域,其内部主机可以直接通信&am…...

pytest-yaml-sanmu(五):跳过执行和预期失败

除了手动注册标记之外,pytest 还内置了一些标记可直接使用,每种内置标记都会用例带来不同的特殊效果,本文先介绍 3 种。 1. skip skip 标记通常用于忽略暂时无法执行,或不需要执行的用例。 pytest 在执行用例时,如果…...

linux指令整合(centos系统持续更新中。。。)

1、查询java进程 ps -ef|grep java 2、查询端口占用 lsof -i:端口号 3、 启动java程序 java -jar jar包路径 后台启动 nohup java -jar jar包路径 -Xms512m -Xmx512m > 日志路径 2>&1 & 4、查看服务器资源占用 top 5、关闭进程 kill -9 进程号...

个人开发实现AI套壳网站快速搭建(Vue+elementUI+SpringBoot)

目录 一、效果展示 二、项目概述 三、手把手快速搭建实现本项目 3.1 前端实现 3.2 后端方向 五、后续开发计划 一、效果展示 默认展示 一般对话展示: 代码对话展示: 二、项目概述 本项目是一个基于Web的智能对话服务平台,通过后端与第…...

Cesium与Three相机同步(3)

Cesium与Three融合的案例demo <!DOCTYPE html> <html lang"en" class"dark"><head><meta charset"UTF-8"><link rel"icon" href"/favicon.ico"><meta name"viewport" content&q…...

PMP考试报名项目经历怎么填写?指引请收好

PMP&#xff0c;这一全球公认的项目管理金牌认证&#xff0c;不仅是对项目管理能力的认可&#xff0c;更是职业生涯中的一大助力。然而&#xff0c;在报名PMP时&#xff0c;很多小伙伴都面临一个共同的难题&#xff1a;如何书写项目经验&#xff1f;今天&#xff0c;就让我们一…...

Git的基本使用方法

Git的基本使用方法 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨Git的基本使用方法&#xff0c;Git作为目前最流行的版本控制系统之一&…...

深入剖析 @Autowired 和 @Resource 在 Spring 中的区别

在 Spring 框架中&#xff0c;Autowired 和 Resource 是两个常用的注解&#xff0c;用于实现依赖注入。尽管它们都能达到将依赖对象注入到目标 bean 的目的&#xff0c;但在细节上存在一些显著的差异。本文将深入探讨这两个注解的区别&#xff0c;并结合 Spring 源码进行分析&a…...

Golang-slice理解

slice golang-slice语雀笔记整理 slicego为何设计slice&#xff1f;引用传递实现扩容机制 go为何设计slice&#xff1f; 切片对标其他语言的动态数组&#xff0c;底层通过数组实现&#xff0c;可以说是对数组的抽象&#xff0c;底层的内存是连续分配的所以效率高&#xff0c;可…...

【Linux系统】文件描述符fd

1.回顾一下文件 我们之前对文件的理解是在语言层上&#xff0c;而语言层去理解文件是不可能的&#xff01;&#xff01;&#xff01; 下面是一份c语言文件操作代码&#xff01;&#xff01;&#xff01; #include<stdio.h> int main() {FILE* fd fopen("lo…...

【嵌入式——FreeRTOS】启动任务调度器

【嵌入式——FreeRTOS】启动任务调度器 开启任务调度器vTaskStartScheduler()xPortStartScheduler()prvStartFirstTask()启动第一个任务 开启任务调度器 用于启动任务调度器&#xff0c;任务调度器启动后&#xff0c;FreeRTOS便会开始进行任务调度。 //启动任务&#xff0c;开…...

EFCore_客户端评估与服务端评估

定义 客户端评估: 先将表的所有数据读取至内存&#xff0c;再在内存中对数据进行筛选&#xff0c;数据的筛选工作在客户端服务端评估: 先将代码翻译为SQL语句&#xff0c;再执行SQL语句对数据进行筛选&#xff0c;数据的筛选工作在服务端&#xff08;默认方式&#xff09; 如何…...

Java面试题--JVM大厂篇之深入了解G1 GC:高并发、响应时间敏感应用的最佳选择

引言&#xff1a; 在现代Java应用的性能优化中&#xff0c;垃圾回收器&#xff08;GC&#xff09;的选择至关重要。对于高并发、响应时间敏感的应用而言&#xff0c;G1 GC&#xff08;Garbage-First Garbage Collector&#xff09;无疑是一个强大的工具。本文将深入探讨G1 GC适…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一&#xff1a;HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二&#xff1a;Floyd 快慢指针法&#xff08;…...

倒装芯片凸点成型工艺

UBM&#xff08;Under Bump Metallization&#xff09;与Bump&#xff08;焊球&#xff09;形成工艺流程。我们可以将整张流程图分为三大阶段来理解&#xff1a; &#x1f527; 一、UBM&#xff08;Under Bump Metallization&#xff09;工艺流程&#xff08;黄色区域&#xff…...

数据库——redis

一、Redis 介绍 1. 概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的、高性能的内存键值数据库系统&#xff0c;具有以下核心特点&#xff1a; 内存存储架构&#xff1a;数据主要存储在内存中&#xff0c;提供微秒级的读写响应 多数据结构支持&…...