wordpress网站公告,现在的网站前端用什么做,销售管理软件排名,跨境电商平台有哪些免费的在本文中#xff0c;我们设计了一个类似于 Amazon Simple Storage Service (S3) 的对象存储服务。S3 是 Amazon Web Services (AWS) 提供的一项服务#xff0c; 它通过基于 RESTful API 的接口提供对象存储。根据亚马逊的报告#xff0c;到 2021 年#xff0c;有超过 100 万… 在本文中我们设计了一个类似于 Amazon Simple Storage Service (S3) 的对象存储服务。S3 是 Amazon Web Services (AWS) 提供的一项服务 它通过基于 RESTful API 的接口提供对象存储。根据亚马逊的报告到 2021 年有超过 100 万亿个对象存储在 S3 中。在深入设计之前有必要先回顾一下存储系统和相关的术语。存储系统在高层次上存储系统分类三大类• 块存储• 文件存储• 对象存储块存储块存储最早出现在 1960 年。常见的物理存储设备比如常说的 HDD 和 SSD 都属于块存储。块存储直接暴露出来卷或者盘这是最灵活最通用的存储形式。块存储不局限于物理连接的存储也可以通过网络、光纤和 iSCSI 行业标准协议连接到服务器。从概念上讲网络附加块存储仍然暴露原始块对于服务器来说它的工作方式和使用物理连接的块存储是相同的。文件存储文件存储在块存储的上层提供了更高级别的抽象文件存储不需要处理管理块、格式化卷等所以它处理文件和目录更简单数据文件存储在分层目录结构。对象存储对象存储相对来说比较新为了高持久性大规模和低成本而牺牲性能这是一个非常刻意的权衡。对象存储针对的是相对 “冷” 的数据主要用于归档和备份。对象存储把所有的数据作为对象存储在平面结构中没有分层的目录结构。通常提供了 RESTful API 用来支持数据访问和其他的存储相比它是比较慢的大多云服务商都提供了对象存储的产品比如 AWS S3, Azure Blob 存储等。对比术语要设计一个类似于 S3 的对象存储我们需要先了解一些对象存储的核心概念。• 桶 Bucket桶是对象的逻辑容器存储桶名称是全局唯一的。• 对象Object对象时我们存储在桶中的单个数据它由对象数据和元数据组成。对象可以是我们存储的任何字节序列元数据是一组描述对象的键值对。• 版本控制 Versioning 数据更新时允许多版本共存。• 统一资源标识符 (URI)对象存储提供了 RESTful API 来访问资源所以每个资源都有一个URI 唯一标识。• 服务等级协议 (SLA)SLA 是服务提供商和客户之间的协议。比如 AWS S3 对象存储提供了 99.9 的可用性以及夸张的 99.999999999% 11个9 的数据持久性。设计要求在这个面试的系统设计环节中需要设计一个对象存储并且要满足下面的几个要求。• 基础功能桶管理对象上传和下载版本控制。• 对象数据有可能是大对象几个 GB也可能是小对象几十 kb。• 一年需要存储 100 PB 的数据。• 服务可用性 99.99% 4个9, 数据持久性 99.9999 % 6个 9。• 需要比较低的存储成本。对象存储的特点在开始设计对象存储之前你需要了解它的下面这些特点。对象不变性对象存储和其他两种存储的主要区别是存储对象是不可变的允许进行删除或者完全更新但是不能进行增量修改。键值存储我们可以使用 URI 来访问对象数据对象的 URI 是键对象的数据是值如下Request:
GET /bucket1/object1.txt HTTP/1.1Response:
HTTP/1.1 200 OK
Content-Length: 4567[4567 bytes of object data]写一次读多次对象数据的访问模式是一次写入多次读取。根据 LinkedIn 做的研究报告95 %的请求是读取操作。【Ambry: LinkedIn’s Scalable Geo-Distributed Object Store】支持小型和大型对象对象存储的设计理念和 UNIX 文件系统的设计理念非常相似。在 UNIX 中当我们在本地文件系统中保存文件时它不会把文件名和文件数据一起保存。那是怎么做的呢它把文件名存储在 inode 的数据结构中把文件数据存储在不同的磁盘位置。inode 包含一个文件块指针列表这些指针指向文件数据的磁盘位置。当我们访问本地文件时首先会获取 inode 中的元数据。然后我们按照文件块指针来读取磁盘的文件数据。对象存储的工作方式也是如此元数据和数据存储分离如下看一看我们的存储桶和对象的设计整体设计下图显示了对象存储的整体设计。• Load balancer 负载均衡向多个 API 服务分发 RESTful API 请求。• API Service编排身份验证服务元数据服务和存储服务它是无状态的可以很好的支持水平扩展。• Identity Access Management IAM身份和访问管理这是处理身份验证、授权和访问控制的服务。• Data Store 数据存储存储和检索对象数据所有和数据有关的操作都是基于对象 IDUUID。• Metadata Service 元数据服务存储对象的元数据。接下来我们一起来探索对象存储中的一些重要的工作流程。• 上传对象• 下载对象• 版本控制上传对象在上面的流程中我们首先创建了一个名为 bucket-to-share 的存储桶然后把一个名为 script.txt 的文件上传到这个桶。1. 客户端发送一个创建 “bucket-to-share” 桶的 HTTP PUT 请求经过负载均衡器转发到 API 服务。2. API 服务调用 IAM 确保用户已获得授权并且有 Write 权限。3. API 服务调用元数据服务创建存储桶并返回成功给客户端。4. 客户端发送创建 “script.txt” 对象的 HTTP PUT 请求。5. API 服务验证用户的身份并确保用户对存储桶具有 Write 权限。6. API 服务把 HTTP 请求发到到数据存储服务完成存储后返回对象的 UUID。7. 调用元数据服务并创建元数据项格式如下上传数据的 Http 请求示例如下下载对象存储对象可以通过 HTTP GET 请求进行下载示例如下下载流程图1. 客户端发送 GET 请求GET /bucket-to-share/script.txt2. API 服务查询 IAM 验证用户是否有对应桶的读取权限。3. 验证后API 服务会从元数据服务中获取对象的 UUID。4. 通过 对象的 UUID 从数据存储中获取相应的对象。5. API 服务返回对象给客户端。深入设计接下来我们会讨论下面几个比较重要的部分。• 数据一致性• 元数据• 版本控制• 优化大文件的上传• 垃圾收集 GC数据一致性对象数据只存放在单个节点肯定是不行的为了保证高可用需要把数据复制到多个节点。这种情况下我们需要考虑到一致性和性能问题。保证强一致性就要牺牲性能如果性能要求比较高时可以选择弱一致性。鱼和熊掌不可兼得。数据存储方式对于数据存储一个简单的方式是把每个对象都存储在一个独立的文件中这样当然是可以的。但是当有大量的小型文件时会有下面两个问题。第一个问题是会浪费很多数据块。文件系统把文件存储在磁盘块中磁盘块的大小在卷初始化的时候就固定了一般是 4 kb。所以对于小于 4kb 的文件它也会占满整个磁盘块。如果文件系统中保存了大量的小文件那就会就会有很多浪费。第二个问题是系统的 inode 容量是有限的。文件系统把文件元数据存储在 inode 特殊类型的磁盘块中。对于大多数文件系统inode 的数量在磁盘初始化时是固定的。所以有大量的文件时要考虑到 inode 容量满的问题。为了解决这个问题我们可以把很多小文件合并到一个更大的文件中。从概念上讲类似于预写日志WAL。当我们保存一个对象时它被附加到一个现有的文件中。文件大小达到一定值比如说 1 GB后创建一个新的文件来存储对象下图解释了它的工作流程。数据持久性对存储系统来说数据持久性非常重要如何设计出一个 6 个 9 (99.9999%) 持久性 的存储系统硬件故障和故障域无论使用哪种存储硬件故障都是不可避免的。所以为了数据持久性需要把数据复制到多个硬盘中。假设硬盘的年故障率是 0.81 %, 当然不同的型号和品牌这些是不一样的那个我们需要三个数据副本1-(0.0081)^3~0.999999, 才可以满足要求。另外我们还需要考虑到不同故障域的影响。这样可以在极端情况下带来更好的可靠性比如大规模停电自然灾害等。Erasure Coding 纠删码上面提到我们用三个完整的数据副本可以提供大概 6 个 9 的数据持久性但是这样的成本太高了。还能不能优化呢我们可以使用纠删码技术它的原理其实很简单假设现在有 a 和 b 两条数据进行异或 XOR运算后得到 ca ^ b c , 而 b c ^ aa c ^ b所以这三条数据丢失任意一条数据都可以通过剩余两条数据计算出丢失数据。下面是一个 4 2 纠删码的例子。1. 数据被分成四个大小均匀的数据块 d1、d2、d3 和 d4。2. 使用 Reed-Solomon 数学公式计算校验块比如 p1 d1 2*d2 - d3 4*d4 p2 -d1 5*d2 d3 - 3*d4 3. 节点崩溃导致数据 d3 和 d4 丢失。4. 通过数据公式和现有数据计算出丢失的数据并恢复。d3 3*p1 4*p2 d1 - 26*d2d4 p1 p2 - 7*d2和多副本复制相比纠删码占用的存储空间更少。但是在进行丢失数据恢复时它需要先根据现有数据计算出丢失数据这也消耗了 CPU 资源。数据完整性校验纠删码技术在保证数据持久性的同时也降低的存储成本。接下来我们可以继续解决下一个难题数据损坏。我们可以给数据通过 Checksum 算法计算出校验和。常见的 checksum 算法有 MD5, SHA1 等。当需要验证数据时只需要对比校验和即可如果不一致说明文件数据发生了改变。我们同样可以把校验和添加到存储系统中对于读写文件每个对象都计算校验和而对于只读文件只需要在文件的末尾添加上整个文件的校验和即可。版本控制版本控制可以让一个对象的多个版本同时保存在存储桶中。这样的好处是我们可以恢复意外删除或者覆盖的对象。为了支持版本控制元数据存储的列表中需要有一个 object_version 的列。上传对象文件时不是直接覆盖现有的记录而是插入一个新记录。当进行对象删除的时候不需要删除这条记录而是添加一个删除标记即可然后等垃圾收集器自动处理它。优化大文件上传对于比较大的对象文件可能有几个 GB上传可能需要较长的时间。如果在上传过程中网络连接失败就要重新进行上传了。为了解决这个问题我们可以使用分段上传上传失败时可以快速恢复。1. 客户端调用对象存储服务发起分段上传请求。2. 数据存储服务返回一个唯一的 uploadID。3. 客户端把大文件拆分为小对象并开始上传假设文件大小是 1.6 GB, 每个部分的大小是 200 MB, 客户端上传第一部分和 uploadID 。4. 上传第一部分后数据存储服务会返回一个 ETag本质上它是第一部分的 md5 校验和客户端通过它来判断数据是否发生了更改如果是则重新上传。5. 当每个部分都上传成功后客户端发送一个分段上传成功的请求。6. 数据存储服务组装小对象为大文件并返回一个成功消息。垃圾收集 GC垃圾收集是自动回收不再使用的存储空间的过程数据可能变成垃圾的几种方式• 延迟删除的对象对象在删除时标记成已删除但实际上还没有删除。• 孤儿数据比如上传一半的数据。• 损坏的数据。对于需要删除的对象我们使用压缩机制定期清理下图显示了它的工作流程。1. 垃圾收集器把对象 “/data/b”复制到一个名为“/data/d”的新文件中。这里会跳过对象 2 和 5因为它们的删除标志都是 true。2. 复制完所有的对象后垃圾收集器会更新 object_mapping 表指向新的文件地址然后删除掉旧的文件。总结在本文中介绍了类似于 S3 的对象存储比较了块存储、文件存储和对象存储之间的区别设计了对象上传对象下载版本控制功能并讨论了两种提高可靠性和持久性的方法复制和纠删码最后介绍了对象存储的垃圾收集的工作流程。希望这篇设计对象存储的文章对大家有用Reference[0] System Design Interview Volume 2:https://www.amazon.com/System-Design-Interview-Insiders-Guide/dp/1736049119[1] Fibre channel: https://en.wikipedia.org/wiki/Fibre_Channel[2] iSCSI: https://en.wikipedia.org/wiki/ISCSI[3] Server Message Block: https://en.wikipedia.org/wiki/Server_Message_Block[4] Network File System: https://en.wikipedia.org/wiki/Network_File_System[5] Amazon S3 Strong Consistency: https://aws.amazon.com/s3/consistency/[6] Serial Attached SCSI: https://en.wikipedia.org/wiki/Serial_Attached_SCSI[7] AWS CLI ls command: https://docs.aws.amazon.com/cli/latest/reference/s3/ls.html[8] Amazon S3 Service Level Agreement: https://aws.amazon.com/s3/sla/[9] Ambry: LinkedIn’s Scalable Geo-Distributed Object Store: https://assured-cloud-computing.illinois.edu/files/2014/03/Ambry-LinkedIns-Scalable-GeoDistributed-Object-Store.pdf[10] inode: https://en.wikipedia.org/wiki/Inode[11] Ceph’s Rados Gateway: https://docs.ceph.com/en/pacific/radosgw/index.html[12] grpc: https://grpc.io/[13] Paxos: https://en.wikipedia.org/wiki/Paxos_(computer_science)[14] Raft: https://raft.github.io/[15] Consistent hashing: https://www.toptal.com/big-data/consistent-hashing[16] RocksDB: https://github.com/facebook/rocksdb[17] SSTable: https://www.igvita.com/2012/02/06/sstable-and-log-structured-storage-leveldb/[18] B tree: https://en.wikipedia.org/wiki/B%2B_tree[19] SQLite: https://www.sqlite.org/index.html[20] Data Durability Calculation: https://www.backblaze.com/blog/cloud-storage-durability/[21] Rack: https://en.wikipedia.org/wiki/19-inch_rack[22] Erasure Coding: https://en.wikipedia.org/wiki/Erasure_code[23] Reed–Solomon error correction: https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction[24] Erasure Coding Demystified: https://www.youtube.com/watch?vQ5kVuM7zEUI[25] Checksum:https://en.wikipedia.org/wiki/Checksum[26] Md5: https://en.wikipedia.org/wiki/MD5[27] Sha1: https://en.wikipedia.org/wiki/SHA-1[28] Hmac: https://en.wikipedia.org/wiki/HMAC[29] TIMEUUID: https://docs.datastax.com/en/cql-oss/3.3/cql/cql_reference/timeuuid_functions_r.html