按照任意一个IP或者域名查找该数据库实例所在集群架构、是不是主库或者从库,是DBA运维中很是常见和必不可少的功能。本文描述的功能实现已经实际应用于某互联网公司内部,目前运行稳定,持续提供服务。这里和你们分享实现方式,和你们一块儿学习。node
1. 前提条件
为了可以统一查找全部集群架构,这些机器须要有一个统一的可以访问全部机器的帐号和密码,这里使用db_admin;另外作主从同步的时候,须要使用统一的帐号和密码,这里使用repl。
做为示例,这里使用以下的集群结构:
这里A、B、C是主库的从库,是一级从库,D、E是从库C的从库,是二级从库,若是实际有其余更复杂的结构,以此类推便可。python
2. 搜索查找
平时查找,任意给一个IP或者域名进行查找,因为集群中是没法标示域名的,所以须要将域名转化为IP进行查找。按照任意IP查找,不会知道它在集群所处的位置,为了获得整个集群的结构须要先回溯到整个集群的主库。sql
3. 回溯主库
回溯主库使用db_admin帐号登陆MySQL执行"SHOW SLAVE STATUS"命令,查找当前库的主库信息进行整理。
针对以前的集群结构常见的回溯类型以下图的三种:数据库
最终要得到的都是主库实例,python的实现代码以下:json
# curr_node 当前搜索节点 # lisense 统一访问的帐号,密码 # sub_node 子节点 def traceback_root(curr_node, lisense, sub_node): query_process = 'SHOW SLAVE STATUS' master_row = None conn = None try: # 链接当前数据库,查找主库信息 conn = get_connection( curr_node.get('ip'), curr_node.get('port'), lisense.get('account'), lisense.get('passwd')) with open_cursor(conn) as cursor: cursor.execute(query_process) master_row = cursor.fetchone() except Exception as e: return None if master_row: return curr_node # 读取主库信息 io_run = master_row.get('Slave_IO_Running', '') sql_run = master_row.get('Slave_SQL_Running', '') master_ip = master_row.get('Master_Host', '') master_port = master_row.get('Master_Port', '') # 检查主库状态,状态不对返回当前节点 if io_run.lower() == 'yes' and sql_run.lower() == 'yes': may_master_node = dict() may_master_node['ip'] = master_ip may_master_node['port'] = master_port # 检查父节点实例信息是否和子节点同样, # 用来避免双主库回溯陷入无线循环的状况 if sub_node and sub_node.get('ip', '') == master_ip and\ sub_node.get('port', '') == master_port: return None # 因为考虑了双主的状况,当前库的父节点只是可能主库, # 使用父节点继续回溯主库实例 master_node = traceback_root( may_master_node, lisense, curr_node) # 若是回溯到主库,返回;不然返回当前节点 if master_node: return master_node else: return curr_node else: return curr_node
4. 遍历从库
找到主库以后,从主库开始,查找主库下的全部从库。查找从库使用db_admin登陆MySQL执行"SHOW PROCESSLIST"命令,而后从结果里,按照User是不是repl进行筛选,对于用户是repl的从库,链接上去使用回溯主库使用的查看主库的方法,验证从库的主库是不是当前查询的数据库实例,是的话,加入集群;不然放弃。对于查找出来的从库,继续使用上述方式查找从库,知道找到全部从库。多线程
5. 返回集群结构
查找出来的集群结构,按照json格式组织,能够返回给须要的服务,也能够整理以后显示在页面,下图是对查找出来的整个集群结构的简单显示:架构
6. 结束语
整个查询的大体过程如此,这里没有说太多的编码细节。在实际使用的过程当中,能够根据须要自行进行调整,如添加多线程提升查询速度等。运维