docs(docs-zh): change rst to markdown and update docs
Signed-off-by: pengtianyue <pengtianyue@oppo.com>
23
docs-zh/source/community/article.md
Normal file
@ -0,0 +1,23 @@
|
||||
# 文章合集
|
||||
|
||||
## 入门系列
|
||||
|
||||
- [K8S容器化存储](https://mp.weixin.qq.com/s/RgpunU_j2ggE679B5y0sbQ),2023-02-07, 胡炜财@贝壳
|
||||
- [集群安装部署](https://mp.weixin.qq.com/s/B98CJ_gh-ViPlDKXkmptTA),2022-07-26,存储团队@OPPO
|
||||
- [云原生分布式存储CubeFS](https://mp.weixin.qq.com/s/mhxODmVEkSLhH8EqgJzcuQ),2022-06-28,存储团队@OPPO
|
||||
|
||||
## 最佳实践
|
||||
|
||||
- [纠删码模式选型](https://mp.weixin.qq.com/s/v-fFJZtDY2_9loHWAnPXqA),2022-12-15,存储团队@OPPO
|
||||
- [常见运营问题处理](https://mp.weixin.qq.com/s/cH9xw5sK80RIkkZWpyd4qA),2022-11-29,存储团队@OPPO
|
||||
- [大数据冷热分离技术实践](https://mp.weixin.qq.com/s/F9_Ix1lkAfn0b05hoWlVwg),2022-09-01,存储团队@OPPO
|
||||
- [机器学习平台技术实践](https://mp.weixin.qq.com/s/RB1iYn850vfnwE37-UDhdA),2022-08-09,存储团队@OPPO
|
||||
|
||||
## 技术揭秘
|
||||
|
||||
- [元数据管理设计](https://mp.weixin.qq.com/s/_PwSANyJZZuFst1SOolNGQ),2023-01-04,存储团队@OPPO
|
||||
- [Posix文件客户端热升级原理设计](https://mp.weixin.qq.com/s/AUcOjcXOIs4ba1vvnu0-3Q),2022-12-22,存储团队@OPPO
|
||||
- [均衡、巡检与故障自愈设计](https://mp.weixin.qq.com/s/CUfaEKUqvQ6UekcTDqkMqQ),2022-11-04,存储团队@OPPO
|
||||
- [纠删码单机存储引擎设计](https://mp.weixin.qq.com/s/jCdvwueQrjeIbwAADzb_7Q),2022-10-13,存储团队@OPPO
|
||||
- [混合云加速设计](https://mp.weixin.qq.com/s/kkUvZUMhg-qmy6Bw_RM2xw),2022-09-16,存储团队@OPPO
|
||||
- [纠删码引起系统设计](https://mp.weixin.qq.com/s/Bx2QM3p7Tz-2y6IGlXAdKA),2022-07-21,存储团队@OPPO
|
||||
@ -1,4 +0,0 @@
|
||||
文章合集
|
||||
========================
|
||||
|
||||
TODO
|
||||
@ -1,4 +0,0 @@
|
||||
贡献者
|
||||
========================
|
||||
|
||||
TODO
|
||||
16
docs-zh/source/community/overview.md
Normal file
@ -0,0 +1,16 @@
|
||||
# 加入社区
|
||||
|
||||
## 开发指南
|
||||
|
||||
你可以通过多种方式参与到CubeFS的开源建设当中,如:
|
||||
|
||||
- **报告问题**:请合理的使用关键字搜索 [查找问题](https://github.com/cubeFS/cubefs/search?q=&type=Issues&utf8=%E2%9C%93),以确保问题没有提交。然后通过 [打开问题](https://github.com/cubeFS/cubefs/issues) 提交问题描述和复现方法。
|
||||
- **新增补丁**:[规范说明](https://github.com/cubefs/cubefs/blob/master/CONTRIBUTING.md)。
|
||||
|
||||
## 开发者
|
||||
|
||||
[主要维护者及其职责列表](https://github.com/cubefs/cubefs/blob/master/MAINTAINERS.md)
|
||||
|
||||
## 用户
|
||||
|
||||
[使用用户](https://github.com/cubefs/cubefs/blob/master/ADOPTERS.md)
|
||||
@ -1,4 +0,0 @@
|
||||
使用者
|
||||
========================
|
||||
|
||||
TODO
|
||||
@ -39,7 +39,7 @@ release = u''
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.autodoc','recommonmark','sphinx_markdown_tables',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
@ -49,7 +49,7 @@ templates_path = ['_templates']
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ['.rst', '.md']
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
@ -75,7 +75,7 @@ pygments_style = None
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme = 'piccolo_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
|
||||
81
docs-zh/source/design/authnode.md
Normal file
@ -0,0 +1,81 @@
|
||||
# 鉴权
|
||||
|
||||
众所周知,Internet(国际互联网)和intranet(企业内部网)都是不安全的地方,黑客通常可以使用工具在网络上嗅探到很多敏感信息。更糟糕的是,由于无法确认对端是否诚实的表达了自己的身份,客户端与服务端之间没有办法建立可信的连接。因此,如果没有鉴权机制,CubeFS一旦部署在了网络中,便会存在一些常见的安全问题。
|
||||
|
||||
## 安全问题
|
||||
|
||||
- 未认证的节点可能会访问敏感信息,如`restful API`,`volume`信息等
|
||||
|
||||
- 通信信道可能受到 `Man-in-the-middle (MITM)` 攻击
|
||||
|
||||
## 系统架构
|
||||
|
||||
`Authnode` 是为 CubeFS 提供通用认证和授权框架的安全节点。此外, `Authnode` 还充当对称密钥和非对称密钥的集中密钥存储。`Authnode` 采用并定制了基于票证的 `Kerberos` 认证思想。具体来说,当客户端节点( `Master 、 Meta 、 Data 或 client `节点)访问服务时,首先需要在 `Authnode` 中展示用于身份验证的共享密钥。如果认证成功, Authnode 将专门为该服务颁发一个限时票证。出于授权的目的,功能嵌入到票证中,以指示 谁可以在什么资源上做什么 。
|
||||
|
||||
{.align-center}
|
||||
|
||||
在`Authnode` 的上下文中,我们将负责初始化一个服务请求的节点定义为 `Client` ,而响应该请求的节点定义为 `Server` 。这样,任何 CubeFS 节点都可以充当 `Client` 或者 `Server` 。
|
||||
|
||||
`Client` 和 `Server` 之间通过 `HTTPS` 或者 `TCP` 进行通信。 `Authnode` 的工作流程如上图所示,简要描述如下:
|
||||
|
||||
### 凭据请求 (F1)
|
||||
|
||||
在任何服务请求之前,需要持有密钥 *Ckey* 的客户端为服务( `target
|
||||
service`)从 `Authnode` 获取服务的认证信息。
|
||||
|
||||
- C-\>A:
|
||||
客户端发送一个认证请求,请求中包含一个代表客户端的客户端ID(`id`)和一个代表目标服务的服务ID(`sid`)。
|
||||
- C\<-A: 服务端从自己的 [key store]{.title-ref}
|
||||
中查找客户端秘钥(`CKey`)和服务端秘钥(`SKey`)。如果认证成功,服务端会向客户端回应一条`CKey`加密的消息。消息中会包含会话秘钥(`sess_key`)和目标服务的凭据。
|
||||
|
||||
在获取凭据并使用`Ckey`处理一些安全检查后,客户端拥有`sess_key`和Skey{*ticket*}以备将来的服务请求。
|
||||
|
||||
### HTTPS中的服务请求 (F2)
|
||||
|
||||
如果服务请求是通过HTTPS协议发送的,那么它将按如下步骤进行:
|
||||
|
||||
- C-\>S: 客户端发送一个包含SKey {*ticket*}的请求。
|
||||
- C\<-S:
|
||||
服务端进行以下操作
|
||||
- (1)执行消息解密并获取凭据
|
||||
- (2)验证功能
|
||||
- (3)使用从凭据中获取的`sess_key`,加密`data`返回给客户端。
|
||||
|
||||
客户端使用`sess_key`解密从服务器返回的消息并验证其有效性。
|
||||
|
||||
### TCP中的服务请求 (F3)
|
||||
|
||||
如果服务请求是通过TCP协议发送的,那么它将按如下步骤进行:
|
||||
|
||||
- C-\>S: 客户端发送一个包含SKey {*ticket*}的请求。
|
||||
- C\<-S: 服务端
|
||||
- (1)解密凭据并验证其功能
|
||||
- (2)提取`sess_key`
|
||||
- (3)生成一个随机数`s_n`
|
||||
- (4)用`sess_key`加密的这个数后响应给客户端。
|
||||
- C-\>S:
|
||||
客户端解密回复的消息,并向服务端发送另一条消息,其中包括随机生成的数字`s_c`和`s_n+1`,这两个数字都用`sess_key`加密。
|
||||
- C\<-S:
|
||||
服务器将验证`s_n`是否增加了1。如果验证成功,服务端将发送一条包含`s_c+1`的消息,该消息由`sess_key`加密。
|
||||
- C\<-\>S:
|
||||
客户机在消息解密后验证`s_c`是否增加了一个。如果成功,则已在客户端和服务器之间建立经过身份验证的通信通道。基于此通道,客户端和服务器可以执行进一步的通信。
|
||||
|
||||
## 未来工作
|
||||
|
||||
`Authnode`支持CubeFS急需的一般的身份验证和授权。未来`CubeFS`的安全增强有两个方向:
|
||||
|
||||
### 特性丰富
|
||||
|
||||
当前的 `Authnode`实现不支持某些高级功能:
|
||||
|
||||
- 密钥轮换:共享密钥在客户端和服务器中硬编码,不会更改。它增加了安全风险,攻击会破坏加密并找到密钥。定期轮换秘钥有助于降低此类风险。
|
||||
- 凭据撤销:出于性能考虑,凭据将有效一段时间(如几个小时)。如果客户端不幸地泄漏了它的票证,恶意方可以在有效期内将票证用于服务请求。凭据撤销机制可以通过在发生泄漏时撤销凭据来预防此类问题。
|
||||
- HSM支持:`Authnode`是CubeFS中的安全瓶颈。破坏`Authnode`意味着破坏整个系统,因为它管理密钥存储。硬件安全模块(HSM)为密钥管理提供物理保护。让HSM(例如`SGX`)保护`Authnode`,可以降低 `Authnode`被破坏的风险。
|
||||
|
||||
### 端到端数据加密
|
||||
|
||||
当前的 `Authnode`实现并不系统地支持对传输中和静止数据的加密,即使我们可以在通信期间使用会话密钥加密数据。保护数据的一种更安全的方法是使用`端到端数据加密`。特别是,加密密钥由 `Authnode`管理和分发,数据在客户端节点加密,通过网络发送并存储在服务端中。与基于现有工具(`fscrypt` 、 `ecryptfs` 和`dm-crypt`)的服务端加密相比, `端到端数据加密` 至少具有以下优点:
|
||||
|
||||
- 由于数据解码密钥存储在 `Authnode` 中,一旦数据服务器(例如
|
||||
`data Node`)被攻击者入侵,它就可以减少数据泄漏。
|
||||
- 它提供对加密密钥的集中管理(轮换、撤销和生成)。
|
||||
@ -1,79 +0,0 @@
|
||||
鉴权节点
|
||||
=========
|
||||
|
||||
众所周知,Internet(国际互联网)和intranet(企业内部网)都是不安全的地方,黑客通常可以使用工具在网络上嗅探到很多敏感信息。更糟糕的是,由于无法确认对端是否诚实的表达了自己的身份,客户端与服务端之间没有办法建立可信的连接。因此,如果没有鉴权机制,CubeFS一旦部署在了网络中,便会存在一些常见的安全问题。
|
||||
|
||||
安全问题
|
||||
------------------
|
||||
|
||||
- 未认证的节点可能会访问敏感信息,如restful API,volume信息等
|
||||
- 通信信道可能受到 `Man-in-the-middle` (`MITM`) 攻击
|
||||
|
||||
系统架构
|
||||
-----------------------
|
||||
|
||||
`Authnode` 是为 `CubeFS` 提供通用认证和授权框架的安全节点。此外, `Authnode` 还充当对称密钥和非对称密钥的集中密钥存储。 `Authnode` 采用并定制了基于票证的 `Kerberos` 认证思想。具体来说,当客户端节点( `Master` 、 `Meta` 、 `Data` 或 `client` 节点)访问服务时,首先需要在 `Authnode` 中展示用于身份验证的共享密钥。如果认证成功, `Authnode` 将专门为该服务颁发一个限时票证。出于授权的目的,功能嵌入到票证中,以指示 `谁可以在什么资源上做什么` 。
|
||||
|
||||
|
||||
.. image:: pic/authflow.png
|
||||
:align: center
|
||||
:scale: 50 %
|
||||
:alt: Architecture
|
||||
|
||||
在 `Authnode` 的上下文中,我们将负责初始化一个服务请求的节点定义为 `Client` ,而响应该请求的节点定义为 `Server` 。这样,任何 `CubeFS` 节点都可以充当 `Client` 或者 `Server` 。
|
||||
|
||||
`Client` 和 `Server` 之间通过 `HTTPS` 或者 `TCP` 进行通信。 `Authnode` 的工作流程如上图所示,简要描述如下:
|
||||
|
||||
凭据请求 (F1)
|
||||
+++++++++++++++++++
|
||||
|
||||
在任何服务请求之前,需要持有密钥 *Ckey* 的客户端为服务( `target service` )从 `Authnode` 获取服务的认证信息。
|
||||
|
||||
- C->A: 客户端发送一个认证请求,请求中包含一个代表客户端的客户端ID(*id*)和一个代表目标服务的服务ID(*sid*)。
|
||||
- C<-A: 服务端从自己的 `key store` 中查找客户端秘钥(*CKey*)和服务端秘钥(*SKey*)。如果认证成功,服务端会向客户端回应一条*CKey*加密的消息。消息中会包含会话秘钥(*sess_key*)和目标服务的凭据。
|
||||
|
||||
在获取凭据并使用*Ckey*处理一些安全检查后,客户端拥有*sess_key*和Skey{*ticket*}以备将来的服务请求。
|
||||
|
||||
HTTPS中的服务请求 (F2)
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
如果服务请求是通过HTTPS协议发送的,那么它将按如下步骤进行:
|
||||
|
||||
- C->S: 客户端发送一个包含SKey {*ticket*}的请求。
|
||||
- C<-S: 服务端进行以下操作,(1)执行消息解密并获取凭据,(2)验证功能,(3)使用从凭据中获取的*sess_key*,加密*data*返回给客户端。
|
||||
|
||||
客户端使用*sess_key*解密从服务器返回的消息并验证其有效性。
|
||||
|
||||
TCP中的服务请求 (F3)
|
||||
+++++++++++++++++++++++++++
|
||||
|
||||
如果服务请求是通过TCP协议发送的,那么它将按如下步骤进行:
|
||||
|
||||
- C->S: 客户端发送一个包含SKey {*ticket*}的请求。
|
||||
- C<-S: 服务端(1)解密凭据并验证其功能,(2)提取*sess_key*,(3)生成一个随机数*s_n*,(4)用*sess_key*加密的这个数后响应给客户端。
|
||||
- C->S: 客户端解密回复的消息,并向服务端发送另一条消息,其中包括随机生成的数字*s_c*和*s_n*+1,这两个数字都用*sess_key*加密。
|
||||
- C<-S: 服务器将验证*s_n*是否增加了1。如果验证成功,服务端将发送一条包含*s_c*+1的消息,该消息由*sess_key*加密。
|
||||
- C<->S: 客户机在消息解密后验证*s_c*是否增加了一个。如果成功,则已在客户端和服务器之间建立经过身份验证的通信通道。基于此通道,客户端和服务器可以执行进一步的通信。
|
||||
|
||||
未来工作
|
||||
-----------
|
||||
|
||||
`Authnode` 支持CubeFS急需的一般的身份验证和授权。未来 `CubeFS` 的安全增强有两个方向:
|
||||
|
||||
特性丰富
|
||||
++++++++++++++++++
|
||||
|
||||
当前的 `Authnode` 实现不支持某些高级功能:
|
||||
|
||||
- 密钥轮换:共享密钥在客户端和服务器中硬编码,不会更改。它增加了安全风险,攻击会破坏加密并找到密钥。定期轮换秘钥有助于降低此类风险。
|
||||
- 凭据撤销:出于性能考虑,凭据将有效一段时间(如几个小时)。如果客户端不幸地泄漏了它的票证,恶意方可以在有效期内将票证用于服务请求。凭据撤销机制可以通过在发生泄漏时撤销凭据来预防此类问题。
|
||||
- HSM支持: `Authnode` 是CubeFS中的安全瓶颈。破坏 `Authnode` 意味着破坏整个系统,因为它管理密钥存储。硬件安全模块(HSM)为密钥管理提供物理保护。让HSM(例如*SGX*)保护 `Authnode` ,可以降低 `Authnode` 被破坏的风险。
|
||||
|
||||
端到端数据加密
|
||||
++++++++++++++++++++++++++
|
||||
|
||||
当前的 `Authnode` 实现并不系统地支持对传输中和静止数据的加密,即使我们可以在通信期间使用会话密钥加密数据。保护数据的一种更安全的方法是使用 `端到端` `数据` `加密` 。特别是,加密密钥由 `Authnode` 管理和分发,数据在客户端节点加密,通过网络发送并存储在服务端中。与基于现有工具( `fscrypt` 、 `ecryptfs` 和 `dm-crypt` )的服务端加密相比, `端到端` `数据` `加密` 至少具有以下优点:
|
||||
|
||||
-由于数据解码密钥存储在 `Authnode` 中,一旦数据服务器(例如 `data Node` )被攻击者入侵,它就可以减少数据泄漏。
|
||||
-它提供对加密密钥的集中管理(轮换、撤销和生成)。
|
||||
|
||||
269
docs-zh/source/design/blobstore.md
Normal file
@ -0,0 +1,269 @@
|
||||
# 纠删码子系统
|
||||
|
||||
CubeFS 3.0.0以前版本只提供多副本存储,随着数据规模持续增长,业务面临着更大的成本挑战,用户对更低成本的纠删码(ErasureCode, 下文简称EC)的需求愈加强烈;CubeFS近期重磅发布3.0.0版本,其关键特性之一是增加了对EC的支持(下图中ErasureCode Subsystem部分),EC将大幅降低数据冗余度,优化存储成本,有力支撑更大规模存储需求。
|
||||
|
||||

|
||||
|
||||
本文将为大家分享CubeFS中纠删码存储子系统的设计思考。
|
||||
|
||||
## 系统特性
|
||||
|
||||
CubeFS的纠删码存储子系统(BlobStore),是一个高可靠、高可用、低成本、支持EB规模的独立键值存储系统。主要特点:
|
||||
|
||||
1. 采用 Reed-Solomon编码,简洁的在线EC架构;
|
||||
2. 动态可配的EC模式:支持如“6+3”、“12+3”、“10+4”、...等多种规格 ;
|
||||
3. 灵活的多AZ部署:支持1、2、3不同AZ数目的部署;
|
||||
4. 采用Raft协议保证元数据的强一致性和高可用;
|
||||
5. 高性能的存储引擎:小文件专项优化、高效的垃圾回收机制;
|
||||
|
||||
## 整体架构
|
||||
|
||||

|
||||
|
||||
**模块简介**
|
||||
|
||||
* Access:请求接入网关,提供数据读、写、删等基本操作接口;
|
||||
* BlobNode:单机存储引擎,管理整机的磁盘数据,负责数据的持久化存储, 执行卷修补、迁移和回收任务;
|
||||
* ClusterManager:元数据管理模块, 负责集群资源(如磁盘、节点、存储空间单元)的管理;
|
||||
* Proxy:ClusterManager与异步消息代理模块,提供数据写入空间的分配、删除与修补消息转发等;
|
||||
* Scheduler:异步任务调度中心,负责磁盘修复、磁盘下线、数据均衡、数据巡检、数据修补以及数据删除等任务的生成和调度。
|
||||
|
||||
## 名词解析
|
||||
|
||||
**Volume**
|
||||
|
||||
一个逻辑的存储空间单元,有固定容量上限 (如32G,写满32G变Immutable),Volume 由 Volume ID 标识,Volume的创建、销毁、分配在 ClusterManager 统一管理。**不同的 Volume支持不同的EC模式**。
|
||||
|
||||
集群的可分配空间由一个个Volume组成。Access写数据前需先申请一个可用的Volume,读数据则先查询到数据对应的Volume。
|
||||

|
||||
|
||||
**Chunk**
|
||||
|
||||
**Chunk**是Volume的基本组成单元,是存储数据的容器,由 Chunk ID 唯一标识,对应磁盘的一段实际的物理存储空间;Chunk的创建、销毁由BlobNode管理;多个 Chunk按照纠删码编码模式组成一个Volume,Chunk和Volume的绑定关系持久化在ClusterManager中。
|
||||
|
||||
以纠删码模式为“4+4”(即数据块数目为n=4,校验块数目m=4)的Volume举例,该Volume由 8 个 Chunk组成。 这 8 个 Chunk分散在不同机器的磁盘上。
|
||||
|
||||

|
||||
|
||||
**Blob**
|
||||
|
||||
**Blob** 是用户数据的一次EC计算的数据大小。由 Access 负责切分,Blob用 BlobID 唯一标识,BlobID 则由ClusterManager统一管理分配,**保证****全局唯一**。
|
||||
|
||||
假设系统预设的Blob大小为8 M。当前有用户数据 200 M,则会被切分成有序的 25 个 Blob,优先写入某个 Volume 中,当前 Volume 空间不足时,余下Blob 可写入其他 Volume。
|
||||

|
||||
|
||||
**Shard**
|
||||
|
||||
**Shard 是****EC****条带****数据****的组成单元。**上面提到 Volume 由多个 Chunk 组成,Blob 写入Volume 时,对应切成多个块分别写到各个Chunk。**每个小块数据叫做 Shard ,一个 Shard 对应写一个 Chunk**。
|
||||
|
||||
假设一份用户Blob 数据大小为8M, Volume纠删码模式为“ 4+4 ”,Access会把blob切成4份大小为2M的原始数据块,再计算出4个大小为2M的冗余校验块。该8个2M块都被称为 Shard ,这些 Shard会被分别写到Volume绑定的各个Chunk中,至此完成EC编码及存储流程。
|
||||
|
||||

|
||||
|
||||
## 数据读写流程
|
||||
|
||||
**写流程**
|
||||
|
||||
1. Access 申请一个或多个足够空间且可用的 volume;
|
||||
2. Access 顺序接收用户数据,切分成Blob,按照EC编码模式,切成N个数据块,再计算出M个校验块,每一个数据块和校验块表示一个shard;
|
||||
3. 把这些 shard 并发写入卷映射的 chunk中;
|
||||
4. Blob写采用quorum模型,大多数的 (>n个)shard写成功即可,写失败的shard投递修补消息到Proxy中,作异步修补,最终达到数据完整。如下图,2+1 的纠删码模式,用户数据生成3个shard(两个数据块,一个校验块)。并发写入到 BlobNode。正常情况,3 份都会成功,假设出现异常情况,写入超过两份也算成功。
|
||||

|
||||
5. Access 把对应的数据位置信息(Location)返回给用户,用户需要保存该位置信息,用来作读取数据。
|
||||
**读流程**
|
||||
|
||||
在没有数据损坏的情况下,根据数据位置信息读取指定长度(Range)的数据直接返回。
|
||||

|
||||
|
||||
当需要读取的数据块有损坏或者数据所在节点故障,需要读取其他节点上的数据来修复数据。
|
||||
|
||||
这里可能导致一定程度的读放大,因为它必须读到足够的数据块才能计算出所需数据。
|
||||
|
||||
成本考量:我们总是希望读取本地数据即可返回给用户。则多AZ模式下优先选择修复读,通过本AZ存储的部分数据块和部分校验块计算出完整数据;减少IO时间,及AZ间的网络带宽;以计算时间换取带宽成本。
|
||||
|
||||
尾延时通过backup request来优化:要得到完整的blob,正常读n个shard数据即可,实际可发n+x(1< x <= m)个Shard的读请求,任意前n个请求响应后即可得到原始blob,优雅应对网络超时、节点负载重、磁盘IO慢或故障导致的尾延时。
|
||||

|
||||
|
||||
## 元数据中心
|
||||
|
||||
元数据中心(ClusterManager)负责 Volume 的创建和分配,并管理集群存储节点的状态信息,也为无状态组件提供服务注册功能。
|
||||
|
||||
ClusterManager多节点部署,采用Raft协议保障一致性,以RocksDB作为底层存储,得益于RocksDB其批量聚合特性,ClusterManager可提供很高的吞吐能力。
|
||||

|
||||
|
||||
## Access 模块
|
||||
|
||||
Access是接入层模块,负责数据收发、切片、EC编解码及流控等。
|
||||
|
||||
### Blob分片
|
||||
|
||||
用户数据按照一定大小被切分成多个连续的 Blob,打散分布在集群的多个物理节点。在并发场景下,读写请求能充分利用全部集群资源数据。
|
||||
|
||||
### 并发优化
|
||||
|
||||
写数据流程中对应的每个 Blob 被切分成多个Shard,Shard 之间并发写入。读取流程中的多 Shard 数据构建和用户端数据发送是 Pipeline 并行的,节省了网络IO时间。
|
||||
|
||||
### Quorum 机制
|
||||
|
||||
EC 模式要写入的数据分块数比副本模式要多,往往一份数据需要写多个位置。比如 3 副本只需写 3 次,3+2 的 EC 模式则需要写 5 次。在单次写入失败率一定的情况下,EC 模式整体失败率更高。 为了提高可用性,Access 采用 Quorum 机制,允许一定份数的写入失败,只需要满足 EC 的可恢复条件即可。Quorum 写成功返回后,通过异步流程对失败数据块进行修补,达到最终数据完整性。
|
||||
|
||||
### EC 编解码
|
||||
|
||||
我们采用 RS(Reed-Solomon) 编解码,存储冗余度低但数据耐久性高。在多AZ部署时,可配置使用LRC编码,在每个AZ内添加1份局部校验块,可大幅降低数据修复时需跨AZ读的概率,从而降低跨机房带宽传输,加速数据修复。
|
||||
|
||||
### 小文件优化
|
||||
|
||||
小文件做在线EC会有较严重的IO放大。比如 128K 大小的文件,切分后的shard存储在 4+4 个位置,修复读至少需要4次网络请求才能构建出完整数据。我们提出的优化方案为:对于越小文件数据,尽可能写入到越少的数据块中,以减少读取时的网络请求;写入性能并没有明显降低,但读取性能大大提高。
|
||||
|
||||
举个例子,假设 Blob 阈值为 4 M,纠删码模式为"4+4",单个Shard阈值为1M。当前有 128K 的用户数据。如果按照常规的切分方式,128K 切成 4 份,每一份 32K :
|
||||
|
||||

|
||||
|
||||
这种切片方式当用户读 128K 数据的时候,需要至少发送 4 次网络请求进行多次 IO,异常发生的概率更高。
|
||||
|
||||
我们的方案采用空间换时间的方式,只需要 1 次网络请求就可能得到完整的数据。把128K用户数据全部写入第一个数据块,后三个数据块以空白数据代替;下载时只要能正确得到有用数据块或任一校验快即可修复全部用户数据。
|
||||
|
||||

|
||||
|
||||
## 存储引擎
|
||||
|
||||
BlobNode作为单机存储引擎,管理本机所有磁盘存储空间,负责用户数据在磁盘和内存上的组织,对外提供数据读、写、删、修复等接口。
|
||||
|
||||
### Key/Value 分离存储
|
||||
|
||||
Key 和 Value 分离存储,适合大中型的 Value 存储。kay / value 分离的思想自 2016 年《WiscKey: Separating Keys from Values in SSD-Conscious Storage》,[https://www.usenix.org/system/files/conference/fast16/fast16-papers-lu.pdf](https://www.usenix.org/system/files/conference/fast16/fast16-papers-lu.pdf),论文提出以后,有了很多实践的项目,在 BlobStore 系统的存储引擎中也借鉴了该思想。
|
||||
|
||||
每个磁盘分为元数据和数据两部分,如下:
|
||||
|
||||

|
||||
|
||||
Shard的元数据存储 LSM Tree 里,实际数据部分存储在一个顺序大文件( Chunk File)中。由于 LSM Tree 里面的数据量少,compact 带来的影响就很小,实际运行几乎不会出现 compact 。也可以把元数据集中放在高性能的 SSD 介质上,SATA 盘来承接用户数据。
|
||||
|
||||
Chunk 形式上是一个个大文件,大小有上限,Chunk只支持Append写,对HDD友好。
|
||||
|
||||
### 高可靠设计
|
||||
|
||||
### 数据保护设计
|
||||
|
||||
磁盘硬件故障是常态(如坏道、静默错误),数据损坏后系统要能校验出来,保证返回给上层业务的一定是正常数据。
|
||||
|
||||
**Key 元数据**
|
||||
|
||||
LSM Tree 有自己的 crc 校验保护。sst 文件由 block 组成:
|
||||

|
||||
每个 block 都有 crc 保护:
|
||||

|
||||
|
||||
当磁盘出现静默错误的时候,能及时校验出来,避免读到错误的数据。上层感知到这个节点的错误,只需通过其他节点重构出数据即可获得正确的数据。
|
||||
|
||||
**Value 数据格式**
|
||||
|
||||
用户数据存在于 Chunk File ,这是一个大的聚合文件。它有自己的保护设计。Chunk 由 header 头部和 Shard 组成:
|
||||

|
||||
每个 shard 都单独保护起来,它有自己的 magic 定界符,并且内部按照 block 分块保护(而不是一个 shard 只有一个 crc ,这样能做到更细粒度的保护):
|
||||

|
||||
|
||||
**兜底设计**
|
||||
|
||||
考虑到 LSM 里存放的元数据是集中存放,如果出现丢失可能影响很大。所以 Chunk File 在写入 Shard 数据的时候,在 header ,footer 里会备份一份元数据。在极端情况,LSM 的元数据就算全部丢失,能够通过解析 Chunk 文件重构出元数据,从而恢复索引数据,而在读写删的时候,也能通过双重校验来保护数据。
|
||||
|
||||
### 高效的垃圾回收
|
||||
|
||||
传统的垃圾回收一般采用先标记删除,后异步做compact的方式 ,compact过程则涉及到大量磁盘读写,有明显缺点:
|
||||
|
||||
1. 磁盘IO开销大:compact过程是读旧的文件,写新的文件,然后删旧的文件;易导致长时间的随机 IO,速度慢,效率低,也会影响业务的正常IO
|
||||
2. 空间利用率低:因compact过程磁盘IO开销大,为减少 compact 次数,一般会等垃圾数据累积到一定阈值再做compact,易导致空间回收不及时,磁盘存储利用率降低。
|
||||
BlobNode的垃圾回收流程如下:
|
||||
|
||||
1. 先删数据在LSM中的索引条目;
|
||||
2. 再对Chunk File用系统调用fallocate在指定位置打一个相应大小的"洞";
|
||||
BlobNode垃圾回收机制充分利用文件系统的“打洞”(punch hole)功能:删除数据打洞时,系统会把文件洞中空间释放,剩余部分的文件偏移不变,而文件大小相应减小,无需整理文件即可快速释放垃圾空间。
|
||||

|
||||
|
||||
BlobNode高效的垃圾回收方法,可解决传统垃圾回收compact过程带来的大量IO开销,提高存储空间利用率,对删除量大的业务场景非常适用。
|
||||
|
||||
### Append写
|
||||
|
||||
覆盖更新是数据损坏最常见的场景之一,Chunk File 的设计是:数据的写入永远都是 Append 写入,不存在覆盖更新的情况。写过的位置只能读,尽量发挥机械磁盘顺序访问性能。
|
||||

|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 多 AZ 部署
|
||||
|
||||
BlobStore 支持多 AZ 的部署方式,1AZ,2AZ,3AZ 都是完美支持,只需要配置对应的 EC 编码模式即可。假设3AZ使用"15+9"编码模式,任意一个AZ故障导致其中数据完全损毁(8份), 利用剩余两个AZ数据(16份)即可将故障AZ的全部数据修复,从而实现AZ级故障容灾。
|
||||
|
||||

|
||||
|
||||
### 服务器选型
|
||||
|
||||
不同的组件对组件有不同的偏重,下面就 Access 接入模块,BlobNode 单机引擎,ClusterManager 元数据管理做个简单的介绍。
|
||||
|
||||
**Access 机器**:计算和内存需求多,因EC编解码属计算密集型任务,需要 CPU 消耗,并且 Access 需要在内存中编解码,也需要消耗内存。当然这个内存消耗和请求并发数有关,可以配置。
|
||||
|
||||
**BlobNode 机器**:BlobNode 是管理磁盘的单机存储引擎,是集群成本的主要组成部分,所以它的部署机型一般是高密磁盘的机型。比如 4U60 盘的就比较好,这种机型也将会是系统最多的类型。
|
||||
|
||||
**ClusterManager 的机器**:元数据中心,它的吞吐能力要求很高,这个必须要部署在高性能的 SSD 盘上,CPU 内存都要好点。
|
||||
|
||||
## 设计总结
|
||||
|
||||
1、 **数据冗余策略**
|
||||
|
||||
我们知道,保障数据耐久性的关键手段就是数据冗余,冗余策略又分为**多副本**(Replica)和**纠删码**(Erasure Code,简称 EC )两种:
|
||||
|
||||
- **多副本策略**( Replica ):把数据复制多份,按照策略放到分布式不同的存储位置,当某份数据损坏时,可从其他副本读取或修复;
|
||||
- **纠删码策略** ( Erasure Code,简称 EC ):将原始数据编码得到冗余数据,并将原始和冗余数据一并存储,以达到容错目的。其基本思想是将n块原始的数据元素通过一定的计算,得到m块冗余元素(校验块);对于这n+m块的元素,当其中任意的m块元素出错(包括原始数据和冗余数据)时,均可以通过对应的重构算法恢复出原来的n块数据
|
||||
多副本与纠删码两者在系统复杂度、数据耐久性、存储成本、读写放大比等方面表现不同:
|
||||
|
||||
多副本实现简单,数据耐久性一般,资源利用率较低、存储成本较高;纠删码实现较复杂,数据耐久性更高,资源利用率更高,存储成本低。
|
||||
|
||||
数据冗余策略如何选型,需从业务的数据规模、访问模型、耐久性及成本需求等多维度综合评估;以OPPO手机云相册业务为例,支撑数亿用户访问,数据体量大,成本诉求强烈,目前已全面使用低成本的纠删码引擎。
|
||||
|
||||
2、**离线/在线EC策略**
|
||||
|
||||
**离线EC**
|
||||
|
||||
多副本策略实现简单,而纠删码数据耐久性高且存储成本低。为兼顾性能和成本,有些产品会同时提供两套系统,数据先写入作为缓存的多副本,再异步迁移到最终的纠删码,即所谓的离线 EC 。这种方式优点在于可提供较低的写入时延(无在线EC的计算开销),又能利用低数据冗余度的纠删码降低成本;
|
||||
|
||||
离线EC缺点也较明显:
|
||||
|
||||
* 架构复杂:包含多副本和纠错码两套存储子系统,系统间涉及数据搬迁,两者相互依赖
|
||||
* 运维不友好:需管理两套存储集群,模块也更多,运维难度及风险较大
|
||||
* IO开销高:数据先写多副本再转存EC,1个业务IO对应后台多份IO,磁盘读写放大多,IOPS及带宽额外开销大
|
||||
**在线EC**
|
||||
|
||||
得益于CPU算力提升和指令集加速,EC编解码计算不再是性能瓶颈,在线 EC 逐步流行。
|
||||
|
||||
所谓**在线EC**是指系统在收到业务原始数据块时,实时同步计算出冗余块,与数据块一并下发存储,无需再做数据的搬迁;相比离线EC,在线EC在架构简洁性、运维成本方面更具优势;两者对比示意如下:
|
||||

|
||||
|
||||
在线EC也存在一些技术挑战:
|
||||
|
||||
* 相比离线EC,数据写入需实时计算得到冗余块,有一定的时间开销
|
||||
* 相比多副本,业务一次读写涉及更多存储节点,扇出大,易出现尾时延
|
||||
* 适合于大文件,小文件有一定读写放大
|
||||
CubeFS对这些问题做了大量针对性优化,使得在线EC在实际生产可落地。
|
||||
|
||||
**3、块EC/条带EC策略**
|
||||
|
||||
计算 EC时数据需切片,如果是 N+M 模式,那么用户数据切成 N 块,再生成 M 块校验块就是一个完整的 EC 条带数据。按照凑一个条带的数据方式我们可以分为“条带EC”"和“块EC”两种方式。
|
||||
|
||||
**块 EC:**
|
||||
|
||||
* 定长条带,要凑满一个条带的数据才能去按照 N+M 切块做 EC ,每个条带长度固定,每个条带块长度固定;
|
||||
* 凑条带的场景有点复杂,会导致一个完整的用户数据可能跨条带,元数据结构复杂,一般使用于离线EC场景;
|
||||

|
||||
|
||||
**条带 EC:**
|
||||
|
||||
* 直接把用户数据按照 N+M 切块做 EC ;
|
||||
* 不需要再凑条带数据,一个用户数据就是完整条带,元数据结构简单;
|
||||

|
||||
|
||||
CubeFS 使用的是更简单、更通用的条带 EC 的方式。
|
||||
|
||||
## 未来方向
|
||||
|
||||
1. 架构精简,降低对非必要组件的依赖
|
||||
2. 小文件读写性能优化
|
||||
3. 三副本卷的支持
|
||||
@ -1,19 +0,0 @@
|
||||
纠删码存储计数揭秘
|
||||
=======================
|
||||
|
||||
TODO
|
||||
|
||||
纠删码引擎系统设计
|
||||
--------------------------
|
||||
|
||||
TODO
|
||||
|
||||
纠删码单机存储引擎
|
||||
---------------------
|
||||
|
||||
TODO
|
||||
|
||||
均衡、巡检与故障自愈
|
||||
---------------------
|
||||
|
||||
TODO
|
||||
@ -1,10 +1,8 @@
|
||||
客户端
|
||||
=========
|
||||
# 客户端
|
||||
|
||||
客户端以用户态可执行程序的形式可以运行在容器中,并且通过FUSE将挂载的卷及文件系统接口提供给其它用户态应用。
|
||||
|
||||
客户端缓存
|
||||
-----------------------
|
||||
## 客户端缓存
|
||||
|
||||
客户端进程在以下几种情况下会使用客户端缓存。
|
||||
|
||||
@ -12,29 +10,31 @@
|
||||
|
||||
客户端为了减少与元数据节点的通信,会缓存inode,dentry以及extent元数据信息。通常意义上,读请求应该能够读到之前所有的写入,但是客户端元数据缓存可能会导致多客户端写同一个文件时的一致性问题。所以,CubeFS的设计中,不同客户端,或者说挂载点,可以同时读一个文件,但是不能够同时写一个文件(注意:不同进程可以从同一个挂载点并发写一个文件)。打开文件时,客户端会强制从元数据节点更新文件元数据信息。
|
||||
|
||||
由于故障恢复时,raft复制组的主节点有可能发生变化,导致客户端缓存的主节点地址无效。因此,客户端在发送请求收到not leader回复时,会轮询重试该复制组的所有节点。重试成功后识别出新的主节点,客户端会缓存新的主节点地址。
|
||||
由于故障恢复时,raft复制组的主节点有可能发生变化,导致客户端缓存的主节点地址无效。因此,客户端在发送请求收到not
|
||||
leader回复时,会轮询重试该复制组的所有节点。重试成功后识别出新的主节点,客户端会缓存新的主节点地址。
|
||||
|
||||
对接FUSE接口
|
||||
-----------------------
|
||||
## 对接FUSE接口
|
||||
|
||||
CubeFS客户端通过对接FUSE为提供用户态文件系统接口。之前,性能较低被认为是用户态文件系统最大的缺点。但是经过多年的发展,FUSE已经在性能上有了很大提高。后续,CubeFS会着手开发内核态文件系统客户端。
|
||||
|
||||
目前来看,FUSE的writeback cache特性并未达到预期的性能提升。FUSE默认的写流程走的是directIO接口,使得每次写入长度较小时会有性能问题,因为每次的写请求都会被推送至后端存储。FUSE的解决方案是writeback cache,即小写入写到缓存页即返回,由内核根据回刷策略推送至后端存储。这样,顺序的小请求会被聚合。但是,在实际生产中,我们发现writeback cache特性作用非常有限,原因是走writecache的写操作触发了内核balance dirty page的流程,使得本应该是响应时间非常短的写操作仍然会等较长时间才返回。这个问题在小的写入时尤其明显。
|
||||
目前来看,FUSE的writeback
|
||||
cache特性并未达到预期的性能提升。FUSE默认的写流程走的是directIO接口,使得每次写入长度较小时会有性能问题,因为每次的写请求都会被推送至后端存储。FUSE的解决方案是writeback
|
||||
cache,即小写入写到缓存页即返回,由内核根据回刷策略推送至后端存储。这样,顺序的小请求会被聚合。但是,在实际生产中,我们发现writeback
|
||||
cache特性作用非常有限,原因是走writecache的写操作触发了内核balance dirty
|
||||
page的流程,使得本应该是响应时间非常短的写操作仍然会等较长时间才返回。这个问题在小的写入时尤其明显。
|
||||
|
||||
## 客户端预热
|
||||
|
||||
客户端预热
|
||||
-----------------------
|
||||
客户端为了提高纠删卷的读取效率,可以通过预热功能将纠删码子系统的数据缓存到副本子系统中。副本子系统中的缓存内容会在预热TTL过期后,自动删除。
|
||||
|
||||
一级缓存(数据缓存)
|
||||
-----------------------
|
||||
## 一级缓存(数据缓存)
|
||||
|
||||
L1Cache是独立于客户端的本地数据缓存服务,对外提供Put/Get/Delete接口,基于数据块(Block)进行缓存读写、淘汰操作,整体结构如下图所示。
|
||||
|
||||
.. image:: pic/block-cache.png
|
||||
:align: center
|
||||
:alt: block cache
|
||||
{.align-center}
|
||||
|
||||
L1Cache缓存服务为本机所有打开一级缓存配置的客户端提供缓存服务。本地缓存数据块与远端存储数据块一一对应,并按块进行索引(BlockKey)访问,数据块索引BlockKey生成方式为:VolumeName_Inode_hex(FileOffset)。数据块索引经过两次取模计算将内存数据块结构映射到本地缓存文件,LocalPath
|
||||
/ hash(BlockKey)%512 / hash(BlockKey)%256 /
|
||||
BlockKey。L1CacheStoreService统一维护全局的BlockKeys,定期按照LRU进行淘汰。
|
||||
|
||||
L1Cache缓存服务为本机所有打开一级缓存配置的客户端提供缓存服务。本地缓存数据块与远端存储数据块一一对应,并按块进行索引(BlockKey)访问,数据块索引BlockKey生成方式为:VolumeName_Inode_hex(FileOffset)。数据块索引经过两次取模计算将内存数据块结构映射到本地缓存文件,LocalPath / hash(BlockKey)%512 / hash(BlockKey)%256 / BlockKey。L1CacheStoreService统一维护全局的BlockKeys,定期按照LRU进行淘汰。
|
||||
|
||||
L1Cache服务重启时自动扫描磁盘上的缓存数据,并重建缓存索引信息。缓存目录的增加和退出不涉及数据迁移,丢失的缓存数据重新缓存,残留的缓存数据最终会被LRU淘汰。
|
||||
L1Cache服务重启时自动扫描磁盘上的缓存数据,并重建缓存索引信息。缓存目录的增加和退出不涉及数据迁移,丢失的缓存数据重新缓存,残留的缓存数据最终会被LRU淘汰。
|
||||
45
docs-zh/source/design/datanode.md
Normal file
@ -0,0 +1,45 @@
|
||||
# 副本子系统
|
||||
|
||||
副本子系统的设计是为了满足大、小文件支持顺序随机访问的多租户需求。采用两种不同的复制协议,以确保副本之间的强一致性,并在性能和代码可用性上进行一些权衡。也可以用作Cache节点,搭建纠删码卷的二级cache
|
||||
|
||||
{.align-center}
|
||||
|
||||
## 系统特性
|
||||
|
||||
- 大文件存储
|
||||
|
||||
对于大文件,内容存储为一个或多个扩展数据块的序列,这些扩展数据块可以分布在不同数据节点上的不同数据分区中。将新文件写入扩展数据块存储区始终会导致数据以新扩展数据块的零偏移量写入,这样就不需要在扩展数据块内进行偏移。文件的最后一个范围不需要通过填充来补齐大小限制(即该范围没有空洞),并且不会存储来自其他文件的数据。
|
||||
|
||||
- 小文件存储
|
||||
|
||||
将多个小文件的内容聚合存储在一个文件内,并将每个文件内容的物理偏移量记录在相应的元数据中。删除文件内容(释放此文件占用的磁盘空间)是通过底层文件系统提供的文件穿洞接口(`fallocate()`)实现的。这种设计的优点是不需要实现垃圾回收机制,因此在一定程度上避免使用从逻辑偏移到物理偏移的映射。
|
||||
|
||||
- 复制
|
||||
成员间的文件复制,根据文件写入模式,CubeFS采用不同的复制策略。
|
||||
|
||||
当文件按顺序写入CubeFS时,使用主备份复制协议来确保与优化的IO吞吐量的强一致性。
|
||||
|
||||
{.align-center}
|
||||
|
||||
在随机写入时覆盖现有的文件内容时,我们采用了一种基于Multi-Raft的复制协议,该协议类似于元数据子系统中使用的协议,以确保强一致性。
|
||||
|
||||
{.align-center}
|
||||
|
||||
- 故障恢复
|
||||
|
||||
由于存在两种不同的复制协议,当发现复制副本上的故障时,我们首先通过检查每个数据块的长度并使所有数据块对齐,启动基于主备份的复制协议的恢复。一旦这个处理完成,我们就开始在我们的基于Multi-Raft的恢复。
|
||||
|
||||
- 缓存数据
|
||||
|
||||
通过使用缓存类型的分区,实现缓存热数据,为纠删码卷提供缓存加速能力,在达到阈值的时候,动态的淘汰缓存中的冷数据。
|
||||
|
||||
## HTTP接口
|
||||
|
||||
| API | 方法 | 参数 | 描述 |
|
||||
|-------------|------|--------------------------------|------------------------------------------|
|
||||
| /disks | GET | N/A | 获取磁盘的列表和信息。 |
|
||||
| /partitions | GET | N/A | 获取所有数据组的信息。 |
|
||||
| /partition | GET | partitionId[int] | 获取特定数据组的详细信息。 |
|
||||
| /extent | GET | partitionId[int]&extentId[int] | 获取特定数据组里面特定extent文件的信息。 |
|
||||
| /stats | GET | N/A | 获取DATA节点的信息。 |
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
副本子系统
|
||||
===================
|
||||
|
||||
副本子系统的设计是为了满足大、小文件支持顺序随机访问的多租户需求。采用两种不同的复制协议,以确保副本之间的强一致性,并在性能和代码可用性上进行一些权衡。也可以用作Cache节点,搭建纠删码卷的二级cache
|
||||
|
||||
.. image:: ../pic/data-subsystem.png
|
||||
:align: center
|
||||
:alt: Data Subsystem Architecture
|
||||
|
||||
系统特性
|
||||
----------
|
||||
|
||||
- 大文件存储
|
||||
|
||||
对于大文件,内容存储为一个或多个扩展数据块的序列,这些扩展数据块可以分布在不同数据节点上的不同数据分区中。将新文件写入扩展数据块存储区始终会导致数据以新扩展数据块的零偏移量写入,这样就不需要在扩展数据块内进行偏移。文件的最后一个范围不需要通过填充来补齐其大小限制(即该范围没有空洞),并且不会存储来自其他文件的数据。
|
||||
|
||||
- 小文件存储
|
||||
|
||||
将多个小文件的内容聚合存储在一个文件内,并将每个文件内容的物理偏移量记录在相应的元数据中。删除文件内容(释放此文件占用的磁盘空间)是通过底层文件系统提供的文件穿洞接口(fallocate())实现的。这种设计的优点是不需要实现垃圾回收机制,因此在一定程度上避免使用从逻辑偏移到物理偏移的映射。
|
||||
|
||||
- 复制
|
||||
|
||||
成员间的文件复制,根据文件写入模式,CubeFS采用不同的复制策略。
|
||||
|
||||
当文件按顺序写入CubeFS时,使用主备份复制协议来确保与优化的IO吞吐量的强一致性。
|
||||
|
||||
.. image:: ../pic/workflow-sequential-write.png
|
||||
:align: center
|
||||
|
||||
|
||||
在随机写入时覆盖现有的文件内容时,我们采用了一种基于Multi-Raft的复制协议,该协议类似于元数据子系统中使用的协议,以确保强一致性。
|
||||
|
||||
.. image:: ../pic/workflow-overwriting.png
|
||||
:align: center
|
||||
|
||||
|
||||
|
||||
- 故障恢复
|
||||
|
||||
由于存在两种不同的复制协议,当发现复制副本上的故障时,我们首先通过检查每个数据块的长度并使所有数据块对齐,启动基于主备份的复制协议的恢复。一旦这个处理完成,我们就开始在我们的基于Multi-Raft的恢复。
|
||||
|
||||
- 缓存数据
|
||||
|
||||
通过使用缓存类型的分区,实现缓存热数据,为纠删码卷提供缓存加速能力,在达到阈值的时候,动态的淘汰缓存中的冷数据。
|
||||
|
||||
HTTP接口
|
||||
-----------
|
||||
|
||||
.. csv-table::
|
||||
:header: "API", "方法", "参数", "描述"
|
||||
|
||||
|
||||
"/disks", "GET", "N/A", "获取磁盘的列表和信息。"
|
||||
"/partitions", "GET", "N/A", "获取所有数据组的信息。 "
|
||||
"/partition", "GET", "partitionId[int]", "获取特定数据组的详细信息。"
|
||||
"/extent", "GET", "partitionId[int]&extentId[int]", "获取特定数据组里面特定extent文件的信息。"
|
||||
"/stats", "GET", "N/A", "获取DATA节点的信息。"
|
||||
@ -1,11 +1,9 @@
|
||||
资源管理子系统
|
||||
==================
|
||||
# 资源管理子系统
|
||||
|
||||
Master负责异步的处理不同类型的任务, 比如 创建/删除/更新/比对副本是否一致等数据分片和元数据分片的操作,管理数据节点和元数据节点的存活状态,创建和维护卷信息。
|
||||
Master有多个节点,它们之间通过raft算法保证元数据一致性,并且把元数据持久化到RocksDB。
|
||||
|
||||
基于利用率的分布策略
|
||||
------------------------
|
||||
## 基于利用率的分布策略
|
||||
|
||||
基于利用率的分布策略放置文件元数据和内容是Master最主要的特征,此分布策略能够更高效的利用集群资源。
|
||||
数据分片和元数据分片的分布策略工作流程:
|
||||
@ -16,14 +14,12 @@ Master有多个节点,它们之间通过raft算法保证元数据一致性,
|
||||
1. 当新节点加入时,不需要重新做数据均衡,避免了因为数据迁移带来的开销。
|
||||
2. 因为使用统一的分布策略, 显著降低了产生热点数据的可能性。
|
||||
|
||||
## 副本放置
|
||||
|
||||
副本放置
|
||||
-----------
|
||||
Master确保一个分片的多个副本都在不同的机器上。
|
||||
|
||||
Master确保一个分片的多个副本都在不同的机器上.
|
||||
## 拆分元数据分片
|
||||
|
||||
拆分元数据分片
|
||||
-----------------
|
||||
满足下面任意一个条件,元数据分片将会被拆分
|
||||
1. 元数据节点内存使用率达到设置的阈值,比如总内存是64GB,阈值是0.75,如果元数据节点使用的内存达到48GB,该节点上的所有元数据分片都将会被拆分.
|
||||
2. 元数据分片占用的内存达到16GB
|
||||
@ -31,9 +27,6 @@ Master确保一个分片的多个副本都在不同的机器上.
|
||||
只有数据分片ID是卷所有数据分片中ID最大的,才会真正被拆分。假设数据分片A符合拆分条件,其inode范围是[0,正无穷),
|
||||
则拆分后A的范围为[0,A.MaxInodeID+step),新生成的B分片的范围是[A.MaxInodeID+step+1,正无穷),其中step是步长,默认是2的24方.MaxInodeID是由元数据节点汇报。
|
||||
|
||||
异常处理
|
||||
-----------
|
||||
|
||||
如果数据/元数据分片某个副本不可用 (硬盘失败、硬件错误等), 该副本上的数据最终会被迁移到新的副本上.
|
||||
|
||||
## 异常处理
|
||||
|
||||
如果数据/元数据分片某个副本不可用 (硬盘失败、硬件错误等), 该副本上的数据最终会被迁移到新的副本上。
|
||||
15
docs-zh/source/design/metanode.md
Normal file
@ -0,0 +1,15 @@
|
||||
# 元数据子系统
|
||||
|
||||
元数据子系统是一个以内存为中心的分布式数据结构,是由一个或多个元数据分片组成。元数据子系统数据使用multiraft来充分使用服务器资源和保障数据高可用及强一致性,可以很方便的迁移资源,并通过分裂实现横向扩展。
|
||||
|
||||
## 元数据内部设计
|
||||
|
||||
每个元数据可以包含成百上千的元数据分片,每个分片由InodeTree(BTree)和DentryTree(BTree)组成。每个Inode代表文件系统中的一个文件或目录, 每个dentry代表一个目录项,dentry由parentId和name组成。在DentryTree中,以PartentId和name组成索引,进行存储和检索;在InodeTree中,则以inode id进行索引。使用multiRaft协议保障高可用性和数据一致性复制,且每个节点集合会包含大量的分片组,每个分片组对应一个raft group;每个分片组隶属于某个volume;每个分片组都是某个volume的一段元数据范围(inode id范[100-20000) );元数据子系统通过分裂来完成动态扩容;当性一分片组的性能(包含如下指标:内存)紧接临近值时,资源管理器服务会预估一个结束点,并通知此组节点设备,只服务到此点之前的数据,同时也会新选出一组节点,并动态加入到当前业务系统中,新节点组其实点刚好是上个节点组的结束点位置。
|
||||
|
||||
## 复制
|
||||
|
||||
元数据更新的复制是以元数据分片为单位的。复制强一致性是通过Raft改良版本,MultiRaft来实现的。MultiRaft减少了心跳通信的负担。
|
||||
|
||||
## 故障恢复
|
||||
|
||||
内存元数据分片通过快照的方式持久化到磁盘以作备份和恢复使用。日志压缩技术被用来减小日志文件大小和恢复时间。 值得一提的是,元数据操作有可能会导致孤儿inode,即只有inode但是没有对应的dentry。为了减少这种情况的发生,首先,元数据节点通过Raft保证高可用,单点故障后可以迅速恢复;其次,客户端保证在一定时间内进行重试。
|
||||
@ -1,4 +0,0 @@
|
||||
元数据管理设计
|
||||
=================
|
||||
|
||||
TODO
|
||||
130
docs-zh/source/design/objectnode.md
Normal file
@ -0,0 +1,130 @@
|
||||
# 对象存储子系统
|
||||
|
||||
对象存储系统提供兼容S3的对象存储接口。它使得CubeFS成为一个可以将两种通用类型接口进行融合的存储(POSIX和S3兼容接口)。可以使用户使用原生的Amazon
|
||||
S3 SDK操作CubeFS中的文件。
|
||||
|
||||
## 框架
|
||||
|
||||
{.align-center}
|
||||
|
||||
ObjectNode是一个功能性的子系统节点。它根据需要从资源管理器(Master)获取卷视图(卷拓扑)。
|
||||
每个ObjectNode直接与元数据子系统(MetaNode)和副本子系统(DataNode)通信。
|
||||
|
||||
ObjectNode是一种无状态设计,具有很高的可扩展性,能够直接操作CubeFS集群中存储的所有文件,而无需任何卷装入操作。
|
||||
*暂不支持纠删码卷*
|
||||
|
||||
## 特性
|
||||
|
||||
- 支持原生的Amazon S3 SDKs的对象存储接口
|
||||
- 支持两种通用接口的融合存储(POSIX和S3兼容接口)
|
||||
- 无状态和高可靠性
|
||||
|
||||
## 语义转换
|
||||
|
||||
基于原有POSIX兼容性的设计。每个来自对象存储接口的文件操作请求都需要对POSIX进行语义转换。
|
||||
|
||||
| POSIX | Object Storage |
|
||||
|----------|----------------|
|
||||
| `Volume` | `Bucket` |
|
||||
| `Path` | `Key` |
|
||||
|
||||
**示例:**
|
||||
|
||||
{.align-center}
|
||||
|
||||
> Put object \'*example/a/b.txt*\' will be create and write data to file
|
||||
> \'*/a/b.txt*\' in volume \'*example*\'.
|
||||
|
||||
## 用户
|
||||
|
||||
在使用对象存储功能前,需要先通过资源管理器创建用户。创建用户的同时,会为每个用户生成
|
||||
*AccessKey* 和 *SecretKey* ,其中 *AccessKey*
|
||||
是整个CubeFS集群中唯一的16个字符的字符串。
|
||||
|
||||
CubeFS以卷的 **Owner** 字段作为用户ID。创建用户的方式有两种:
|
||||
|
||||
1. 通过资源管理器的API创建卷时,如果集群中没有与该卷的Owner同名的用户时,会自动创建一个用户ID为Owner的用户
|
||||
2. 调用资源管理器的用户管理API创建用户,链接:
|
||||
`/admin-api/master/user`{.interpreted-text role="doc"}
|
||||
|
||||
## 授权与鉴权
|
||||
|
||||
对象存储接口中的签名验证算法与Amazon
|
||||
S3服务完全兼容。用户可以通过管理API获取用户信息,请参见 **Get User
|
||||
Information** ,链接: `/admin-api/master/user`{.interpreted-text
|
||||
role="doc"} 。从中获取 *AccessKey* 和 *SecretKey*
|
||||
后,即可利用算法生成签名来访问对象存储功能。
|
||||
|
||||
用户对于自己名下的卷,拥有所有的访问权限。用户可以授予其他用户指定权限来访问自己名下的卷。权限分为以下三类:
|
||||
|
||||
- 只读或读写权限;
|
||||
- 单个操作的权限,比如GetObject、PutObject等;
|
||||
- 自定义权限。
|
||||
|
||||
当用户使用对象存储功能进行某种操作时,CubeFS会鉴别该用户是否拥有当前操作的权限。
|
||||
|
||||
## 临时隐藏数据
|
||||
|
||||
以原子方式在对象存储接口中进行写操作。每个写操作都将创建数据并将其写入一个不可见的临时对象。ObjectNode中的volume运算符将文件数据放入临时文件,临时文件的元数据中只有\'
|
||||
**inode**\'而没有\'**dentry**\'。当所有文件数据都成功存储时,volume操作符在元数据中创建或更新\'**dentry**\'使其对用户可见。
|
||||
|
||||
## 对象名称冲突(重要)
|
||||
|
||||
POSIX和对象存储是两种不同类型的存储产品,对象存储是一种键-值对存储服务。所以在对象存储中,名称为\'*a/b/c*\'和名称为\'*a/b*
|
||||
\'的对象是两个完全没有冲突的对象。
|
||||
|
||||
不过CubeFS是基于POSIX设计的。根据语义转换规则,对象名\'*a/b/c*\'中的\'*b*\'部分转换为文件夹\'*a*\'下的文件夹\'*b*\',对象名\'
|
||||
*a/b*\'中的\'*b*\'部分转换为文件夹\'*a*\'下的文件\'*b*\'。
|
||||
|
||||
类似于上面这样的对象名称在CubeFS中是冲突的。
|
||||
|
||||
## 支持的S3兼容接口
|
||||
|
||||
### 桶接口
|
||||
|
||||
| API | Reference |
|
||||
|---------------------|------------------------------------------------------------------------------|
|
||||
| `HeadBucket` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html> |
|
||||
| `GetBucketLocation` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html> |
|
||||
|
||||
### 对象接口
|
||||
|
||||
| API | Reference |
|
||||
|-----------------|--------------------------------------------------------------------------|
|
||||
| `HeadObject` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html> |
|
||||
| `PutObject` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html> |
|
||||
| `GetObject` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html> |
|
||||
| `ListObjects` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html> |
|
||||
| `ListObjectsV2` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html> |
|
||||
| `DeleteObject` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html> |
|
||||
| `DeleteObjects` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html> |
|
||||
| `CopyObject` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html> |
|
||||
|
||||
### 并发上传接口
|
||||
|
||||
| API | Reference |
|
||||
|---------------------------|------------------------------------------------------------------------------------|
|
||||
| `CreateMultipartUpload` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html> |
|
||||
| `ListMultipartUploads` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html> |
|
||||
| `AbortMultipartUpload` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html> |
|
||||
| `CompleteMultipartUpload` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html> |
|
||||
| `ListParts` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html> |
|
||||
| `UploadPart` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html> |
|
||||
| `UploadPartCopy` | <https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html> |
|
||||
|
||||
## 支持的SDK
|
||||
|
||||
Object Node提供兼容S3的对象存储接口,所以可以直接使用原生的Amazon S3
|
||||
SDKs来操作文件。
|
||||
|
||||
| Name | Language | Link |
|
||||
|-----------------------------------|--------------|-------------------------------------------|
|
||||
| AWS SDK for Java | `Java` | <https://aws.amazon.com/sdk-for-java/> |
|
||||
| AWS SDK for JavaScript | `JavaScript` | <https://aws.amazon.com/sdk-for-browser/> |
|
||||
| AWS SDK for JavaScript in Node.js | `JavaScript` | <https://aws.amazon.com/sdk-for-node-js/> |
|
||||
| AWS SDK for Go | `Go` | <https://docs.aws.amazon.com/sdk-for-go/> |
|
||||
| AWS SDK for PHP | `PHP` | <https://aws.amazon.com/sdk-for-php/> |
|
||||
| AWS SDK for Ruby | `Ruby` | <https://aws.amazon.com/sdk-for-ruby/> |
|
||||
| AWS SDK for .NET | `.NET` | <https://aws.amazon.com/sdk-for-net/> |
|
||||
| AWS SDK for C++ | `C++` | <https://aws.amazon.com/sdk-for-cpp/> |
|
||||
| Boto3 | `Python` | <http://boto.cloudhackers.com> |
|
||||
@ -1,133 +0,0 @@
|
||||
对象存储 (ObjectNode)
|
||||
=============================
|
||||
|
||||
对象存储系统提供兼容S3的对象存储接口。它使得CubeFS成为一个可以将两种通用类型接口进行融合的存储(POSIX和S3兼容接口)。可以使用户使用原生的Amazon S3 SDK操作CubeFS中的文件。
|
||||
|
||||
框架
|
||||
---------
|
||||
|
||||
.. image:: ../pic/cfs-object-subsystem-structure.png
|
||||
:align: center
|
||||
|
||||
ObjectNode是一个功能性的子系统节点。它根据需要从资源管理器(Master)获取卷视图(卷拓扑)。
|
||||
每个ObjectNode直接与元数据子系统(MetaNode)和副本子系统(DataNode)通信。
|
||||
|
||||
ObjectNode是一种无状态设计,具有很高的可扩展性,能够直接操作CubeFS集群中存储的所有文件,而无需任何卷装入操作。 *暂不支持纠删码卷*
|
||||
|
||||
特性
|
||||
--------
|
||||
|
||||
- 支持原生的Amazon S3 SDKs的对象存储接口
|
||||
- 支持两种通用接口的融合存储(POSIX和S3兼容接口)
|
||||
- 无状态和高可靠性
|
||||
|
||||
语义转换
|
||||
-------------------
|
||||
基于原有POSIX兼容性的设计。每个来自对象存储接口的文件操作请求都需要对POSIX进行语义转换。
|
||||
|
||||
.. csv-table::
|
||||
:header: "POSIX", "Object Storage"
|
||||
|
||||
"``Volume``", "``Bucket``"
|
||||
"``Path``", "``Key``"
|
||||
|
||||
**示例:**
|
||||
|
||||
.. image:: ../pic/cfs-object-subsystem-semantic.png
|
||||
:align: center
|
||||
|
||||
Put object '*example/a/b.txt*' will be create and write data to file '*/a/b.txt*' in volume '*example*'.
|
||||
|
||||
用户
|
||||
--------------
|
||||
在使用对象存储功能前,需要先通过资源管理器创建用户。创建用户的同时,会为每个用户生成 *AccessKey* 和 *SecretKey* ,其中 *AccessKey* 是整个CubeFS集群中唯一的16个字符的字符串。
|
||||
|
||||
CubeFS以卷的 **Owner** 字段作为用户ID。创建用户的方式有两种:
|
||||
|
||||
1. 通过资源管理器的API创建卷时,如果集群中没有与该卷的Owner同名的用户时,会自动创建一个用户ID为Owner的用户
|
||||
|
||||
2. 调用资源管理器的用户管理API创建用户,链接: :doc:`/admin-api/master/user`
|
||||
|
||||
授权与鉴权
|
||||
--------------
|
||||
对象存储接口中的签名验证算法与Amazon S3服务完全兼容。用户可以通过管理API获取用户信息,请参见 **Get User Information** ,链接: :doc:`/admin-api/master/user` 。从中获取 *AccessKey* 和 *SecretKey* 后,即可利用算法生成签名来访问对象存储功能。
|
||||
|
||||
用户对于自己名下的卷,拥有所有的访问权限。用户可以授予其他用户指定权限来访问自己名下的卷。权限分为以下三类:
|
||||
|
||||
- 只读或读写权限;
|
||||
- 单个操作的权限,比如GetObject、PutObject等;
|
||||
- 自定义权限。
|
||||
|
||||
当用户使用对象存储功能进行某种操作时,CubeFS会鉴别该用户是否拥有当前操作的权限。
|
||||
|
||||
临时隐藏数据
|
||||
-------------------------
|
||||
以原子方式在对象存储接口中进行写操作。每个写操作都将创建数据并将其写入一个不可见的临时对象。ObjectNode中的volume运算符将文件数据放入临时文件,临时文件的元数据中只有'**inode**'而没有'**dentry**'。当所有文件数据都成功存储时,volume操作符在元数据中创建或更新'**dentry**'使其对用户可见。
|
||||
|
||||
对象名称冲突(重要)
|
||||
--------------------------------
|
||||
POSIX和对象存储是两种不同类型的存储产品,对象存储是一种键-值对存储服务。所以在对象存储中,名称为'*a/b/c*'和名称为'*a/b*'的对象是两个完全没有冲突的对象。
|
||||
|
||||
不过CubeFS是基于POSIX设计的。根据语义转换规则,对象名'*a/b/c*'中的'*b*'部分转换为文件夹'*a*'下的文件夹'*b*',对象名'*a/b*'中的'*b*'部分转换为文件夹'*a*'下的文件'*b*'。
|
||||
|
||||
类似于上面这样的对象名称在CubeFS中是冲突的。
|
||||
|
||||
支持的S3兼容接口
|
||||
----------------------------
|
||||
|
||||
桶接口
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. csv-table::
|
||||
:header: "API", "Reference"
|
||||
|
||||
"``HeadBucket``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html"
|
||||
"``GetBucketLocation``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html"
|
||||
|
||||
对象接口
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. csv-table::
|
||||
:header: "API", "Reference"
|
||||
|
||||
"``HeadObject``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html"
|
||||
"``PutObject``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html"
|
||||
"``GetObject``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html"
|
||||
"``ListObjects``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html"
|
||||
"``ListObjectsV2``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html"
|
||||
"``DeleteObject``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html"
|
||||
"``DeleteObjects``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html"
|
||||
"``CopyObject``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html"
|
||||
|
||||
并发上传接口
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. csv-table::
|
||||
:header: "API", "Reference"
|
||||
|
||||
"``CreateMultipartUpload``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html"
|
||||
"``ListMultipartUploads``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html"
|
||||
"``AbortMultipartUpload``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html"
|
||||
"``CompleteMultipartUpload``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html"
|
||||
"``ListParts``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html"
|
||||
"``UploadPart``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html"
|
||||
"``UploadPartCopy``", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html"
|
||||
|
||||
支持的SDK
|
||||
--------------
|
||||
Object Node提供兼容S3的对象存储接口,所以可以直接使用原生的Amazon S3 SDKs来操作文件。
|
||||
|
||||
.. csv-table::
|
||||
:header: "Name", "Language", "Link"
|
||||
|
||||
"AWS SDK for Java", "``Java``", "https://aws.amazon.com/sdk-for-java/"
|
||||
"AWS SDK for JavaScript", "``JavaScript``", "https://aws.amazon.com/sdk-for-browser/"
|
||||
"AWS SDK for JavaScript in Node.js", "``JavaScript``", "https://aws.amazon.com/sdk-for-node-js/"
|
||||
"AWS SDK for Go", "``Go``", "https://docs.aws.amazon.com/sdk-for-go/"
|
||||
"AWS SDK for PHP", "``PHP``", "https://aws.amazon.com/sdk-for-php/"
|
||||
"AWS SDK for Ruby", "``Ruby``", "https://aws.amazon.com/sdk-for-ruby/"
|
||||
"AWS SDK for .NET", "``.NET``", "https://aws.amazon.com/sdk-for-net/"
|
||||
"AWS SDK for C++", "``C++``", "https://aws.amazon.com/sdk-for-cpp/"
|
||||
"Boto3", "``Python``", "http://boto.cloudhackers.com"
|
||||
|
||||
|
||||
BIN
docs-zh/source/design/pic/ec-append.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
docs-zh/source/design/pic/ec-arc.png
Normal file
|
After Width: | Height: | Size: 238 KiB |
BIN
docs-zh/source/design/pic/ec-az.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
docs-zh/source/design/pic/ec-b-shard.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
docs-zh/source/design/pic/ec-blob.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
docs-zh/source/design/pic/ec-blobnode-data.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
docs-zh/source/design/pic/ec-block.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
docs-zh/source/design/pic/ec-chunk.png
Normal file
|
After Width: | Height: | Size: 219 KiB |
BIN
docs-zh/source/design/pic/ec-crc.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
docs-zh/source/design/pic/ec-disk.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
docs-zh/source/design/pic/ec-get.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
docs-zh/source/design/pic/ec-online.png
Normal file
|
After Width: | Height: | Size: 183 KiB |
BIN
docs-zh/source/design/pic/ec-opt.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
docs-zh/source/design/pic/ec-put.png
Normal file
|
After Width: | Height: | Size: 184 KiB |
BIN
docs-zh/source/design/pic/ec-raft.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
docs-zh/source/design/pic/ec-read.png
Normal file
|
After Width: | Height: | Size: 161 KiB |
BIN
docs-zh/source/design/pic/ec-recycle.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
docs-zh/source/design/pic/ec-shard-d.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
docs-zh/source/design/pic/ec-shard.png
Normal file
|
After Width: | Height: | Size: 331 KiB |
BIN
docs-zh/source/design/pic/ec-stripe.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
docs-zh/source/design/pic/ec-tiny.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
docs-zh/source/design/pic/ec-volume.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
docs-zh/source/design/pic/ec.png
Normal file
|
After Width: | Height: | Size: 277 KiB |
1
docs-zh/source/faq/build.md
Normal file
@ -0,0 +1 @@
|
||||
# 编译问题
|
||||
1
docs-zh/source/faq/fuse.md
Normal file
@ -0,0 +1 @@
|
||||
# Fuse客户端问题
|
||||
@ -5,7 +5,8 @@
|
||||
:maxdepth: 2
|
||||
:caption: 概览
|
||||
|
||||
overview
|
||||
overview/introduction
|
||||
overview/architecture
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
@ -23,7 +24,7 @@
|
||||
|
||||
user-guide/hotvol
|
||||
user-guide/coldvol
|
||||
user-guide/datanode
|
||||
user-guide/cache
|
||||
user-guide/file
|
||||
user-guide/objectnode
|
||||
user-guide/hadoop
|
||||
@ -49,7 +50,7 @@
|
||||
.. toctree::
|
||||
:maxdepth: 0
|
||||
:caption: 测试评估
|
||||
|
||||
|
||||
evaluation/env
|
||||
evaluation/tiny
|
||||
evaluation/io
|
||||
@ -59,26 +60,24 @@
|
||||
:maxdepth: 2
|
||||
:caption: 设计文档
|
||||
|
||||
design/master
|
||||
design/metanode
|
||||
design/blobstore.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: 开发指南
|
||||
|
||||
dev/guide
|
||||
dev/code
|
||||
design/datanode
|
||||
design/blobstore
|
||||
design/objectnode
|
||||
design/client
|
||||
design/authnode
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 0
|
||||
:caption: 社区
|
||||
|
||||
community/contributing
|
||||
community/user
|
||||
community/overview
|
||||
community/article
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: 常见问题
|
||||
:caption: FAQ
|
||||
|
||||
faq
|
||||
faq/build
|
||||
faq/fuse
|
||||
|
||||
23
docs-zh/source/overview/architecture.md
Normal file
@ -0,0 +1,23 @@
|
||||
# 技术架构
|
||||
|
||||

|
||||
|
||||
CubeFS由 **元数据子系统(Metadata Subsystem)** ,**数据子系统(Data Subsystem)** 和 **Master节点(Master)** 以及 **对象子系统(Object Subsystem)** 组成,可以通过POSIX/HDFS/S3接口访问存储数据。
|
||||
|
||||
- **资源管理节点**:由多个Master节点组成,负责异步处理不同类型的任务,如管理数据分片与元数据分片(包括创建、删除、更新以及一致性检查等),检查数据节点或者元数据节点的健康状态,维护管理卷信息等
|
||||
|
||||
> Master节点可以有多个,节点之前通过Raft算法保证元数据的一致性,并且持久化到RocksDB中。
|
||||
|
||||
- **元数据子系统**:由多个Meta Node节点组成,多个元数据分片(Meta Partition)和Raft实例(基于Multi-Raft的示例)组成,每个元数据分片表示一个Inode范围元数据,其中包含两个内存B-Tree数:inode BTree与dentry BTree。
|
||||
|
||||
> 元数据实例最少需要3个,支持水平扩容
|
||||
|
||||
- **数据子系统**:分为副本子系统和纠删码子系统,两种子系统可同时存在,也都可单独存在:
|
||||
- 副本子系统由Data Node组成,每个节点管理一组 **数据分片**,多个节点的**数据分片**构成一个副本组;
|
||||
- 纠删码子系统由多个BlobNode节点组成,每个节点管理一组**数据块**,多个节点的**数据块**构成一个纠删码条带。
|
||||
|
||||
> 数据节点支持水平扩容
|
||||
|
||||
- **对象子系统**:由对象节点组成,提供了兼容标准S3语义的访问协议,可以通过Amazon S3 SDK或者是s3cmd等工具访问存储资源。
|
||||
|
||||
- **卷**:逻辑上的概念,由多个元数据和数据分片组成,从客户端的角度看,卷可以被看作是可被容器访问的文件系统实例。从对象存储的角度来看,一个卷对应着一个bucket。一个卷可以在多个容器中挂载,使得文件可以被不同客户端同时访问。
|
||||
73
docs-zh/source/overview/introduction.md
Normal file
@ -0,0 +1,73 @@
|
||||
# 什么是CubeFS
|
||||
|
||||
## 简介
|
||||
CubeFS是新一代云原生存储产品,目前是云原生计算基金会(CNCF)托管的孵化阶段开源项目,
|
||||
兼容S3、POSIX、HDFS等数据访问协议,支持多副本与纠删码两种存储引擎,为用户提供多租户、
|
||||
多AZ部署以及跨区域复制等多种特性,广泛应用于大数据、AI、容器平台、数据库、中间件存算分离、数据共享以及数据保护等场景。
|
||||
|
||||
<video width="100%" height="300" controls>
|
||||
<source src="https://ocs-cn-north1.heytapcs.com/cubefs/community/video1657061611.mp4" type="video/mp4">
|
||||
</video>
|
||||
|
||||
## 系统特性
|
||||
|
||||
### 多协议
|
||||
|
||||
CubeFS支持多种数据访问协议以满足不同的应用场景,协议之间可以无缝转换,不再需要元数据或数据的迁移,让一份数据可以多协议访问。
|
||||
|
||||
- **POSIX兼容**:兼容POSIX接口,让上层应用的开发变得及其简单,就跟使用本地文件系统一样便捷。此外,CubeFS在实现时放松了对POSIX语义的一致性要求来兼顾文件和元文件操作的性能。
|
||||
- **对象存储兼容**:兼容AWS的S3对象存储协议,用户可以使用原生的Amazon S3 SDK管理CubeFS中的资源。
|
||||
- **Hadoop协议兼容**:兼容Hadoop FileSystem接口协议,用户可以使用CubeFS来替换Hadoop 文件系统( HDFS ),做到上层业务无感。
|
||||
|
||||
### 双引擎
|
||||
|
||||
CubeFS支持两种不同的存储引擎,用户可以自由的选择是采用多副本模式或者是纠删码模式,又或者是两种协议并存,比如选择多副本作为数据缓存层以提升数据的访问性能,选择纠删码引擎作为冷数据的底座以降低存储成本。
|
||||
|
||||
- **多副本存储引擎**:副本之间的数据为镜像关系,通过强一致的复制协议来保证副本之间的数据一致性,用户可以根据应用场景灵活的配置不同副本数。
|
||||
- **纠删码存储引擎**:纠删码引擎具备高可靠、高可用、低成本、支持超大规模(EB)的特性,不同AZ以及不同纠删码模式可以灵活搭配。
|
||||
|
||||
### 可扩展
|
||||
|
||||
CubeFS可以帮助你轻松组建PB或者EB级规模的分布式存储系统,不管是元数据模块还是数据模块都支持无限水平扩展。
|
||||
|
||||
### 高性能
|
||||
|
||||
- **元数据管理**:元数据集群为内存元数据存储,在设计上使用两个B-Tree(inodeBTree与dentryBTree)来管理索引,进而提升元数据访问性能;
|
||||
- **强一致副本协议**:CubeFS根据文件写入方式的不同采用不同的复制协议来保证副本间的数据一致性。(如果文件按照顺序写入,则会使用主备复制协议来优化IO吞吐量;如果是随机写入覆盖现有文件内容时,则是采用一种基于Multi-Raft的复制协议,来确保数据的强一致性);
|
||||
- **多级缓存**:纠删码卷支持多级缓存加速能力,针对热点数据,提供更高数据访问性能:
|
||||
- 本地缓存:可以在Client机器上同机部署BlockCache组件,管理本地磁盘作为本地缓存. 可以不经过网络读取本地Cache当中的数据, 容量受本地磁盘限制;
|
||||
- 全局缓存:使用副本组件DataNode搭建的分布式全局Cache, 比如可以通过部署客户端同机房的SSD磁盘的DataNode作为全局cache, 相对于本地cache, 需要经过网络, 但是容量更大, 可动态扩缩容, 副本数可调。
|
||||
|
||||

|
||||
|
||||
### 多租户
|
||||
|
||||
CubeFS具有租户的概念,可以创建不同的租户,租户之间的数据隔离,同时也支持租户与租户之间的数据共享,以提升整个系统的资源利用率
|
||||
|
||||
## 应用场景
|
||||
|
||||
CubeFS作为一个云原生的分布式存储平台,提供了多种访问协议,因此其应用场景也非常广泛,下面简单介绍几种比较典型的应用场景
|
||||
|
||||
### 大数据分析
|
||||
|
||||
兼容HDFS协议,为Hadoop生态(如Spark、Hive)提供统一存储底座,为计算引擎提供无限的存储空间以及大带宽的数据存储能力。
|
||||
|
||||
### 深度训练/机器学习
|
||||
|
||||
作为分布式并行文件系统,支撑AI训练、模型存储及分发、IO加速等需求。
|
||||
|
||||
### 容器共享存储
|
||||
|
||||
容器集群可以将容器镜像的配置文件或初始化加载数据存储在CubeFS上,在容器批量加载时实时读取。多POD间通过CubeFS共享持久化数据,在POD故障时可以进行快速故障切换。
|
||||
|
||||
### 数据库&中间件
|
||||
|
||||
为数据库应用如MySQL、ElasticSearch、ClickHouse提供高并发、低时延云盘服务,实现彻底的存算分离。
|
||||
|
||||
### 在线服务
|
||||
|
||||
为在线业务(如广告、点击流、搜索)或终端用户的图、文、音视频等内容提供高可靠、低成本的对象存储服务。
|
||||
|
||||
### 传统NAS上云
|
||||
|
||||
替换线下传统本地存储及NAS,助力IT业务上云。
|
||||
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 44 KiB |
@ -1,4 +0,0 @@
|
||||
如何使用对象存储
|
||||
----------------
|
||||
|
||||
TODO
|
||||
1
docs-zh/source/user-guide/cache.md
Normal file
@ -0,0 +1 @@
|
||||
# 开启多级缓存
|
||||
1
docs-zh/source/user-guide/coldvol.md
Normal file
@ -0,0 +1 @@
|
||||
# 创建纠删码卷
|
||||
@ -1,4 +0,0 @@
|
||||
如何创建就删吗卷
|
||||
----------------
|
||||
|
||||
TODO
|
||||
@ -1,4 +0,0 @@
|
||||
如何设置副本系统为缓存
|
||||
----------------
|
||||
|
||||
TODO
|
||||
1
docs-zh/source/user-guide/docker.md
Normal file
@ -0,0 +1 @@
|
||||
# 对接容器
|
||||
@ -1,4 +0,0 @@
|
||||
如何对接容器
|
||||
----------------
|
||||
|
||||
TODO
|
||||
1
docs-zh/source/user-guide/file.md
Normal file
@ -0,0 +1 @@
|
||||
# 使用文件存储
|
||||
@ -1,4 +0,0 @@
|
||||
如何使用文件存储
|
||||
----------------
|
||||
|
||||
TODO
|
||||
1
docs-zh/source/user-guide/hadoop.md
Normal file
@ -0,0 +1 @@
|
||||
# 对接Hadoop
|
||||
@ -1,4 +0,0 @@
|
||||
如何使用对接Hadoop
|
||||
----------------
|
||||
|
||||
TODO
|
||||
1
docs-zh/source/user-guide/hotvol.md
Normal file
@ -0,0 +1 @@
|
||||
# 创建副本卷
|
||||
@ -1,4 +0,0 @@
|
||||
如何创建副本卷
|
||||
----------------
|
||||
|
||||
TODO
|
||||
1
docs-zh/source/user-guide/k8s.md
Normal file
@ -0,0 +1 @@
|
||||
# 对接Kubernetes
|
||||
@ -1,4 +0,0 @@
|
||||
如何对接Kubenetes
|
||||
----------------
|
||||
|
||||
TODO
|
||||
1
docs-zh/source/user-guide/objectnode.md
Normal file
@ -0,0 +1 @@
|
||||
# 使用对象存储
|
||||
@ -1,4 +0,0 @@
|
||||
如何使用对象存储
|
||||
----------------
|
||||
|
||||
TODO
|
||||