{T}

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

存储虚拟化实现

javascript
// 存储虚拟化管理器
class StorageVirtualization {
  constructor() {
    this.storageNodes = {
      beijing: {
        endpoint: 'storage-bj.example.com',
        capacity: 1000,  // TB
        used: 300,
        latency: 5       // ms
      },
      shanghai: {
        endpoint: 'storage-sh.example.com',
        capacity: 1000,
        used: 350,
        latency: 8
      },
      guangzhou: {
        endpoint: 'storage-gz.example.com',
        capacity: 800,
        used: 200,
        latency: 12
      }
    }
  }
  
  // 统一写入接口
  async write(key, data) {
    // 1. 选择最优存储节点
    const node = this.selectOptimalNode()
    
    // 2. 写入数据
    await this.writeToNode(node, key, data)
    
    // 3. 异步同步到其他节点
    this.syncToOtherNodes(node, key, data)
    
    return { success: true, location: node }
  }
  
  // 统一读取接口
  async read(key) {
    // 从最近的节点读取
    const node = this.selectNearestNode()
    
    try {
      const data = await this.readFromNode(node, key)
      return data
    } catch (error) {
      // 失败时从其他节点读取
      return this.readFromOtherNodes(key)
    }
  }
  
  // 选择最优节点
  selectOptimalNode() {
    const nodes = Object.keys(this.storageNodes)
    
    // 根据负载和延迟选择
    const sorted = nodes.sort((a, b) => {
      const nodeA = this.storageNodes[a]
      const nodeB = this.storageNodes[b]
      
      const scoreA = this.calculateScore(nodeA)
      const scoreB = this.calculateScore(nodeB)
      
      return scoreB - scoreA
    })
    
    return sorted[0]
  }
  
  // 计算节点得分
  calculateScore(node) {
    const availableSpace = node.capacity - node.used
    const latencyScore = 100 - node.latency
    
    return availableSpace * 0.6 + latencyScore * 0.4
  }
  
  // 选择最近节点
  selectNearestNode() {
    const nodes = Object.keys(this.storageNodes)
    
    const sorted = nodes.sort((a, b) => {
      return this.storageNodes[a].latency - this.storageNodes[b].latency
    })
    
    return sorted[0]
  }
  
  // 写入到指定节点
  async writeToNode(nodeName, key, data) {
    // 实际实现:调用存储节点的 API
    console.log(`写入数据到 ${nodeName}: ${key}`)
  }
  
  // 从指定节点读取
  async readFromNode(nodeName, key) {
    console.log(`从 ${nodeName} 读取数据: ${key}`)
    return { data: 'example' }
  }
  
  // 同步到其他节点
  async syncToOtherNodes(sourceNode, key, data) {
    const otherNodes = Object.keys(this.storageNodes)
      .filter(n => n !== sourceNode)
    
    // 异步同步
    Promise.all(otherNodes.map(node => 
      this.writeToNode(node, key, data)
    ))
  }
  
  // 从其他节点读取
  async readFromOtherNodes(key) {
    const nodes = Object.keys(this.storageNodes)
    
    for (const node of nodes) {
      try {
        return await this.readFromNode(node, key)
      } catch (error) {
        continue
      }
    }
    
    throw new Error('数据读取失败')
  }
}

1.2.5 数据库双活

定义:两个数据库系统在相隔较远的情况下同时运行,支持相同的应用负载

plaintext
数据库双活架构:
 
北京数据库                上海数据库
┌──────────┐             ┌──────────┐
│ MySQL 主  │ ←─────────→ │ MySQL 主  │
└────┬─────┘   双向同步    └────┬─────┘
     │                         │
┌────┴─────┐             ┌────┴─────┐
│ 应用集群  │             │ 应用集群  │
│ (北京)   │             │ (上海)   │
└──────────┘             └──────────┘
     ↑                         ↑
     └─────────┬───────────────┘

         负载均衡


          用户请求
 
特点:
- 双主架构
- 双向数据同步
- 故障自动切换
- 支持跨地域部署

MySQL 双主复制配置

sql
-- 北京数据库配置 (my.cnf)
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW
auto-increment-increment = 2
auto-increment-offset = 1
 
-- 上海数据库配置 (my.cnf)
[mysqld]
server-id = 2
log-bin = mysql-bin
binlog-format = ROW
auto-increment-increment = 2
auto-increment-offset = 2
 
-- 北京数据库:配置上海为主
CHANGE MASTER TO
  MASTER_HOST='shanghai-db-ip',
  MASTER_USER='repl',
  MASTER_PASSWORD='password',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=0;
 
-- 上海数据库:配置北京为主
CHANGE MASTER TO
  MASTER_HOST='beijing-db-ip',
  MASTER_USER='repl',
  MASTER_PASSWORD='password',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=0;
 
-- 启动双向复制
START SLAVE;