Skip to content

Neo4j 手动故障转移

手动故障转移前提条件

集群架构要求

  1. 核心节点数量

    • 最少3个核心节点,推荐奇数个节点
    • 确保集群能够形成多数派
  2. 集群健康状态

    • 大多数核心节点处于健康状态
    • 集群通信正常
    • 数据同步状态良好
  3. 备份状态

    • 最近有成功的备份
    • 确保数据安全性

监控和准备工作

  1. 监控工具

    • 确保监控系统正常运行
    • 配置关键指标告警
    • 实时监控集群状态
  2. 准备工作

    • 确认当前主节点和其他节点状态
    • 检查数据同步情况
    • 准备故障转移命令和脚本
    • 通知相关团队和人员
  3. 回滚计划

    • 制定详细的回滚计划
    • 准备回滚命令和脚本
    • 确保能够快速恢复到原始状态

工具和权限要求

  1. 访问权限

    • 集群节点的 SSH 访问权限
    • Neo4j 管理员权限
    • 操作系统管理员权限
  2. 工具准备

    • Neo4j 命令行工具(neo4j-admin, cypher-shell)
    • 集群监控工具
    • SSH 客户端
    • 日志查看工具

手动故障转移操作步骤

1. 故障检测和确认

检查集群状态

cypher
// 查看集群状态
CALL dbms.cluster.overview()
YIELD address, role, databases
RETURN address, role, databases
ORDER BY role;
bash
# 使用 neo4j-admin 查看集群状态
neo4j-admin cluster status

确认主节点故障

bash
# 检查主节点状态
ssh <master-node> "systemctl status neo4j"

# 检查主节点日志
ssh <master-node> "tail -n 100 /opt/neo4j/logs/neo4j.log"

# 检查网络连接
ping <master-node>
telnet <master-node> 7687

2. 选择新的主节点

评估候选节点

cypher
// 评估节点状态
CALL dbms.cluster.overview()
YIELD address, role, databases
WITH address, role, databases
UNWIND databases AS db
RETURN address, db.name AS database, db.status AS status, db.defaultAccessMode AS accessMode
ORDER BY address;

选择标准

  • 节点状态正常
  • 数据同步状态良好
  • 硬件资源充足
  • 网络连接稳定
  • 地理位置合理(如果是跨数据中心部署)

3. 执行故障转移操作

方法一:使用 cypher-shell 手动触发选举

cypher
// 查看当前主节点
CALL dbms.cluster.overview()
YIELD address, role
WHERE role = 'LEADER'
RETURN address AS current_leader;

// 手动触发选举(从任意核心节点执行)
CALL dbms.cluster.rotateLeader();

方法二:使用 neo4j-admin 命令

bash
# 手动切换主节点
neo4j-admin cluster promote --database=neo4j --to=<new-leader-address>

方法三:通过配置文件调整

bash
# 在候选主节点上调整配置
ssh <candidate-node> "echo 'causal_clustering.leader_election_timeout=5s' >> /opt/neo4j/conf/neo4j.conf"

# 重启候选节点
ssh <candidate-node> "systemctl restart neo4j"

4. 验证故障转移结果

检查新主节点状态

cypher
// 查看新的主节点
CALL dbms.cluster.overview()
YIELD address, role
WHERE role = 'LEADER'
RETURN address AS new_leader;

// 检查数据库状态
CALL dbms.databases()
YIELD name, status, defaultAccessMode
RETURN name, status, defaultAccessMode;

验证数据一致性

bash
# 检查数据一致性
neo4j-admin debug consistency --database=neo4j

# 验证数据完整性
cypher-shell -u neo4j -p <password> -c "MATCH (n) RETURN count(n) AS node_count;"
cypher-shell -u neo4j -p <password> -c "MATCH ()-[r]->() RETURN count(r) AS relationship_count;"

测试读写操作

cypher
// 测试写操作
CREATE (t:Test {name: 'failover-test', timestamp: datetime()});

// 测试读操作
MATCH (t:Test) WHERE t.name = 'failover-test' RETURN t;

// 清理测试数据
MATCH (t:Test) WHERE t.name = 'failover-test' DELETE t;

5. 恢复故障节点

修复故障节点

bash
# 登录故障节点
ssh <failed-node>

# 检查故障原因
journalctl -xe | grep -i neo4j
tail -n 200 /opt/neo4j/logs/neo4j.log

# 修复故障
# 例如,修复硬件问题、网络问题或配置问题

# 重启节点
neo4j restart

重新加入集群

cypher
// 检查节点是否重新加入集群
CALL dbms.cluster.overview()
YIELD address, role
RETURN address, role;

