存储系统:ceph-14.2.22
操作系统:ubuntu-server-18.04

一、总体框架

二、源码分析

encode_and_write 函数分析

osd在写数据时,最终会通过encode_and_write函数,该函数中会先根据数据块编码生成校验块,最后将数据块和校验块一起写入底层.
文件路径:ceph/src/osd/ECTransaction.cc

void encode_and_write(pg_t pgid, const hobject_t &oid, const ECUtil::stripe_info_t &sinfo,ErasureCodeInterfaceRef &ecimpl, const set<int> &want, uint64_t offset, bufferlist bl,uint32_t flags, ECUtil::HashInfoRef hinfo, extent_map &written,map<shard_id_t, ObjectStore::Transaction> *transactions, DoutPrefixProvider *dpp)
{const uint64_t before_size = hinfo->get_total_logical_size(sinfo);ceph_assert(sinfo.logical_offset_is_stripe_aligned(offset));ceph_assert(sinfo.logical_offset_is_stripe_aligned(bl.length()));ceph_assert(bl.length());map<int, bufferlist> buffers;//计算校验块数据//sinfo存储分片信息,bl输入的数据,want统计分片编号,buffers输出数据int r = ECUtil::encode(sinfo, ecimpl, bl, want, &buffers);ceph_assert(r == 0);written.insert(offset, bl.length(), bl);ldpp_dout(dpp, 20) << __func__ << ": " << oid << " new_size " << offset + bl.length() << dendl;if (offset >= before_size){ceph_assert(offset == before_size);hinfo->append(sinfo.aligned_logical_offset_to_chunk_offset(offset), buffers);}for (auto &&i : *transactions){ceph_assert(buffers.count(i.first));bufferlist &enc_bl = buffers[i.first];if (offset >= before_size){i.second.set_alloc_hint(coll_t(spg_t(pgid, i.first)), ghobject_t(oid, ghobject_t::NO_GEN, i.first), 0, 0,CEPH_OSD_ALLOC_HINT_FLAG_SEQUENTIAL_WRITE | CEPH_OSD_ALLOC_HINT_FLAG_APPEND_ONLY);}i.second.write(coll_t(spg_t(pgid, i.first)), ghobject_t(oid, ghobject_t::NO_GEN, i.first),sinfo.logical_to_prev_chunk_offset(offset), enc_bl.length(), enc_bl, flags);}
}

ECUtil::encode 方法分析

上面分析到,encode_and_write函数会调用encode计算校验块数据,encode是类ECUtil的方法。该方法将循环读取一个条带数据(数据块),调用相应接口,编码出校验块数据,最后将单条带数据(数据块+校验块)有序地追加到bufferlist结构中.
文件路径:ceph/src/osd/ECUtil.cc

int ECUtil::encode(const stripe_info_t &sinfo, ErasureCodeInterfaceRef &ec_impl, bufferlist &in, const set<int> &want,map<int, bufferlist> *out)
{//获取单个object的逻辑长度uint64_t logical_size = in.length();ceph_assert(logical_size % sinfo.get_stripe_width() == 0);ceph_assert(out);ceph_assert(out->empty());if (logical_size == 0)return 0;//for:以条带为单元进行数据编码for (uint64_t i = 0; i < logical_size; i += sinfo.get_stripe_width()){map<int, bufferlist> encoded;//临时存储编码生成的单条带数据(数据块+校验块)bufferlist buf;//临时存储用来编码的单个条带数据(数据块)buf.substr_of(in, i, sinfo.get_stripe_width());//获取一个条带的数据//调用encode进行编码,将编码完的数据也就是校验快数据临时放在encodedint r = ec_impl->encode(want, buf, &encoded);ceph_assert(r == 0);//将单条带数据(数据块+校验块)添加到out中for (map<int, bufferlist>::iterator i = encoded.begin(); i != encoded.end(); ++i){ceph_assert(i->second.length() == sinfo.get_chunk_size());(*out)[i->first].claim_append(i->second);}}for (map<int, bufferlist>::iterator i = out->begin(); i != out->end(); ++i){ceph_assert(i->second.length() % sinfo.get_chunk_size() == 0);ceph_assert(sinfo.aligned_chunk_offset_to_logical_offset(i->second.length()) == logical_size);}return 0;
}

ErasureCode::encode 方法分析

上面分析到,ECUtil::encode会调用ec_impl->encode计算校验块数据,ec_impl->encode是类ErasureCode的方法。该方法首先会调用相应接口,计算单条带数据(数据块)大小是否是blocksize的倍数,如果不是,需要对该条带数据(数据块)进行补空块。然后再调用相应接口,对条带数据(数据块+校验快)做进一步处理.
文件路径:ceph/src/erasure-code/ErasureCode.cc

