數據庫集羣主從架構查詢功能設計

按照任意一個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. 結束語
       整個查詢的大體過程如此,這裏沒有說太多的編碼細節。在實際使用的過程當中,能夠根據須要自行進行調整,如添加多線程提升查詢速度等。運維

相關文章
相關標籤/搜索