// 检查数据同步状态
CALL dbms.cluster.overview()
YIELD address, databases
UNWIND databases AS db
RETURN address, db.name AS database, db.status AS status;

不同场景下的手动故障转移

主节点故障场景

场景描述

  • 主节点突然宕机
  • 无法通过网络访问
  • 自动故障转移未触发或失败

处理步骤

  1. 确认主节点故障

    bash
    # 多次尝试连接主节点
    for i in {1..5}; do ssh <master-node> "echo 'test'" || echo "Connection failed $i"; sleep 1; done
  2. 检查集群状态

    cypher
    CALL dbms.cluster.overview()
    YIELD address, role
    RETURN address, role;
  3. 执行手动故障转移

    cypher
    CALL dbms.cluster.rotateLeader();
  4. 验证新主节点

    cypher
    CALL dbms.cluster.overview()
    YIELD address, role
    WHERE role = 'LEADER'
    RETURN address;
  5. 恢复故障节点

    • 修复故障原因
    • 重启节点
    • 验证节点重新加入集群

网络分区场景

场景描述

  • 集群发生网络分区
  • 形成多个子集群
  • 出现分裂脑风险

处理步骤

  1. 检测网络分区

    bash
    # 检查节点间通信
    for node in <node1> <node2> <node3>; do
      echo "Checking connectivity to $node:"
      ping -c 3 $node
    done
  2. 确定分区情况

    cypher
    CALL dbms.cluster.overview()
    YIELD address, role
    RETURN address, role;
  3. 选择主要分区

    • 选择包含大多数核心节点的分区
    • 确保数据完整性
  4. 隔离次要分区

    bash
    # 停止次要分区的节点
    for node in <secondary-partition-nodes>; do
      ssh $node "neo4j stop"
    done
  5. 在主要分区执行故障转移

    cypher
    CALL dbms.cluster.rotateLeader();
  6. 修复网络问题

    • 修复网络故障
    • 逐步恢复次要分区节点
    • 验证集群完整性

计划内维护场景

场景描述

  • 主节点计划内维护
  • 需要将主节点切换到其他节点
  • 确保业务连续性

处理步骤

  1. 提前通知

    • 通知相关团队和用户
    • 选择合适的维护窗口
  2. 准备工作

    • 备份数据库
    • 检查集群状态
    • 准备故障转移命令
  3. 执行故障转移

    cypher
    CALL dbms.cluster.rotateLeader();
  4. 验证新主节点

    cypher
    CALL dbms.cluster.overview()
    YIELD address, role
    WHERE role = 'LEADER'
    RETURN address;
  5. 执行维护操作

    • 在原主节点上执行维护
    • 升级硬件、软件或配置
  6. 恢复原主节点

    • 重启原主节点
    • 验证节点重新加入集群
    • 可选:将主节点切换回原节点

故障转移后处理

数据一致性检查

检查数据完整性

bash
# 使用 neo4j-admin 检查数据一致性
neo4j-admin debug consistency --database=neo4j

# 检查事务日志
neo4j-admin tx-log info --database=neo4j

验证业务数据

cypher
// 验证关键业务数据
MATCH (u:User {id: 1}) RETURN u;
MATCH (p:Product {id: 100}) RETURN p;
MATCH (o:Order {id: 1000}) RETURN o;

// 验证关系完整性
MATCH (u:User {id: 1})-[:OWNS]->(p:Product) RETURN u, p;

监控调整

更新监控配置

bash
# 更新监控系统中的主节点信息
# 示例:Prometheus 配置更新
sed -i 's/<old-master-ip>/<new-master-ip>/g' /etc/prometheus/prometheus.yml

# 重启监控服务
systemctl restart prometheus

调整告警规则

yaml
# 更新告警规则,确保监控新的主节点
groups:
- name: neo4j-alerts
  rules:
  - alert: Neo4jHighCpuUsage
    expr: system_cpu_usage{instance="<new-master-ip>:9100"} > 80
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "Neo4j high CPU usage on {{ $labels.instance }}"
      description: "CPU usage is above 80% for 5 minutes"

文档更新

更新集群文档

  • 更新集群拓扑图
  • 更新主节点信息
  • 记录故障转移事件
  • 更新维护计划

更新操作手册

  • 更新故障转移步骤
  • 更新回滚计划
  • 添加经验教训
  • 更新联系方式

手动故障转移最佳实践

1. 定期演练

制定演练计划

  • 定期进行故障转移演练
  • 模拟不同故障场景
  • 记录演练过程和结果
  • 优化故障转移流程