int ErasureCode::encode(const set<int> &want_to_encode, const bufferlist &in, map<int, bufferlist> *encoded)
{//获取k、munsigned int k = get_data_chunk_count();//获取逻辑数据块个数unsigned int m = get_chunk_count() - k;//获取逻辑校验块个数bufferlist out;//检查条带数据(数据块)是否需要补空块int err = encode_prepare(in, *encoded);if (err)return err;//分离数据块和校验块encode_chunks(want_to_encode, encoded);for (unsigned int i = 0; i < k + m; i++){if (want_to_encode.count(i) == 0)encoded->erase(i);}return 0;
}

ErasureCode::encode_prepare 方法分析

上面分析到,ErasureCode::encode会调用encode_prepare计算条带数据(数据块)是否需要补空块。encode_prepare是类ErasureCode的方法。该方法先计算需要补空字符的块的个数,根据需要补块的数量,把数据块的内容拷贝到bufferlist中。然后对补块处理。补块处理分为两部分:第一部分,最后一块有数据内容,但数据大小不满足blocksize整倍数的数据块在末尾追加空字符处理。第二部分,整个条带剩下的,直接用blocksize大小的空快覆盖处理。补块处理完毕后,再处理校验块,直接初始化新块作为校验块,然后追加到encoded中。此时的条带就被拓展成数据块+校验块.
文件路径:ceph/src/erasure-code/ErasureCode.cc

int ErasureCode::encode_prepare(const bufferlist &raw, map<int, bufferlist> &encoded) const
{unsigned int k = get_data_chunk_count();//获取逻辑数据块个数unsigned int m = get_chunk_count() - k;//获取逻辑校验块个数unsigned blocksize = get_chunk_size(raw.length());//获取逻辑块大小unsigned padded_chunks = k - raw.length() / blocksize;//计算需要补空块的数据块个数bufferlist prepared = raw;//单条带(数据块)//for:将blocksize整倍数的单条带(数据块)数据拷贝到encoded中for (unsigned int i = 0; i < k - padded_chunks; i++){bufferlist &chunk = encoded[chunk_index(i)];//临时存放一个块数据chunk.substr_of(prepared, i * blocksize, blocksize);chunk.rebuild_aligned_size_and_memory(blocksize, SIMD_ALIGN);//获取blocksize大小的快数据ceph_assert(chunk.is_contiguous());}//if:如果需要补空if (padded_chunks){//对有数据但数据大小不是blocksize整倍数的块,在末尾追加空//计算最后一个有数据,但数据不是blocksize整倍数的数据块的数据大小unsigned remainder = raw.length() - (k - padded_chunks) * blocksize;//构造新的数据块,数据块大小为blocksizebufferptr buf(buffer::create_aligned(blocksize, SIMD_ALIGN));//将remainder大小的数据从最后一个数据块中拷贝到新的数据块中raw.copy((k - padded_chunks) * blocksize, remainder, buf.c_str());//将新的数据块剩下的blocksize - remainder大小的内容初始化为空buf.zero(remainder, blocksize - remainder);//将新的数据块覆盖原来最后一个有数据但不是blocksize整倍数的数据块encoded[chunk_index(k - padded_chunks)].push_back(std::move(buf));//for:处理剩下的,需要直接用完整的blocksize大小的空块进行填充for (unsigned int i = k - padded_chunks + 1; i < k; i++){//构造新的块bufferptr buf(buffer::create_aligned(blocksize, SIMD_ALIGN));buf.zero();//新块内容初始化为空encoded[chunk_index(i)].push_back(std::move(buf));//将空块追加到encoded中}}//for:循环处理校验块for (unsigned int i = k; i < k + m; i++){//构建新的校验快,内容为空bufferlist &chunk = encoded[chunk_index(i)];chunk.push_back(buffer::create_aligned(blocksize, SIMD_ALIGN));}return 0;
}

ErasureCodeJerasure::encode_chunks 方法分析

上面分析到,ErasureCode::encode会调用encode_chunks对条带数据(数据块+校验块)分离,encode_chunks是类ErasureCodeJerasure的方法。该方法将整个条带的数据按照k+m个逐个分离出来,最后调用ceph封装的接口,进入最后处理.
文件路径:ceph/src/erasure-code/jerasure/ErasureCodeJerasure.cc

int ErasureCodeJerasure::encode_chunks(const set<int> &want_to_encode, map<int, bufferlist> *encoded)
{char *chunks[k + m];//存放块数据(数据块+校验块)//将条带数据(数据块+校验块)单独分离for (int i = 0; i < k + m; i++)chunks[i] = (*encoded)[i].c_str();//调用ceph封装的接口,进入最后处理//&chunks[0]是数据块指针地址,&chunks[k]是校验快指针地址jerasure_encode(&chunks[0], &chunks[k], (*encoded)[0].length());return 0;
}

ErasureCodeJerasureReedSolomonVandermonde::jerasure_encode 方法分析

