从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 进阶系列(四):Ceph的纠删码特性 EC(Erasure Code)相关推荐

  1. ceph的压缩、加密、纠删码

    ceph的压缩.加密.纠删码 ① 压缩(Compression ) 对ceph压缩的一写描述: (1)The Ceph Object Gateway supports server-side comp ...

  2. CubeFS存储技术揭密(1) — 纠删码引擎系统设计

    00  背景 CubeFS 3.0.0以前版本只提供多副本存储,随着数据规模持续增长,业务面临着更大的成本挑战,用户对更低成本的纠删码(ErasureCode, 下文简称EC)的需求愈加强烈:Cube ...

  3. 纠删码存储系统中的投机性部分写技术

    本文已被USENIX'17年度技术大会录用,此处为中文简译版. 阅读英文论文完整版请点击:Speculative Partial Writes in Erasure-Coded Systems 多副本 ...

  4. 信道编码之纠删码编码

    简介 随着数据的存储呈现出集中化(以分布式存储系统为基础的云存储系统)和移动化(互联网移动终端)的趋势,数据可靠性愈发引起大家的重视.集群所承载的数据量大大上升,但存储介质本身的可靠性进步却很小,这要 ...

  5. 什么是纠删码(与纠错码的区别)|纠删码与副本对比|LDPC码

    什么是纠删码(与纠错码的区别) 存储领域来看,数据冗余机制其实这几十年来没有太多进展,RAID.副本一直是当仁不让的最终选择.而近几年,尤其是规模较大的应用场景下,纠删码越来越多的出现在选择的视野范围 ...

  6. Hadoop 3.0 纠删码技术分析(Erasure Coding)

    背景 随着大数据技术的发展,HDFS作为Hadoop的核心模块之一得到了广泛的应用.为了数据的可靠性,HDFS通过多副本机制来保证.在HDFS中的每一份数据都有两个副本,1TB的原始数据需要占用3TB ...

  7. 【hadoop】纠删码技术详解

    1 纠删码背景 随着大数据技术的发展,HDFS作为Hadoop的核心模块之一得到了广泛的应用.为了数据的可靠性,HDFS通过多副本机制来保证.在HDFS中的每一份数据都有两个副本,1TB的原始数据需要 ...

  8. K8s使用Ceph纠删码池做持久化卷

    K8s使用Ceph纠删码池做持久化卷 Ceph侧准备 Ceph纠删码相关 创建纠删码规则 创建纠删码池 创建复制集池 创建用户并授权 K8s消费ec池 验证 (可选)缓存方式 Kubernetes版本 ...

  9. 「Ceph源码分析」纠删码解码

    存储系统:ceph-14.2.22 操作系统:ubuntu-server-18.04 总体框架 源码分析 ECBackend::objects_read_and_reconstruct [ 文件路径 ...

最新文章

  1. redhat 6.2安装telnet服务
  2. 【网络传输与RTC】
  3. Java三大特性[封装,继承,多态]
  4. mysql 替换非中文_mysql中的正则操作 匹配手机号,匹配中文,替换
  5. 前端websocket获取数据后需要存本地吗_是什么让我放弃了Restful API?了解清楚后我全面拥抱GraphQL!...
  6. SpringBoot配置文件敏感信息加密,springboot配置文件数据库密码加密jasypt
  7. java对mysql的简单操作的综合运用——注册系统
  8. esb接口测试_接口测试用例.docx
  9. HOJ 2739 The Chinese Postman Problem
  10. java代码jar包混淆,proguard对java代码进行混淆
  11. 【IDE-Visual Studio】无法启动程序“xxx.exe”。由于应用程序配置不正确,未能启动此应用程序。
  12. 只要方向正确,路远不是事
  13. Nacos官方Docker版安装
  14. 【项目实践】海康威视工业相机SDK开发小白版入门教程(VS2015+OpenCV4.5.1)
  15. Android开发之连接实体手机进行开发的步骤 遇到的“an app is obsuring...“的问题及解决
  16. Python 外星人入侵(一):武装飞船
  17. I have the Dream
  18. 无线局域网CSMA/CA协议
  19. Android系统应用卸载
  20. 7、Hive数据仓库——Hive JDBC

热门文章

  1. 解决在IDEA里Git特别慢的问题
  2. 什么是stream?
  3. babylon.js入门日记系列
  4. 【Android定制】修改BUILD_AGO_GMS = no 和 BUILD_GMS=no属性
  5. 御龙在天找回以前的服务器,御龙在天各大服务器合服信息公告汇总!
  6. 午后清茶—八月照相馆
  7. Scala模式匹配--样例类--密封样例类--偏函数
  8. 在Linux下执行一个文件时候提示“权限不够”的解决办法
  9. C语言:定义一个数组,5个元素,从xiao到da排序
  10. 一个比较简单的x2m解密方法