演练步骤

  1. 准备工作

    • 通知相关团队
    • 准备演练脚本和工具
    • 确保监控系统正常运行
  2. 执行演练

    • 模拟主节点故障
    • 执行手动故障转移
    • 验证故障转移结果
    • 恢复故障节点
  3. 评估和优化

    • 分析演练结果
    • 识别问题和瓶颈
    • 优化故障转移流程
    • 更新文档和计划

2. 监控和告警

关键监控指标

  • 集群状态:节点状态、角色分布
  • 数据同步:复制延迟、事务日志应用速率
  • 资源使用:CPU、内存、磁盘 I/O
  • 网络状态:节点间通信延迟、丢包率

告警配置

yaml
# 示例:Prometheus 告警规则
- alert: Neo4jLeaderFailure
  expr: neo4j_cluster_role{role="LEADER"} == 0
  for: 1m
  labels:
    severity: critical
  annotations:
    summary: "Neo4j Leader Failure"
    description: "No leader found in the cluster for 1 minute"

- alert: Neo4jReplicationLag
  expr: neo4j_cluster_replication_lag > 1000
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "Neo4j High Replication Lag"
    description: "Replication lag is above 1000ms for 5 minutes"

3. 恢复计划

制定详细的恢复计划

  • 故障检测和确认流程
  • 故障转移操作步骤
  • 数据验证方法
  • 节点恢复流程
  • 回滚计划

恢复工具和脚本

bash
#!/bin/bash
# manual-failover.sh - 手动故障转移脚本

# 配置
NEO4J_USER="neo4j"
NEO4J_PASSWORD="password"
CLUSTER_NODES="node1 node2 node3"

# 检查集群状态
check_cluster_status() {
  echo "Checking cluster status..."
  for node in $CLUSTER_NODES; do
    echo "Node: $node"
    cypher-shell -a neo4j://$node:7687 -u $NEO4J_USER -p $NEO4J_PASSWORD "CALL dbms.cluster.overview() YIELD address, role RETURN address, role;"
    echo ""
  done
}

# 执行故障转移
execute_failover() {
  echo "Executing manual failover..."
  cypher-shell -a neo4j://$1:7687 -u $NEO4J_USER -p $NEO4J_PASSWORD "CALL dbms.cluster.rotateLeader();"
}

# 验证故障转移结果
verify_failover() {
  echo "Verifying failover result..."
  cypher-shell -a neo4j://$1:7687 -u $NEO4J_USER -p $NEO4J_PASSWORD "CALL dbms.cluster.overview() YIELD address, role WHERE role = 'LEADER' RETURN address AS new_leader;"
}

# 主流程
echo "Starting manual failover process..."
check_cluster_status

echo "Enter the node to execute failover:"
read EXECUTE_NODE

execute_failover $EXECUTE_NODE
verify_failover $EXECUTE_NODE

echo "Manual failover process completed."

4. 团队协作

明确角色和职责

  • DBA 团队:负责执行故障转移操作
  • 监控团队:负责故障检测和告警
  • 开发团队:负责验证业务功能
  • 运维团队:负责硬件和网络支持

建立沟通机制

  • 建立故障转移沟通频道
  • 明确通知流程
  • 制定决策流程
  • 建立 escalation 机制

常见问题和解决方案

问题 1:手动故障转移失败

症状

  • 执行故障转移命令后没有反应
  • 集群仍然没有主节点
  • 出现错误信息

解决方案

  1. 检查集群状态

    cypher
    CALL dbms.cluster.overview()
    YIELD address, role, databases
    RETURN address, role, databases;
  2. 检查节点状态

    bash
    for node in <node1> <node2> <node3>; do
      ssh $node "neo4j status"
    done
  3. 检查日志信息

    bash
    tail -n 200 /opt/neo4j/logs/neo4j.log | grep -i error
  4. 尝试其他方法

    • 重启所有核心节点
    • 检查网络连接
    • 验证集群配置

问题 2:数据不一致

症状

  • 故障转移后数据不完整
  • 查询结果不一致
  • 出现数据丢失

解决方案

  1. 检查数据一致性

    bash
    neo4j-admin debug consistency --database=neo4j
  2. 从备份恢复

    bash
    neo4j-admin restore --from=/backup/neo4j --database=neo4j --force
  3. 重新同步数据

    bash
    # 删除旧数据
    rm -rf /var/lib/neo4j/data/databases/neo4j
    rm -rf /var/lib/neo4j/data/transactions/neo4j
    
    # 重启节点,自动从其他节点同步数据
    neo4j restart

问题 3:节点无法重新加入集群

