{T}

异地容灾与多活架构 学习笔记(第 7 部分)

3.2 数据库层容灾

技术方案:数据库复制技术

code
数据库层容灾架构:

主数据中心                  备数据中心
┌──────────────┐           ┌──────────────┐
│ 应用服务器    │           │ 应用服务器    │
└──────┬───────┘           └──────┬───────┘
       │                          │
       ↓                          ↓
┌──────────────┐           ┌──────────────┐
│ MySQL 主库    │ ────────→ │ MySQL 从库    │
│ (A厂存储)     │   Binlog   │ (B厂存储)     │
└──────────────┘   同步     └──────────────┘

特点:
- 存储异构支持
- 占用网络带宽
- 占用应用资源
- 配置灵活

优势与劣势

优势劣势
支持异构存储占用网络带宽
配置灵活占用应用资源
成本相对较低复制延迟问题
技术成熟可能影响性能

主流数据库容灾技术

javascript
// 数据库容灾技术对比
const databaseDR = {
  // MySQL
  mysql: {
    replication: {
      async: '异步复制',
      semiSync: '半同步复制',
      group: '组复制(MGR)'
    },
    tools: ['MySQL Replication', 'MySQL Router', 'MHA', 'Orchestrator'],
    features: [
      '开源免费',
      '配置简单',
      '支持异构存储',
      '延迟监控方便'
    ]
  },
  
  // Oracle
  oracle: {
    technologies: {
      dataguard: 'Data Guard(物理/逻辑备库)',
      rac: 'RAC(集群)',
      goldengate: 'Golden Gate(逻辑复制)'
    },
    features: [
      '功能强大',
      '企业级支持',
      '数据一致性保证',
      '成本高昂'
    ]
  },
  
  // PostgreSQL
  postgresql: {
    replication: {
      streaming: '流复制',
      logical: '逻辑复制',
      cascading: '级联复制'
    },
    features: [
      '开源免费',
      '功能丰富',
      '性能优秀',
      '社区活跃'
    ]
  },
  
  // MongoDB
  mongodb: {
    replication: {
      replicaSet: '副本集',
      sharding: '分片集群'
    },
    features: [
      '自动故障转移',
      '支持跨机房部署',
      '配置简单',
      '性能优秀'
    ]
  }
}

MySQL 数据库容灾实现

javascript
// MySQL 主从复制管理
class MySQLReplicationManager {
  constructor() {
    this.master = {
      host: 'master.db.example.com',
      port: 3306,
      status: 'active'
    }
    
    this.slaves = [
      { host: 'slave1.db.example.com', port: 3306, status: 'active' },
      { host: 'slave2.db.example.com', port: 3306, status: 'active' }
    ]
  }
  
  // 监控复制状态
  async monitorReplication() {
    const replicationStatus = []
    
    for (const slave of this.slaves) {
      const status = await this.getSlaveStatus(slave)
      
      replicationStatus.push({
        slave: slave.host,
        ioRunning: status.Slave_IO_Running,
        sqlRunning: status.Slave_SQL_Running,
        secondsBehindMaster: status.Seconds_Behind_Master,
        lastError: status.Last_Error
      })
      
      // 检查延迟
      if (status.Seconds_Behind_Master > 10) {
        this.sendAlert({
          type: 'replication_lag',
          slave: slave.host,
          delay: status.Seconds_Behind_Master
        })
      }
    }
    
    return replicationStatus
  }
  
  // 获取从库状态
  async getSlaveStatus(slave) {
    // 实际实现:执行 SHOW SLAVE STATUS
    return {
      Slave_IO_Running: 'Yes',
      Slave_SQL_Running: 'Yes',
      Seconds_Behind_Master: 0,
      Last_Error: ''
    }
  }
  
  // 主从切换
  async failover(failedMaster) {
    console.log('开始主从切换...')
    
    // 1. 选择新的主库
    const newMaster = this.selectNewMaster()
    
    // 2. 停止所有从库复制
    await this.stopAllSlaves()
    
    // 3. 提升新主库
    await this.promoteToMaster(newMaster)
    
    // 4. 重新配置其他从库
    await this.reconfigureSlaves(newMaster)
    
    // 5. 更新应用配置
    await this.updateApplicationConfig(newMaster)
    
    console.log(`主从切换完成,新主库: ${newMaster.host}`)
  }
  
  // 选择新主库
  selectNewMaster() {
    // 选择延迟最小的从库
    const sortedSlaves = this.slaves.sort((a, b) => {
      return a.delay - b.delay
    })
    
    return sortedSlaves[0]
  }
  
  // 停止所有从库复制
  async stopAllSlaves() {
    for (const slave of this.slaves) {
      // 执行 STOP SLAVE
      console.log(`停止从库 ${slave.host} 复制`)
    }
  }
  
  // 提升为主库
  async promoteToMaster(slave) {
    // 执行 RESET SLAVE ALL
    console.log(`提升 ${slave.host} 为主库`)
  }
  
  // 重新配置从库
  async reconfigureSlaves(newMaster) {
    for (const slave of this.slaves) {
      if (slave !== newMaster) {
        // CHANGE MASTER TO ...
        console.log(`重新配置从库 ${slave.host}`)
      }
    }
  }
  
  // 更新应用配置
  async updateApplicationConfig(newMaster) {
    // 更新数据库连接配置
    console.log('更新应用数据库连接配置')
  }
  
  // 发送告警
  sendAlert(alert) {
    console.log('发送告警:', alert)
  }
}