异地容灾与多活架构 学习笔记(第 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 数据库双活
定义:两个数据库系统在相隔较远的情况下同时运行,支持相同的应用负载
code
数据库双活架构:
北京数据库 上海数据库
┌──────────┐ ┌──────────┐
│ 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;