症状

  • 修复后的节点无法加入集群
  • 日志中出现连接错误
  • 节点状态异常

解决方案

  1. 检查网络连接

    bash
    ping <other-node>
    telnet <other-node> 5000
  2. 检查集群配置

    bash
    grep -A 10 "dbms.cluster" /opt/neo4j/conf/neo4j.conf
  3. 清理旧数据

    bash
    # 清理集群状态数据
    rm -rf /var/lib/neo4j/data/cluster/
    
    # 重启节点
    neo4j restart
  4. 手动添加节点

    cypher
    // 从其他节点执行
    CALL dbms.cluster.addNode('new-node:5000');

问题 4:分裂脑问题

症状

  • 集群出现多个主节点
  • 数据出现分歧
  • 集群状态混乱

解决方案

  1. 立即隔离节点

    bash
    # 停止多余的主节点
    for node in <node1> <node2>; do
      ssh $node "neo4j stop"
    done
  2. 选择权威节点

    • 选择数据最新、状态最健康的节点作为权威节点
    • 以该节点的数据为准
  3. 重建集群

    • 从权威节点恢复其他节点
    • 确保集群形成单一主节点
    • 验证数据一致性
  4. 预防措施

    • 确保集群节点数量为奇数
    • 配置合理的选举超时时间
    • 加强网络监控
    • 定期进行集群健康检查

常见问题(FAQ)

Q1: 什么时候需要执行手动故障转移?

A1: 手动故障转移适用于以下场景:

  • 计划内维护(硬件升级、软件更新、配置调整)
  • 自动故障转移失败
  • 集群处于分裂脑状态
  • 需要在特定时间窗口进行故障转移
  • 需要将主节点切换到特定健康节点
  • 需要验证故障转移流程

Q2: 手动故障转移前需要做哪些准备工作?

A2: 手动故障转移前的准备工作包括:

  • 确保监控系统正常运行
  • 备份数据库
  • 检查集群状态,确保多数核心节点健康
  • 准备故障转移命令和脚本
  • 制定回滚计划
  • 通知相关团队和用户

Q3: 如何选择新的主节点?

A3: 选择新主节点时应考虑以下因素:

  • 节点状态正常
  • 数据同步状态良好
  • 硬件资源充足
  • 网络连接稳定
  • 地理位置合理(跨数据中心部署时)

Q4: 手动故障转移有哪些风险?

A4: 手动故障转移的主要风险包括:

  • 数据不一致
  • 集群分裂脑
  • 业务中断
  • 节点无法重新加入集群

为降低这些风险,应严格遵循故障转移流程,做好准备工作,并在故障转移后验证结果。

Q5: 如何验证手动故障转移的结果?

A5: 手动故障转移后的验证工作包括:

  • 检查新主节点状态
  • 验证数据一致性
  • 测试读写操作
  • 检查集群完整性
  • 验证业务功能正常

Q6: 如何处理手动故障转移失败?

A6: 手动故障转移失败时的处理方法:

  • 检查集群状态和节点状态
  • 查看日志信息,分析失败原因
  • 尝试其他故障转移方法
  • 重启核心节点
  • 检查网络连接
  • 验证集群配置

Q7: 如何预防分裂脑问题?

A7: 预防分裂脑问题的措施包括:

  • 确保集群节点数量为奇数
  • 配置合理的选举超时时间
  • 加强网络监控,及时发现网络分区
  • 定期进行集群健康检查
  • 实施自动故障转移监控

Q8: 如何提高手动故障转移的成功率?

A8: 提高手动故障转移成功率的方法:

  • 定期进行故障转移演练
  • 制定详细的故障转移计划和脚本
  • 确保团队成员熟悉故障转移流程
  • 加强监控和告警
  • 做好备份和回滚准备
  • 保持集群处于健康状态

Q9: 计划内维护时如何执行手动故障转移?

A9: 计划内维护时的手动故障转移步骤:

  1. 提前通知相关团队和用户
  2. 选择合适的维护窗口
  3. 备份数据库
  4. 检查集群状态
  5. 执行故障转移操作
  6. 验证转移结果
  7. 在原主节点上执行维护操作
  8. 恢复原主节点并重新加入集群
  9. 可选:将主节点切换回原节点

Q10: 如何处理故障转移后的数据一致性问题?

A10: 处理数据一致性问题的方法:

  • 使用 neo4j-admin debug consistency 检查数据一致性
  • 从备份恢复有问题的节点
  • 重新同步数据(删除旧数据,让节点从其他节点重新同步)
  • 必要时重建集群,以健康节点的数据为准