复制的架构设计介绍
一、简介
用户为了确保自己的重要数据不丢失,通常会采用备份功能。而备份数据同样是在存储上,一样会有丢失的风险,这时就会期望备份数据有多个副本。如果这些副本跨地域保存,就可以极大的增加数据的可靠性。为了保证数据的安全性,通常会是两个相同的服务在两地协作完成此功能,二者的数据是隔离的,互相不可见,这样就不会因为误操作,删除了备份数据或者其副本。通过两个服务协作生成备份数据多个副本的这个过程,我们称为复制。
二、背景
常规备份的策略都是周期的全备份,周期之间采用增备。而复制由于跨地域,带宽会受限,选择性复制部分备份副本。因此复制有两个重要的需求,
第一有数据传输的性能要高,只有它的性能提高了,才会使得尽可能多的备份可以复制。
第二有乱序需求,不能因为选择了增量备份复制,这个数据就不完整。
三、架构原型
不考虑具体架构的话,整个复制主要功能就是获得需要复制的数据、传输到目的端,最后存储到目标存储上。这样就有三个模块,它们是业务模块、通信模块、读写存储模块。
针对任意备份可以复制,可以基于恢复的原理在业务模块实现。
由于是服务间的协作就涉及到push还是pull模型。考虑可以1对多模型,每个服务间进度不同,目的端自己关心进度,这里选择pull模型。
主流程如下:
- 业务模块分析需要复制的数据
- 通信模块将数据传递到目的端
- 目的端读写模块获得数据后存储
如果想要高效的复制,顺序的执行上面的流程显然会有大量的等待耗时。转为异步的后,流水线方式会大大提高性能。但是各个模块的运行步调不会是一样的,网络上还会乱序,流水线并不会像想象的那么好,很可能会错乱。
预分配空间
传递数据就需要数据空间,反复的申请小内存会降低系统性能。这样预先申请一定数量的数据块,让数据块在各个模块间流动。即可以减少反复的内存申请释放,又可以在3个模块间做数据缓冲。
- 业务模块从内存池获得内存,存储需要复制的信息传递到通信模块
- 通信模块将内存数据传给源端服务
- 当源端数据返回后,回调数据对应的通信模块
- 通信模块将数据内存传给读写模块
- 读写模块完成数据存储,将内存还给内存池
四、容灾考虑
复制涉及到组件比较多,两个同样的服务都可能重启,广域网丢包或者断网等因数,因此有任务失败之后的续做需求。
如果像下载软件一样多流,每个流复制一部分数据,记录进度有以下问题:
1) 需要复制的数据并不是一个大文件,不容易控制
2) 目的端的写也可能有瓶颈,在每个复制流内部同步等待并不利用性能调整。
因为网络的回应包可能是乱序的,记录进度必须有一个地方同步。如果接收数据排序后,性能会受到影响,可以先存储,只是把数据内存存入完成队列,当这个队列顺序后再记录进度,并把内存还回内存池。这样通过合适的内存缓冲可以有效的屏蔽等待时间。
五、总结
到此整个复制的架构设计过程就讲完了。当然这个架构还可以进一步演进,分离的通信层,可以通过重删等功能进一步降低传输数据,数据越少必然传输越快。