上面分析到,ErasureCodeJerasure::encode_chunks会调用jerasure_encode对条带数据(数据块+校验块)做最后处理。jerasure_encode是类ErasureCodeJerasureReedSolomonVandermonde的方法.该方法调用纠删码编码C语言接口。纠删码编码方法很多,目前使用的是范德蒙行列式编码.
文件路径:ceph/src/erasure-code/jerasure/ErasureCodeJerasure.cc

void ErasureCodeJerasureReedSolomonVandermonde::jerasure_encode(char **data, char **coding, int blocksize)
{//调用jerasure编码接口jerasure_matrix_encode(k, m, w, matrix, data, coding, blocksize);
}

【Ceph源码分析】纠删码编码相关推荐

  1. 纠删码项目总结(1.0)

    1. 为什么要使用纠删码? 随着数据的持续增长,在 PB 级别的数据中心,多副本技术会引入极大的存 储开销.比如,现有的分布式存储系统,如 HDFS(Hadoop distributed file s ...

  2. 我慌了,纠删码是什么?我被面试官问蒙了

    几年前去某大厂面试,岗位是:高级运维工程师.一面二面都很顺利,三面是技术总监,问了很多linux操作系统,shell,python,自动化运维等问题,可以说是对答如流,出口成章,滔滔不绝,心里觉得这下 ...

  3. RS(纠删码)技术浅析及Python实现

    前言 在Ceph和RAID存储领域,RS纠删码扮演着重要的角色,纠删码是经典的时间换空间的案例,通过更多的CPU计算,降低低频存储数据的存储空间占用. 纠删码原理 纠删码基于范德蒙德矩阵实现,核心公式 ...

  4. 【海云捷迅云课堂】分布式存储系统纠删码技术分享

    云课堂专题 海云捷迅云课堂专题,旨在秉承开源理念,为大家提供OpenStack技术原理与实践经验,该专题文章均由海云捷迅工程师理论与实践相结合总结而成,如大家有其他想要了解的信息,可留言给我们,我们会 ...

  5. MiniO纠删码快速入门

    MiniO纠删码快速入门 Minio使用纠删码erasure code和校验和checksum来保护数据免受硬件故障和无声数据损坏. 即便您丢失一半数量(N/2)的硬盘,您仍然可以恢复数据. 什么是纠 ...

  6. 第一节 Minio保护数据免受硬件故障和无声数据损坏的纠删码Erasure-Code

    第一节 第一节 Minio保护数据免受硬件故障和无声数据损坏的纠删码Erasure-Code 什么是纠删码Erasure-Code? 什么是位衰减bit rot保护? 驱动器(盘)如何使用纠删码? E ...

  7. Beehive:用于修复分布式存储系统中多个故障的纠删码

    Beehive:用于修复分布式存储系统中多个故障的纠删码 摘要:分布式存储系统越来越多地部署纠删码(例如 Reed-Solomon 码)以实现容错.尽管 Reed-Solomon 代码需要的存储空间比 ...

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

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

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

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

  10. 全网最新最全的 HDFS 文件纠删码技术分析

    前言 本文隶属于专栏<1000个问题搞定大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见1000个问题搞定大数据技 ...

最新文章

  1. 我在MongoDB年终大会上获二等奖文章:由数据迁移至MongoDB导致的数据不一致问题及解决方案...
  2. DataGridView 分页显示
  3. MySQL笔记2: count() 函数和 sum() 函数用法和区别
  4. 使用自己的按钮关闭或刷新RadWindow
  5. gb50268-2008给水排水管道施工及验收规范_20131城市给水排水管道·中篇(开槽施工管道质量验收标准)...
  6. python如何保存源文件_python自动保存百度盘资源到百度盘中的实例代码
  7. if和case用法比较
  8. python包mdure_Python hashlib模块实例使用详解
  9. python双线性插值函数_双线性插值法原理 python实现
  10. 【英语学习】【WOTD】encroach 释义/词源/示例
  11. Ubuntu安装ASIO开发库
  12. [转载] python---python中时间的应用(time模块)
  13. 模2除法与二进制除法
  14. vue 城市级联选择 distPicker
  15. Flask初级(三)flash使用模板
  16. wps ppt 自动播放怎么怎么办
  17. localhost:8080打不开本地网页
  18. adlds文件服务器,Windows Server 2008:AD LDS应用攻略
  19. centos7搭建owncloud私有云
  20. java spark 朴素贝叶斯算法(naive-bayes)

热门文章

  1. 如何区别文本是BIG5还是GB
  2. paxos算法java实现_Paxos算法——前世
  3. xampp套件使用php,php集成套件服务器xampp安装使用教程(适合第一次玩PHP的新手),xampp安装使用...
  4. xampp的安装教程
  5. Selenium 全自动化下载QQ付费音乐-说好不哭MV
  6. CSS4.2.3 参考手册.CHM
  7. 软考中级软件设计师--6.UML
  8. imx6ul之LCD驱动移植
  9. ac8265网卡linux驱动,英特尔8265无线网卡驱动
  10. LINUX下打包jar