关于
我的项目
相关阅读
热度排行
- [转] 宫崎骏用动漫教给我们的人生哲理,每一句都能说到心里! - (日期:[八月 24, 2013] 点击:[53,185])
- Google 网页爬虫报告无法连接站点解决办法 - (日期:[七月 20, 2014] 点击:[38,634])
- 架设Tiny Tiny RSS(TTRSS)阅读器,找回Google Reader! - (日期:[九月 27, 2013] 点击:[27,764])
- SkyDrive、DropBox和Google Drive三大公有云存储服务对比 - (日期:[六月 25, 2013] 点击:[25,568])
- 升级到至强E5440后,与i5 CPU笔记本性能对比 - (日期:[二月 18, 2014] 点击:[23,704])
- 公钥私钥加密解密数字证书数字签名详解 - (日期:[四月 19, 2014] 点击:[22,955])
- 本站建站技术合集 - (日期:[九月 20, 2013] 点击:[22,481])
- 使用OpenerDNS解决无法访问Google的问题 - (日期:[七月 5, 2014] 点击:[21,784])
- WordPress博客添加“返回顶部”按钮 - (日期:[七月 14, 2013] 点击:[21,194])
- Linux文件系统基础之inode和dentry - (日期:[三月 13, 2015] 点击:[20,161])
- 云存储中的HTTP鉴权算法分析 - (日期:[二月 7, 2014] 点击:[18,636])
- 存储基础知识之——磁盘阵列原理及操作实战 - (日期:[二月 9, 2014] 点击:[17,487])
- 精选37条强大的常用linux shell命令组合 - (日期:[九月 4, 2013] 点击:[17,425])
- DNS原理、架构和配置详解 - (日期:[九月 6, 2013] 点击:[16,798])
- Netty和Jetty的Java NIO 网络框架模型分析 - (日期:[七月 13, 2013] 点击:[16,330])
- CoreOS 初识之安装 - (日期:[十一月 16, 2014] 点击:[16,167])
- Windows与Linux文件系统互访的几种方法 - (日期:[八月 21, 2014] 点击:[15,729])
- Dijkstra算法求解最短路径分析 - (日期:[七月 12, 2014] 点击:[14,923])
- NAS解决方案实现多媒体文件共享播放 - (日期:[十二月 21, 2014] 点击:[13,907])
- 简介 - (日期:[九月 1, 2012] 点击:[13,750])
- 如何编程实现 2 + 2 = 5? - (日期:[六月 2, 2014] 点击:[13,267])
- 搭建了一个iNews程序 - (日期:[十月 15, 2013] 点击:[13,234])
- 2014年9月曝出的Bash ShellShock漏洞简析 - (日期:[九月 26, 2014] 点击:[13,134])
- 彻底解决WordPress博客垃圾评论的问题 - (日期:[八月 5, 2013] 点击:[13,081])
- 如何使用1M的内存排序100万个8位数 - (日期:[三月 27, 2014] 点击:[12,551])
- 全部日志列表 - (日期:[十一月 11, 2012] 点击:[12,322])
- 关于回调函数和this指针探讨 - (日期:[八月 24, 2014] 点击:[12,206])
- 给定一个long型常量,其值为x,给定long型变量a,要求a & x 的取值集合 - (日期:[九月 8, 2012] 点击:[11,699])
- WordPress建站必备实用插件 - (日期:[八月 7, 2014] 点击:[11,358])
- Amazon 云计算业务全面介绍 - (日期:[三月 9, 2014] 点击:[11,266])
分类目录
文章归档
- 2024年四月 (1)
- 2024年二月 (1)
- 2023年九月 (1)
- 2023年一月 (1)
- 2022年十月 (1)
- 2022年八月 (2)
- 2022年四月 (1)
- 2022年三月 (1)
- 2021年十二月 (2)
- 2021年十月 (2)
- 2021年九月 (1)
- 2021年八月 (1)
- 2021年五月 (1)
- 2021年三月 (2)
- 2021年一月 (2)
- 2020年十二月 (5)
- 2020年十一月 (2)
- 2020年十月 (2)
- 2020年九月 (1)
- 2020年八月 (5)
- 2020年七月 (2)
- 2019年九月 (1)
- 2018年八月 (1)
- 2018年七月 (1)
- 2018年六月 (1)
- 2018年五月 (1)
- 2018年三月 (1)
- 2018年二月 (1)
- 2018年一月 (2)
- 2017年十二月 (3)
- 2017年十月 (4)
- 2017年九月 (1)
- 2017年七月 (1)
- 2017年六月 (1)
- 2016年十二月 (1)
- 2016年十月 (1)
- 2016年九月 (1)
- 2016年七月 (2)
- 2016年六月 (1)
- 2016年二月 (3)
- 2015年十二月 (3)
- 2015年十一月 (2)
- 2015年十月 (1)
- 2015年八月 (2)
- 2015年七月 (4)
- 2015年六月 (1)
- 2015年三月 (2)
- 2015年二月 (1)
- 2015年一月 (4)
- 2014年十二月 (2)
- 2014年十一月 (2)
- 2014年十月 (5)
- 2014年九月 (8)
- 2014年八月 (11)
- 2014年七月 (17)
- 2014年六月 (7)
- 2014年五月 (15)
- 2014年四月 (16)
- 2014年三月 (14)
- 2014年二月 (5)
- 2013年十二月 (5)
- 2013年十一月 (3)
- 2013年十月 (13)
- 2013年九月 (13)
- 2013年八月 (13)
- 2013年七月 (9)
- 2013年六月 (8)
- 2013年五月 (1)
- 2013年三月 (3)
- 2013年一月 (1)
- 2012年十一月 (1)
- 2012年九月 (12)
- 2012年八月 (3)
- 2011年二月 (1)
- 2009年三月 (1)
- 2009年二月 (1)
- 2008年十一月 (1)
- 2008年六月 (1)
- 2008年四月 (1)
- 2008年三月 (1)
DRBD源码分析(四)——activelog
大概有半年时间没有分析过DRBD的源码了。今天又翻出了DRBD的代码,想看一下activelog的作用和原理。
首先是看DRBD手册中关于activelog的介绍:http://www.drbd.org/users-guide-8.3/s-activity-log.html
手册的内容很精炼,只是简单介绍了工作原理,activelog中记录的是最近写入磁盘中的IO,每一条activelog对应着一个4M的数据块。62条这样的日志组成一个512bit的sector,整个activelog由若干个这样的sector组成。activelog的条数是可以指定的,在drbd.conf文件中可以配置,配置值为:activelog能记录的数据块的大小,注意不是日志的条数。该值的含义也就是:当出现故障重启时,需要在主备两端同步的数据块的总大小。
当写入新的4M数据块时,DRBD会刷新一次activelog,activelog是循环写入的,在元数据里面会记录当前的所有日志中,哪一条是最老的。因此当反转覆盖发生时,需要更新元数据。事实上,当运行的时间足够长时,反转覆盖在每一次添加一个4M数据块时都会发生。但是当指定的size值与512bit(代表240多M,具体值要根据代码计算。)不是整数倍关系时,在最后一个sector反转时,需要写两个sector,因此从这个角度讲,activelog的size最好是整数个sector,这样可以减少一部分不必要的写两个sector。
具体的activelog的结构为:
/* We maintain a trivial check sum in our on disk activity log.
* With that we can ensure correct operation even when the storage
* device might do a partial (last) sector write while loosing power.
*/
struct __packed al_transaction {
u32 magic;
u32 tr_number;
struct __packed {
u32 pos;
u32 extent; } updates[1 + AL_EXTENTS_PT];
u32 xor_sum;
};
这里AL_EXTENTS_PT的值为62。
再来看具体的日志记录过程:当主端在开始写入一个新的4M数据块时,就会将该块需要写入的位置记录到activelog,写activelog的过程本身就在一次bio的处理过程中,在bio处理过程中,不能再调用bio的处理函数,因此写activelog需要使用一个异步任务,这个在代码里面的注释有详细的说明:
void drbd_al_begin_io(struct drbd_conf *mdev, sector_t sector)
{
unsigned int enr = (sector >> (AL_EXTENT_SHIFT-9));
struct lc_element *al_ext;
struct update_al_work al_work;
D_ASSERT(atomic_read(&mdev->local_cnt) > 0);
trace_drbd_actlog(mdev, sector, "al_begin_io");
wait_event(mdev->al_wait, (al_ext = _al_get(mdev, enr)));
if (al_ext->lc_number != enr) {
/* drbd_al_write_transaction(mdev,al_ext,enr);
* recurses into generic_make_request(), which
* disallows recursion, bios being serialized on the
* current->bio_tail list now.
* we have to delegate updates to the activity log
* to the worker thread. */
init_completion(&al_work.event);
al_work.al_ext = al_ext;
al_work.enr = enr;
al_work.old_enr = al_ext->lc_number;
al_work.w.cb = w_al_write_transaction;
drbd_queue_work_front(&mdev->data.work, &al_work.w);
wait_for_completion(&al_work.event);
dev_err(DEV, "w_al_write_transaction called\n");
mdev->al_writ_cnt++;
/*
DUMPI(al_ext->lc_number);
DUMPI(mdev->act_log->new_number);
*/
spin_lock_irq(&mdev->al_lock);
lc_changed(mdev->act_log, al_ext);
spin_unlock_irq(&mdev->al_lock);
wake_up(&mdev->al_wait);
}
}
等待activelog写完成后,才发起IO本地写入流程和发往对端。
假设,本端写入完成后,IO还没有发往对端前,此时本端出现类似掉电的情况,这样本端的IO已经下盘,而对端的IO还没有下盘,两端出现了数据不一致,这样当本端启动时,则需要从此时的主端同步所有的数据,当整个镜像盘非常大时,这个同步过程会非常漫长。有了activelog后,同步慢的问题可以得到很好的解决,如果对端升主后,写入的数据未超出activelog能cover的数据块的size时,可以只比对本端记录的acitvesize的数据,将这部分数据同步到本端即可。因此同步时间,取决于activelog的大小。当然如果本端下点时间过长,对端在做主期间写入了太多的数据,那么还是需要作全盘同步的。这是不可避免的。activelog只是解决临时的主节点重启的问题。
在DRBD的官网上面有一篇文章详细介绍activelog的设计原理:Rapid resynchronization for replicated storage Activity-logging for DRBD。
5 条评论
看 DRBD8.4 的代码,11 年初提了一个 Patch,把 al 的 size 改成 512Byte 了……
我的qq9178-65322,希望和您交流。
al配合bitmap的话,还可以把bitmap持久化到硬盘,进一步保障了幸存节点掉电也不会丢失记录。请您确认下。
我的qq9178-65322,希望和您交流。
“因此同步时间,取决于activelog的大小。当然如果本端下点时间过长,对端在做主期间写入了太多的数据,那么还是需要作全盘同步的。这是不可避免的。” 这样说不对吧,bitmap可以保障下电时间很长,差异超过al的时候也可以快速同步。