Created
December 28, 2021 08:13
-
-
Save QQGoblin/6288243d9fad8d3ef87311b45eb004bd to your computer and use it in GitHub Desktop.
【Patroni源码阅读】创建replicas副本
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Bootstrap(object): | |
def create_replica(self, clone_member): | |
""" | |
create the replica according to the replica_method | |
defined by the user. this is a list, so we need to | |
loop through all methods the user supplies | |
""" | |
self._postgresql.set_state('creating replica') | |
self._postgresql.schedule_sanity_checks_after_pause() | |
is_remote_master = isinstance(clone_member, RemoteMember) | |
# get list of replica methods either from clone member or from | |
# the config. If there is no configuration key, or no value is | |
# specified, use basebackup | |
# | |
# 查询配置文件中定义的:create_replica_methods,参考:配置文件https://patroni.readthedocs.io/en/latest/replica_bootstrap.html#custom-replica-creation | |
# 该配置是个列表,用户如果没有定义,那么默认使用pg_basebackup创建副本 | |
replica_methods = (clone_member.create_replica_methods if is_remote_master | |
else self._postgresql.create_replica_methods) or ['basebackup'] | |
if clone_member and clone_member.conn_url: | |
r = clone_member.conn_kwargs(self._postgresql.config.replication) | |
# add the credentials to connect to the replica origin to pgpass. | |
# clone对象的连接串信息被写入pgpass文件 | |
env = self._postgresql.config.write_pgpass(r) | |
connstring = self._postgresql.config.format_dsn(r, True) | |
else: | |
# 没有上游配置时,通过何种方式clone,此时replica_methods方法中的定义 | |
connstring = '' | |
env = os.environ.copy() | |
# if we don't have any source, leave only replica methods that work without it | |
replica_methods = [r for r in replica_methods | |
if self._postgresql.replica_method_can_work_without_replication_connection(r)] | |
# go through them in priority order | |
ret = 1 | |
for replica_method in replica_methods: | |
if self._postgresql.cancellable.is_cancelled: | |
break | |
method_config = self._postgresql.replica_method_options(replica_method) | |
# if the method is basebackup, then use the built-in | |
# 默认配置 | |
if replica_method == "basebackup": | |
ret = self.basebackup(connstring, env, method_config) | |
if ret == 0: | |
logger.info("replica has been created using basebackup") | |
# if basebackup succeeds, exit with success | |
break | |
else: | |
if not self._postgresql.data_directory_empty(): | |
# 指定 keep_data 参数时保留数据目录数据 | |
if method_config.get('keep_data', False): | |
logger.info('Leaving data directory uncleaned') | |
else: | |
self._postgresql.remove_data_directory() | |
cmd = replica_method | |
# user-defined method; check for configuration | |
# not required, actually | |
if method_config: | |
# look to see if the user has supplied a full command path | |
# if not, use the method name as the command | |
cmd = method_config.pop('command', cmd) | |
# add the default parameters | |
# 追加自定义配置 | |
if not method_config.get('no_params', False): | |
method_config.update({"scope": self._postgresql.scope, | |
"role": "replica", | |
"datadir": self._postgresql.data_dir, | |
"connstring": connstring}) | |
else: | |
for param in ('no_params', 'no_master', 'keep_data'): | |
method_config.pop(param, None) | |
params = ["--{0}={1}".format(arg, val) for arg, val in method_config.items()] | |
try: | |
# call script with the full set of parameters | |
ret = self._postgresql.cancellable.call(shlex.split(cmd) + params, env=env) | |
# if we succeeded, stop | |
if ret == 0: | |
logger.info('replica has been created using %s', replica_method) | |
break | |
else: | |
logger.error('Error creating replica using method %s: %s exited with code=%s', | |
replica_method, cmd, ret) | |
except Exception: | |
logger.exception('Error creating replica using method %s', replica_method) | |
ret = 1 | |
self._postgresql.set_state('stopped') | |
return ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment