高可用架构 学习笔记(第 3 部分)
2.2 业务逻辑保护
2.2.1 故障类型
人为失误 + 软件错误:
plaintext
业务逻辑保护故障类型:
人为失误
├── 误删除数据
├── 错误配置
├── 发布错误应用
└── 操作失误
软件错误
├── 操作系统 bug
├── 数据库 bug
├── 应用 bug
└── 第三方库 bug
安全事件
├── 数据泄露
├── 恶意攻击
└── 商户跑路(数据丢失)2.2.2 故障特点
| 特点 | 说明 | 解决方案 |
|---|---|---|
| 需要数据恢复 | 数据误删、篡改 | 快照、备份 |
| 需要决策干预 | 人为判断处理 | 监控告警、人工介入 |
| 需要问题追溯 | 查找原因 | 审计日志、追踪系统 |
2.2.3 典型技术方案
1. 数据快照
javascript
// 数据快照实现
class DataSnapshot {
constructor() {
this.snapshots = new Map()
}
// 创建快照
createSnapshot(database, snapshotName) {
const timestamp = Date.now()
const snapshot = {
name: snapshotName,
timestamp,
data: this.cloneData(database),
size: this.calculateSize(database)
}
this.snapshots.set(snapshotName, snapshot)
console.log(`快照 ${snapshotName} 创建成功`)
console.log(`时间: ${new Date(timestamp).toLocaleString()}`)
console.log(`大小: ${snapshot.size} MB`)
return snapshot
}
// 恢复快照
restoreSnapshot(snapshotName, database) {
const snapshot = this.snapshots.get(snapshotName)
if (!snapshot) {
throw new Error(`快照 ${snapshotName} 不存在`)
}
// 恢复数据
Object.assign(database, snapshot.data)
console.log(`快照 ${snapshotName} 恢复成功`)
console.log(`快照时间: ${new Date(snapshot.timestamp).toLocaleString()}`)
return database
}
// 列出所有快照
listSnapshots() {
const list = []
this.snapshots.forEach((snapshot, name) => {
list.push({
name,
timestamp: new Date(snapshot.timestamp).toLocaleString(),
size: snapshot.size
})
})
return list
}
// 克隆数据
cloneData(data) {
return JSON.parse(JSON.stringify(data))
}
// 计算大小
calculateSize(data) {
const json = JSON.stringify(data)
return (Buffer.byteLength(json, 'utf8') / 1024 / 1024).toFixed(2)
}
}
// 使用示例
const snapshotManager = new DataSnapshot()
const database = {
users: [
{ id: 1, name: '张三', balance: 1000 },
{ id: 2, name: '李四', balance: 2000 }
]
}
// 创建快照
snapshotManager.createSnapshot(database, 'before_update')
// 模拟数据误操作
database.users[0].balance = 0
console.log('误操作后:', database.users[0])
// 恢复快照
snapshotManager.restoreSnapshot('before_update', database)
console.log('恢复后:', database.users[0])2. 审计日志
javascript
// 审计日志系统
class AuditLogger {
constructor() {
this.logs = []
}
// 记录操作日志
log(action, userId, details) {
const logEntry = {
timestamp: new Date().toISOString(),
action,
userId,
details,
ip: this.getClientIP(),
userAgent: this.getUserAgent()
}
this.logs.push(logEntry)
// 持久化存储
this.saveToFile(logEntry)
return logEntry
}
// 查询日志
query(filters) {
return this.logs.filter(log => {
if (filters.userId && log.userId !== filters.userId) return false
if (filters.action && log.action !== filters.action) return false
if (filters.startTime && new Date(log.timestamp) < new Date(filters.startTime)) return false
if (filters.endTime && new Date(log.timestamp) > new Date(filters.endTime)) return false
return true
})
}
// 保存到文件
saveToFile(logEntry) {
const logLine = JSON.stringify(logEntry) + '\n'
fs.appendFileSync('audit.log', logLine)
}
// 获取客户端 IP
getClientIP() {
return '192.168.1.100'
}
// 获取 User Agent
getUserAgent() {
return 'Mozilla/5.0 ...'
}
}
// 使用示例
const auditLogger = new AuditLogger()
// 记录用户操作
auditLogger.log('DELETE_USER', 'admin001', {
deletedUserId: 123,
reason: '违规操作'
})
auditLogger.log('UPDATE_BALANCE', 'admin002', {
userId: 456,
oldBalance: 1000,
newBalance: 500
})
// 查询日志
const logs = auditLogger.query({
userId: 'admin001',
startTime: '2024-01-01'
})3. 灰度发布