Ceph的纠删码特性 EC(Erasure Code)代码流程
从GitHub上Clone Ceph项目,我是基于(ceph version 12.2.11 luminous 版本)的代码来分析的
一、EC(Erasure Code)是什么?
Ceph的纠删码特性EC:将写入的数据分成N份原始数据,通过这N份原始数据计算出M份效验数据。把N+M份数据分别保存在不同的设备或者节点中,并通过N+M份中的任意N份数据块还原出所有数据块。EC包含了编码和解码两个过程:将原始的N份数据计算出M份效验数据称为编码过程;通过这N+M份数据中的任意N份数据来还原出原始数据的过程称为解码过程。EC可以容忍M份数据失效,任意小于等于M份的数据失效能通过剩下的数据还原出原始数据。Ceph支持以插件的形式来指定不同的EC编码方式。不同的EC编码方式是三个指标间的折中结果,这个三指标就是是:空间利用率、数据可靠性和恢复效率。
二、不同的 EC 编码方式
1. RS类型编码, 目前应用最广泛的纠删码是ReedSolomon编码,简称RS码。下面是RS编码的两个实现(ISA + Jerasure):
1). .ISA:ISA是Intel提供的一个EC库,只能运行在Intel CPU上,它利用了Intel处理器本地指令来加速EC的计算。
2). Jerasure是一个ErausreCode开源实现库,它实现了EC的RS编码。目前Ceph中默认的编码就是Jerasure方式
RS编码的不足之处在于:在N+K个数据块中有任意一块数据失效,都需要读取N块数据来恢复丢失数据。在数据恢复的过程中引起的网络开销比较大。因此,LRC编码和SHEC编码分别从不同的角度做了相关优化。
2. LRC类型编码(特点:恢复数据块时,减少了读取网络数据块的数量)
LRC编码的核心思想为:将校验块(parity block)分为全局校验块(global parity)和局部校验块(local reconstruction parity),从而减少恢复数据的网络开销。
LRC(M,G,L)的三个参数分别为:
·M是原始数据块的数量。
·G为全局校验块的数量。
·L为局部校验块的数量。
编码过程为:把数据分成M个同等大小的数据块,通过该M个数据块计算出G份全局效验数据块。然后把M个数据块平均分成L组,每组计算出一个本地数据效验块,这样共有L个局部数据校验块。
3. SHEC类型编码(特点:恢复数据块时,减少了读取数据块的数量)
SHEC编码方式为SHEC(K,M,L),其中K代表原始数据块data chunk的数量,M代表校验块parity chunk的数量,L代表计算校验块parity chunk时需要的原始数据块data chunk的数量。其最大允许失效的数据块为:ML/K。这样恢复失效的单个数据块只需要额外读取L个数据块。
以SHEC(10,6,5)为例,其最大允许失效的数据块为:M(6) * L(5)/ K(10 ) = 3,且当一个数据块失效时,只读取5个数据块就可以恢复。
三、纠删码 EC 和 副本 Replicated 的比较
众所周知在创建Ceph的pool时,可以设置pool的冗余恢复方式,EC类型或者Replicated副本类型。指定EC类型时,可以设置N和M的参数。各种纠删码(EC的) 和 副本(Replicated)的比较如下表所示:

说明如下:
·在副本类型(三副本)的情况下,恢复效率和可靠性都比较高,缺点就是数据容量开销比较大。
·EC的RS编码,和三副本比较,数据开销显著降低,以恢复效率和可靠性为代价。
·EC的LRC编码以数据容量开销略高的代价,换取了数据恢复开销的显著降低。
·EC的SHEC编码用可靠性换代价,在LRC的基础上进一步降低了容量开销。
四、先来过一下OSD 处理写操作的序列图,后面分析的EC写流程都是走这个框架

