AWS RDS MySQL 主從同步延遲總結

最近居然被 MySQL 主從同步的問題坑了, 簡直丟盡了老司機的臉, 總結一下.

問題很簡單, 一個業務由于 MySQL 主從同步延遲導致讀取的數據有問題. 問題解決了, 但如何在 AWS RDS 中獲取 MySQL 的延遲信息呢? 非 AWS RDS 的傳統 MySQL 中, 可以直接連到 server 通過 SHOW SLAVE STATUS 獲取延遲信息.

RDS 呢?

0x00 無處不在的 Cloudwatch

AWS 中大多數(我也不確定是不是所有服務)都接入了 Cloudwatch. Cloudwatch 的好處就是可以作為一個中間層抽象, 將不同系統的數據抽象成一個模型, 統一通過 Cloudwatch API 訪問. 就拿主從延遲來說, MySQL/MariaDB 和 PostgeSQL 的計算方法顯然是不一樣的:

因此, 只要通過 Cloudwatch API 獲取 ReplicaLag 這個 metric 的值就可以判斷主從同步延遲, 不管是哪種 DB

def get_cloudwatch_replica_lag(rds_id, start_time, end_time)
    local_timezone = pytz.timezone('Asia/Shanghai')
    cloudwatch = boto3.client('cloudwatch')
    start_time_with_tz = local_timezone.localize(start_time)
    end_time_with_tz = local_timezone.localize(end_time)
    values = cloudwatch.get_metric_statistics(Namespace='AWS/RDS',
                                              MetricName='ReplicaLag',
                                              Dimensions=[dict(Name='DBInstanceIdentifier', Value=rds_id)],
                                              StartTime=start_time_with_tz,
                                              EndTime=end_time_with_tz,
                                              Period=60,
                                              Statistics=['Maximum'],
                                              Unit='Seconds').get('Datapoints')
    return values

0x01 Cloudwatch API "進城手冊"

看上去挺簡單的 API, 還是需要"進城手冊", 避免撓頭:

  1. Cloudwatch API 中的傳入的時間必須攜帶時區, 默認是 UTC, 當然, 如果你廠高瞻遠矚的都按照 UTC 來使用時間了就不用操這個心了
  2. DBInstanceIdentifier 必須存在才會有數據, 若傳入一個錯誤的 DBInstanceIdentifier 返回結果是空, 不要以為是沒有 lag, 因此建議在 Cloudwatch API 前面加一個 RDS 的 DescribeInstance 調用, 確定 DBInstanceIdentifier 的值是正確的
  3. 返回結果的 datetime 也是 UTC
  4. Cloudwatch 雖然是監控數據, 但也是需要 IAM 權限的, 需要加上 IAM 中加上 cloudwatch:GetMetricStatistics 權限
  5. Period=60 代表獲取1分鐘粒度的數據, 這是 Cloudwatch 支持的最細顆粒度的數據
    {
      "Effect": "Allow",
      "Action": [
        "cloudwatch:GetMetricStatistics"
      ],
      "Resource": [
        "*"
      ]
    }

0x02 檢查 ReplicaLag 的時間間隔

由于 Cloudwatch 支持的最細顆粒度的 metric 是1分鐘, 因此僅僅獲取前一分鐘的數據可能會有 Cloudwatch 數據還未抓取到的問題.
建議是獲取前一段時間(比如10分鐘)的數據, 確保前10分鐘的 ReplicaLag 都為0(或者小于一個可以接受的值), 則認為現在的狀態是滿足數據需求的.

總結

MySQL 主從同步從入行就知道是需要重點關注的, 結果還是忽略了一下就掉坑里了. AWS Cloudwatch 也支持根據 ReplicaLag 的值直接告警的, 建議一定要設置一個.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容