Swift源碼分析----swift-container-replicator

感謝朋友支持本博客,歡迎共同探討交流,由於能力和時間有限,錯誤之處在所難免,歡迎指正!

如果轉載,請保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
郵箱地址:[email protected]

PS:最近沒有登錄博客,很多朋友的留言沒有看見,這裏道歉!還有就是本人較少上QQ,可以郵件交流。


概述部分:

實現複製指定分區(容器)數據到指定節點(用以實現數據副本之間的同步);
這裏定義的once=True,說明系統默認調用守護進程類Daemon中的run_once方法;
從而最終實現調用Replicator類中的run_once方法;
注:容器之間同步數據主要就是對形如object_file = /srv/node/node['device']/containers/partition/suffix/hsh****.db的數據庫文件執行復制操作;


源碼解析部分:

下面是這部分代碼的主要執行流程,代碼中較重要的部分已經進行了相關的註釋;

from swift.container.replicator import ContainerReplicator
from swift.common.utils import parse_options
from swift.common.daemon import run_daemon

if __name__ == '__main__':
    conf_file, options = parse_options(once=True)
    run_daemon(ContainerReplicator, conf_file, **options)

from swift.container.backend import ContainerBroker, DATADIR
from swift.common import db_replicator

class ContainerReplicator(db_replicator.Replicator):
    server_type = 'container'
    brokerclass = ContainerBroker
    datadir = DATADIR
    default_port = 6001

    def report_up_to_date(self, full_info):
        for key in ('put_timestamp', 'delete_timestamp', 'object_count',
                    'bytes_used'):
            if full_info['reported_' + key] != full_info[key]:
                return False
        return True

class Replicator(Daemon)----def run_once(self, *args, **kwargs):
    """
    實現複製指定分區數據到指定節點(用以實現數據副本之間的同步);
    數據類型可能是account或container或object;
    """
        
    # 初始化若干參數的操作;
    # self.stats = {'attempted': 0, 'success': 0, 'failure': 0, 'ts_repl': 0,
    #              'no_change': 0, 'hashmatch': 0, 'rsync': 0, 'diff': 0,
    #              'remove': 0, 'empty': 0, 'remote_merge': 0,
    #              'start': time.time(), 'diff_capped': 0}
    self._zero_stats()
    dirs = []
    ips = whataremyips()
    if not ips:
        self.logger.error(_('ERROR Failed to get my own IPs?'))
        return
        
    # 獲取環上的設備信息;
    for node in self.ring.devs:
        if (node and node['replication_ip'] in ips and node['replication_port'] == self.port):
            if self.mount_check and not ismount(os.path.join(self.root, node['device'])):
                self.logger.warn(_('Skipping %(device)s as it is not mounted') % node)
                    continue
                
            # 刪除若干過期文件;
            unlink_older_than(
                os.path.join(self.root, node['device'], 'tmp'),
                time.time() - self.reclaim_age)
                
            datadir = os.path.join(self.root, node['device'], self.datadir)
            if os.path.isdir(datadir):
                dirs.append((datadir, node['id']))
        
    self.logger.info(_('Beginning replication run'))
    for part, object_file, node_id in roundrobin_datadirs(dirs):
            
         # _replicate_object:複製指定分區數據到指定節點(用以實現數據副本之間的同步),具體步驟如下;
         #     獲取指定分區所在的所有節點nodes(一個分區可能對應多個節點,因爲可能有多個副本);
         #     判斷node_id是否在nodes的範圍之內(這是合理的);
         #     循環實現數據到各個目標節點上(的分區)的複製操作;
         #     通過比較同步點和哈希值來判斷複製後的兩個版本是否是同步的,即複製操作是否成功;
        self.cpool.spawn_n(self._replicate_object, part, object_file, node_id)
    self.cpool.waitall()
    self.logger.info(_('Replication run OVER'))
    self._report_stats()
1.for node in self.ring.devs:從環上獲取所有設備,遍歷並執行以下操作:
通過IP地址判斷並獲取屬於本機的且已經掛載的設備,並存儲設備對應的datadir = /srv/node/node['device']/containers和node['id']作爲元素儲存在字典dirs中;
注:這裏實際上就是獲取屬於本機的設備,且明確文件路徑/srv/node/node['device']/containers(對應於容器);

2.循環遍歷node['device']/containers下面的每一個文件object_file(文件路徑形如object_file = /srv/node/node['device']/containers/partition/suffix/hsh****.db,爲容器中具體分區下的以.db爲後綴的文件),調用方法_replicate_object實現複製本地指定分區數據到指定節點(用以實現數據副本之間的同步);


注:其他部分的內容實現與swift-account-replicator的實現是一致的,所以這裏不再進行贅述;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章