根据上面的OSD序列图来分析一下execute_ctx里发生了什么。execute_ctx的函数调用关系为:
PrimaryLogPG::execute_ctx(OpContext *ctx)
=> PrimaryLogPG::prepare_transaction(OpContext *ctx) //准备transaction
=> PrimaryLogPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops) //填充ctx变量的相关成员
=> PrimaryLogPG::issue_repop(RepGather *repop, OpContext *ctx)
=> PGBackend::submit_transaction(...) //提交transaction给PGBackend,见上图
五、EC 写操作源代码的分析
举例EC写操作的代码流程分析,来看相关的函数和数据结构
1. 下面分析EC的写操作时,函数PrimaryLogPG::do_osd_ops中实现操作的事务封装
//源代码文件 src/osd/PrimaryLogPG.cc
int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
{
...
PGTransaction* t = ctx->op_t.get();
...
1)多处代码都验证如果是EC类型,写操作的offset必须以stripe_width对齐,否则不支持。
源代码文件 osd_types.h里定义的requires_aligned_append() 函数判断POOL是否是EC类型
/*
* pg_pool
*/
struct pg_pool_t {
...
bool requires_aligned_append() const {
return is_erasure() && !has_flag(FLAG_EC_OVERWRITES);
}
...
}
源代码文件 src/osd/PrimaryLogPG.cc里 do_osd_ops() 函数的 CEPH_OSD_OP_WRITE 写操作:
// --- WRITES ---
// -- object data --
case CEPH_OSD_OP_WRITE:
++ctx->num_write;
...
if (pool.info.requires_aligned_append() &&
(op.extent.offset % pool.info.required_alignment() != 0)) {
result = -EOPNOTSUPP;
break;
}
2)如果对象不存在,do_osd_ops() 函数里调用PrimaryLogPG::maybe_create_new_object来创建
maybe_create_new_object(ctx);
来看看PrimaryLogPG::maybe_create_new_objec()函数的定义
void PrimaryLogPG::maybe_create_new_object(
OpContext *ctx,
bool ignore_transaction)
{
ObjectState& obs = ctx->new_obs;
if (!obs.exists) {
ctx->delta_stats.num_objects++;
obs.exists = true;
assert(!obs.oi.is_whiteout());
obs.oi.new_object();
if (!ignore_transaction)
ctx->op_t->create(obs.oi.soid);
} else if (obs.oi.is_whiteout()) {
dout(10) << __func__ << " clearing whiteout on " << obs.oi.soid << dendl;
ctx->new_obs.oi.clear_flag(object_info_t::FLAG_WHITEOUT);
--ctx->delta_stats.num_whiteouts;
}
}
3)最后把写操作添加到事务中(t是一个PGTransaction类型的变量,通过ctx->op_t.get()):
if (op.extent.length == 0) {
...
} else {
t->write(
soid, op.extent.offset, op.extent.length, osd_op.indata, op.flags);
}
2. 在函数PrimaryLogPG::do_osd_ops实现事务封装后,由PGBackend提交整个操作上下文信息OpContext ctx给FileStore/BlueStore
PrimaryLogPG::execute_ctx(OpContext *ctx) => PrimaryLogPG::issue_repop(RepGather *repop, OpContext *ctx) => PGBackend::submit_transaction(...),其中PGBackend::submit_transaction为虚函数,具体函数由子类ReplicatedPGBackend/ECPGBackend实现,该函数submit_transaction的参数如下:
PGBackend::submit_transaction(
const hobject_t &hoid,
const object_stat_sum_t &delta_stats,
const eversion_t &at_version,
PGTransactionUPtr &&t,
const eversion_t &trim_to,
const eversion_t &roll_forward_to,
const vector<pg_log_entry_t> &log_entries,
boost::optional<pg_hit_set_history_t> &hset_history,
Context *on_all_commit,
ceph_tid_t tid,
osd_reqid_t reqid,
OpRequestRef client_op
)
3. EC*类介绍
类ECBackend实现了EC的读写操作。ECUtil里定义了编码和解码的函数实现。ECTransaction定了EC的事务。
参考:《Ceph 源代码分析》
相关文章:
Ceph的纠删码特性 EC(Erasure Code)代码流程
从GitHub上Clone Ceph项目,我是基于(ceph version 12.2.11 luminous 版本)的代码来分析的 一、EC(Erasure Code)是什么? Ceph的纠删码特性EC:将写入的数据分成N份原始数据,通过这N份原始数据计算出M份效验…...
盘点那些国际知名黑客(上篇)
电影中的黑客仅靠一部电脑就可以窃取别人的信息,利用自己高超的技术让公司甚至国家都胆战心惊。“黑客”原指热心于计算机技术、水平高超的电脑高手,但逐渐区分为黑帽、白帽、灰帽。这些术语源自美国流行文化的老式西部电影,其中主角戴白色或…...
机器学习基础12-Pipeline实现自动化流程处理(基于印第安糖尿病Pima 数据集)
有一些标准的流程可以实现对机器学习问题的自动化处理,在 scikitlearn 中通过Pipeline来定义和自动化运行这些流程。本节就将介绍如何通过Pipeline实现自动化流程处理。 如何通过Pipeline来最小化数据缺失。如何构建数据准备和生成模型的Pipeline。如何构建特征选择…...
Ansible学习笔记15
1、roles:(难点) roles介绍: roles(角色):就是通过分别将variables,tasks及handlers等放置于单独的目录中,并可以便捷地调用他们的一种机制。 假设我们要写一个playbo…...
圆圈加数字的css
方式一 .circle { width: 50px; height: 50px; border-radius: 50%; background-color: #f00; color: #fff; text-align: center; line-height: 50px; } .circle::before { content: attr(data-number); display: block; } <div class"circle" data-number"…...
YOLOV5/YOLOV7/YOLOV8改进:用于低分辨率图像和小物体的新 CNN 模块SPD-Conv
1.该文章属于YOLOV5/YOLOV7/YOLOV8改进专栏,包含大量的改进方式,主要以2023年的最新文章和2022年的文章提出改进方式。 2.提供更加详细的改进方法,如将注意力机制添加到网络的不同位置,便于做实验,也可以当做论文的创新点。 3.涨点效果:SPD-Conv提升小目标识别,实现有效…...
Docker数据管理(数据卷与数据卷容器)
目录 一、数据卷(Data Volumes) 1、概述 2、原理 3、作用 4、示例:宿主机目录 /var/test 挂载同步到容器中的 /data1 二、数据卷容器(DataVolumes Containers) 1、概述 2、作用 3、示例:创建并使用…...
大量TCP连接滞留TIME_WAIT、SYN_SENT、CLOSE_WAIT状态的分析
文章目录 一、统计各类状态的tcp连接数量二、TIME_WAIT应用服务器上,来自反向代理的连接反向代理上,访问应用服务的连接反向代理上,来自用户的连接 三、SYN_SENT反向代理上,访问位于防火墙另一侧的目标反向代理上,访问…...
kotlin怎么定义类
在Kotlin中,你可以使用class关键字来定义一个类。以下是一个简单的例子: class MyClass {// class body} 这个例子定义了一个名为MyClass的类。你可以在类体中定义属性和方法。 如果你想定义一个带有属性的类,你可以这样做: cla…...
如何查看数据集下载后保存的绝对路径?
1.问题 当我们下载torchvision.datasets里面的数据集时,有时候会遇到找不到数据集保存路径的问题。 2.解决 引入os库 import os调用如下方法 os.path.abspath(数据集对象.root)以下面代码为例 import os import torchvision.datasets as datasets# 指定数据集…...
使用php实现微信登录其实并不难,可以简单地分为三步进行
使用php实现微信登录其实并不难,可以简单地分为三步进行。 第一步:用户同意授权,获取code //微信登录public function wxlogin(){$appid "";$secret "";$str"http://***.***.com/getToken";$redirect_uriu…...
【LeetCode-中等题】24. 两两交换链表中的节点
文章目录 题目方法一:递归方法二:三指针迭代 题目 方法一:递归 图解: 详细版 public ListNode swapPairs(ListNode head) {/*递归法:宗旨就是紧紧抓住原来的函数究竟返回的是什么?作用是什么即可其余的细枝末节不要细究,编译器…...
5.10 汇编语言:汇编过程与结构
过程的实现离不开堆栈的应用,堆栈是一种后进先出(LIFO)的数据结构,最后压入栈的值总是最先被弹出,而新数值在执行压栈时总是被压入到栈的最顶端,栈主要功能是暂时存放数据和地址,通常用来保护断点和现场。 栈是由CPU管…...
【每日一题Day304】LC1267统计参与通信的服务器 | 哈希表
统计参与通信的服务器【LC1267】 这里有一幅服务器分布图,服务器的位置标识在 m * n 的整数矩阵网格 grid 中,1 表示单元格上有服务器,0 表示没有。 如果两台服务器位于同一行或者同一列,我们就认为它们之间可以进行通信。 请你统…...
深度解读零信任身份安全—— 全面身份化:零信任安全的基石
事实上,无论是零信任安全在数据中心的实践,还是通用的零信任安全架构实践,全面身份化都是至关重要的,是“企业边界正在瓦解,基于边界的安全防护体系正在失效”这一大背景下,构筑全新的零信任身份安全架构的…...
音视频 ffmpeg命令提取音视频数据
保留封装格式 ffmpeg -i test.mp4 -acodec copy -vn audio.mp4 ffmpeg -i test.mp4 -vcodec copy -an video.mp4提取视频 保留编码格式:ffmpeg -i test.mp4 -vcodec copy -an test_copy.h264 强制格式:ffmpeg -i test.mp4 -vcodec libx264 -an test.h2…...
vscode 配置
vscode 配置 安装插件 Better C SyntaxC/CCMake、CMake Tools 、CMake Language SupportDoxygen Documentation GeneratorGit Graphhighlight-wordsPythonvscode-iconsClang-Format和clangdtyporahex editor .vscode 中的文件 在 VS Code 中,.vscode 文件夹是用于…...
企业数字化管控平台及信息化治理体系建设方案(附300份方案)
本资料来源公开网络,仅供个人学习,请勿商用,如有侵权请联系删除,更多浏览公众号:智慧方案文库 数字化校园整体解决方案.doc150页6万字数字化智能工厂信息化系统集成整合规划建设方案.docx2022年采购数字化市场研究报告…...
ABB PCD231B通信输入/输出模块
多通道输入和输出: PCD231B 模块通常配备多个输入通道和输出通道,用于连接传感器、执行器和其他设备。 通信接口: 这种模块通常支持各种通信接口,如以太网、串口(RS-232、RS-485)、Profibus、CAN 等&#…...
在springboot项目中显示Services面板的方法
文章目录 前言方法一:Alt8快捷键方法二:使用Component标签总结 前言 在一个springboot项目中,通过开启Services面板,可以快速的启动、配置、管理多个子项目。 方法一:Alt8快捷键 1、在idea界面输入Alt8,在…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
