Skip to content

Neo4j 从单实例到集群

迁移前准备

迁移前准备是确保从单实例到集群迁移成功的关键步骤,包括环境准备、数据准备和集群规划等方面。充分的准备工作可以降低迁移风险,确保迁移过程顺利进行。

1. 环境准备

硬件准备

Neo4j 集群需要一定的硬件资源支持,特别是核心节点需要较高的配置以确保集群的稳定性和性能。以下是推荐的硬件配置:

节点类型数量配置要求说明
核心节点38核CPU,16GB内存,500GB SSD核心节点负责处理写入操作和维护集群一致性,至少需要3个节点以确保高可用性
只读副本28核CPU,16GB内存,500GB SSD只读副本负责处理读操作,可根据业务需求扩展数量
负载均衡器14核CPU,8GB内存用于分发客户端请求,实现读写分离和故障转移

硬件选择建议

  • 核心节点建议使用高性能SSD存储,以提高写入性能和减少延迟
  • 所有节点建议使用相同的硬件配置,以避免性能瓶颈
  • 根据数据量和并发访问量调整硬件配置

软件准备

确保所有集群节点的软件环境一致,包括:

  • Neo4j版本:单实例和集群必须使用相同的Neo4j版本,建议使用最新的Enterprise Edition
  • 操作系统:推荐使用Linux CentOS 7/8或Ubuntu 18.04/20.04,确保所有节点使用相同的操作系统版本
  • Java版本:Neo4j 4.x和5.x支持Java 11或Java 17,确保所有节点使用相同的Java版本
  • 网络配置:确保节点间网络连通,开放必要端口,关闭不必要的防火墙规则

网络端口规划

Neo4j 集群需要开放多个端口用于节点间通信和客户端连接。以下是端口规划建议:

端口用途节点类型说明
7687Bolt协议所有节点客户端主要通信协议,用于应用程序连接
7474HTTP所有节点用于浏览器访问Neo4j Browser(建议生产环境关闭)
7473HTTPS所有节点安全的HTTP访问,用于加密的浏览器访问
5000集群发现核心节点用于集群节点发现和加入
6000集群通信核心节点用于Raft协议通信和数据复制

网络配置建议

  • 使用专用网络进行集群内部通信,提高安全性和性能
  • 确保节点间网络延迟低(建议小于1ms)
  • 启用网络加密,保护集群通信安全

2. 数据准备

数据准备是迁移过程中的重要环节,包括数据备份、清理和一致性检查等步骤。

数据备份

在开始迁移前,必须对单实例数据进行完整备份,以防止迁移过程中出现数据丢失。

bash
# 执行全量备份
neo4j-admin dump --database=neo4j --to=/path/to/backup/neo4j-full.dump

# 验证备份文件
echo $?  # 输出0表示备份成功

备份建议

  • 将备份文件存储在安全的位置,最好是异地存储
  • 验证备份文件的完整性
  • 定期测试备份恢复流程,确保备份可用

数据清理

在迁移前,建议清理不必要的数据,减少迁移数据量,提高迁移效率。

cypher
# 清理过期数据
MATCH (n:Log) WHERE n.timestamp < datetime().epochMillis - 30*24*60*60*1000
DETACH DELETE n;

# 清理孤立节点
MATCH (n) WHERE size((n)--()) = 0
DETACH DELETE n;

# 重建索引
CALL dbms.listIndexes() YIELD name
CALL apoc.schema.assert({}, {}, true) YIELD label, key RETURN label, key;

数据清理建议

  • 清理过期日志、临时数据和测试数据
  • 移除不再使用的节点、关系和属性
  • 重建索引,提高查询性能

数据一致性检查

在迁移前,必须检查数据一致性,确保数据库没有损坏。

bash
# 检查数据库完整性
neo4j-admin check-database --database=neo4j

一致性检查建议

  • 确保没有损坏的节点、关系或属性
  • 检查索引和约束的完整性
  • 验证事务日志的完整性

3. 集群规划

集群规划是迁移成功的关键,包括节点规划、配置规划和拓扑设计等。

节点规划

合理规划节点数量和角色,确保集群的高可用性和性能。

节点名称节点类型IP地址角色说明
neo4j-core-01核心节点192.168.1.101领导者集群的主节点,负责处理写入操作和协调集群
neo4j-core-02核心节点192.168.1.102跟随者复制领导者的数据,参与选举和投票
neo4j-core-03核心节点192.168.1.103跟随者复制领导者的数据,参与选举和投票
neo4j-replica-01只读副本192.168.1.104只读处理读操作,不参与选举
neo4j-replica-02只读副本192.168.1.105只读处理读操作,不参与选举

节点规划建议

  • 核心节点数量建议为奇数(3、5等),以避免脑裂问题
  • 根据读负载调整只读副本数量
  • 考虑跨可用区部署,提高集群的容灾能力

配置规划

确保所有节点的配置一致,特别是关键配置项。

配置项单实例集群说明
数据库文件/var/lib/neo4j/data/databases/neo4j/所有节点相同核心节点存储完整数据,只读副本复制核心节点数据
事务日志/var/lib/neo4j/data/transactions/neo4j/核心节点共享用于数据复制和故障恢复
堆内存16g16g根据节点内存大小调整,建议为总内存的一半
页缓存32g32g根据数据量调整,建议为总内存的一半
认证方式密码认证密码认证确保所有节点使用相同的认证配置
加密可选推荐启用生产环境建议启用SSL/TLS加密

配置规划建议

  • 使用配置管理工具(如Ansible、Puppet)统一管理集群配置
  • 定期备份配置文件
  • 测试配置变更,确保集群稳定性

冷迁移步骤

1. 停止单实例

bash
# 停止Neo4j单实例服务
systemctl stop neo4j

# 验证服务已停止
systemctl status neo4j

2. 部署集群节点

安装Neo4j

在所有集群节点上安装Neo4j:

bash
# 添加Neo4j仓库
wget -O - https://debian.neo4j.com/neotechnology.gpg.key | sudo apt-key add -
echo 'deb https://debian.neo4j.com stable latest' | sudo tee -a /etc/apt/sources.list.d/neo4j.list

# 更新包列表
sudo apt-get update

# 安装Neo4j Enterprise
sudo apt-get install neo4j-enterprise

配置核心节点

在核心节点上配置Neo4j:

txt
# neo4j-core-01配置
server.memory.heap.initial_size=16g
server.memory.heap.max_size=16g
server.memory.pagecache.size=32g

dbms.mode=CORE
dbms.cluster.initial_discovery_members=neo4j-core-01:5000,neo4j-core-02:5000,neo4j-core-03:5000
dbms.cluster.discovery.endpoints=neo4j-core-01:5000
dbms.cluster.raft.advertised_address=neo4j-core-01:6000
dbms.cluster.raft.listen_address=0.0.0.0:6000

dbms.connectors.default_advertised_address=neo4j-core-01
dbms.connectors.default_listen_address=0.0.0.0

dbms.connector.bolt.enabled=true
dbms.connector.bolt.listen_address=0.0.0.0:7687
dbms.connector.bolt.advertised_address=neo4j-core-01:7687

dbms.connector.http.enabled=true
dbms.connector.http.listen_address=0.0.0.0:7474
dbms.connector.http.advertised_address=neo4j-core-01:7474
dbms.connector.https.enabled=false

dbms.security.auth_enabled=true
dbms.security.auth_provider=native

配置只读副本

在只读副本节点上配置Neo4j:

txt
# neo4j-replica-01配置
server.memory.heap.initial_size=16g
server.memory.heap.max_size=16g
server.memory.pagecache.size=32g

dbms.mode=READ_REPLICA
dbms.cluster.initial_discovery_members=neo4j-core-01:5000,neo4j-core-02:5000,neo4j-core-03:5000
dbms.cluster.discovery.endpoints=neo4j-core-01:5000

dbms.connectors.default_advertised_address=neo4j-replica-01
dbms.connectors.default_listen_address=0.0.0.0

dbms.connector.bolt.enabled=true
dbms.connector.bolt.listen_address=0.0.0.0:7687
dbms.connector.bolt.advertised_address=neo4j-replica-01:7687
dbms.connector.http.enabled=true
dbms.connector.http.listen_address=0.0.0.0:7474
dbms.connector.http.advertised_address=neo4j-replica-01:7474
dbms.connector.https.enabled=false

dbms.security.auth_enabled=true
dbms.security.auth_provider=native

3. 迁移数据

复制数据到核心节点

bash
# 将单实例数据复制到第一个核心节点
scp -r /var/lib/neo4j/data/databases/neo4j neo4j-core-01:/var/lib/neo4j/data/databases/
scp -r /var/lib/neo4j/data/transactions/neo4j neo4j-core-01:/var/lib/neo4j/data/transactions/

# 设置正确的权限
ssh neo4j-core-01 "chown -R neo4j:neo4j /var/lib/neo4j/data/"

4. 启动集群

启动核心节点

bash
# 启动第一个核心节点
ssh neo4j-core-01 "systemctl start neo4j"

# 等待30秒,确保节点完全启动
sleep 30

# 启动其他核心节点
ssh neo4j-core-02 "systemctl start neo4j"
ssh neo4j-core-03 "systemctl start neo4j"

# 等待30秒
sleep 30

# 启动只读副本
ssh neo4j-replica-01 "systemctl start neo4j"
ssh neo4j-replica-02 "systemctl start neo4j"

验证集群状态

bash
# 连接到核心节点,验证集群状态
cypher-shell -u neo4j -p password -a bolt://neo4j-core-01:7687 -c "CALL dbms.cluster.overview();"

5. 配置负载均衡

配置HAProxy

txt
# HAProxy配置
frontend neo4j-frontend
    bind *:7687
    mode tcp
    option tcplog
    acl write_request payload(0,1) -m bin 0x10
    use_backend neo4j-write if write_request
    default_backend neo4j-read

backend neo4j-write
    mode tcp
    balance roundrobin
    server neo4j-core-01 neo4j-core-01:7687 check
    server neo4j-core-02 neo4j-core-02:7687 check
    server neo4j-core-03 neo4j-core-03:7687 check

backend neo4j-read
    mode tcp
    balance roundrobin
    server neo4j-replica-01 neo4j-replica-01:7687 check
    server neo4j-replica-02 neo4j-replica-02:7687 check
    server neo4j-core-01 neo4j-core-01:7687 check backup
    server neo4j-core-02 neo4j-core-02:7687 check backup
    server neo4j-core-03 neo4j-core-03:7687 check backup

6. 应用迁移

更新应用配置

将应用连接从单实例切换到负载均衡器:

java
// 旧配置
Driver driver = GraphDatabase.driver("bolt://single-instance:7687", AuthTokens.basic("neo4j", "password"));

// 新配置
Driver driver = GraphDatabase.driver("bolt://load-balancer:7687", AuthTokens.basic("neo4j", "password"));

测试应用连接

bash
# 测试应用连接
java -cp app.jar com.example.Neo4jConnectionTest

热迁移步骤

1. 部署集群

按照冷迁移的步骤2部署集群节点,但不启动服务。

2. 配置数据同步

配置单实例为核心节点

修改单实例配置,使其成为集群的第一个核心节点:

txt
# 修改单实例配置
dbms.mode=CORE
dbms.cluster.initial_discovery_members=single-instance:5000,neo4j-core-02:5000,neo4j-core-03:5000
dbms.cluster.discovery.endpoints=single-instance:5000
dbms.cluster.raft.advertised_address=single-instance:6000
dbms.cluster.raft.listen_address=0.0.0.0:6000

3. 重启单实例

bash
# 重启单实例,使其成为集群的第一个核心节点
systemctl restart neo4j

4. 启动其他集群节点

bash
# 启动其他核心节点
ssh neo4j-core-02 "systemctl start neo4j"
ssh neo4j-core-03 "systemctl start neo4j"

# 等待30秒
sleep 30

# 启动只读副本
ssh neo4j-replica-01 "systemctl start neo4j"
ssh neo4j-replica-02 "systemctl start neo4j"

5. 验证数据同步

cypher
# 在单实例上创建测试数据
CREATE (n:MigrationTest {name: 'Hot Migration Test', created: datetime()});

# 在其他节点上验证数据同步
MATCH (n:MigrationTest {name: 'Hot Migration Test'}) RETURN n;

6. 切换流量

将应用流量从单实例切换到负载均衡器,与冷迁移步骤5相同。

迁移后验证

1. 功能验证

基本功能验证

cypher
# 创建节点
CREATE (n:Test {name: 'Cluster Test', created: datetime()});

# 创建关系
MATCH (n1:Test {name: 'Cluster Test'}), (n2:User {id: 123})
CREATE (n1)-[:RELATED_TO]->(n2);

# 查询数据
MATCH (n:Test)-[:RELATED_TO]->(u:User)
RETURN n, u;

# 更新数据
MATCH (n:Test {name: 'Cluster Test'})
SET n.updated = datetime(), n.status = 'updated';

# 删除数据
MATCH (n:Test {name: 'Cluster Test'})
DETACH DELETE n;

事务功能验证

cypher
# 测试事务提交
BEGIN TRANSACTION;
MATCH (n:User {id: 123}) SET n.balance = n.balance + 100;
MATCH (n:User {id: 456}) SET n.balance = n.balance - 100;
COMMIT;

# 测试事务回滚
BEGIN TRANSACTION;
MATCH (n:User {id: 123}) SET n.balance = n.balance + 200;
MATCH (n:User {id: 456}) SET n.balance = n.balance - 200;
ROLLBACK;

2. 性能验证

基准测试

bash
# 使用apoc.load.csv导入测试数据
cypher-shell -u neo4j -p password -f /path/to/test-data.cypher

# 执行基准查询
cypher-shell -u neo4j -p password -c "MATCH (n:User)-[:FRIEND]->(m:User) WHERE n.city = 'Beijing' RETURN n, m LIMIT 100;"

负载测试

使用JMeter或NeoLoad进行负载测试,比较迁移前后的性能差异。

3. 高可用性验证

故障转移测试

bash
# 模拟核心节点故障
ssh neo4j-core-01 "systemctl stop neo4j"

# 验证集群仍然可用
cypher-shell -u neo4j -p password -a bolt://neo4j-core-02:7687 -c "CREATE (n:FailoverTest {name: 'Failover Test', created: datetime()});"

# 恢复故障节点
ssh neo4j-core-01 "systemctl start neo4j"

# 验证节点重新加入集群
cypher-shell -u neo4j -p password -c "CALL dbms.cluster.overview();"

迁移后优化

1. 配置优化

集群配置优化

txt
# neo4j.conf 集群优化配置
dbms.cluster.pullers=4
dbms.cluster.timeout=10s
dbms.checkpoint.interval.time=30m
dbms.checkpoint.interval.tx=100000
dbms.tx_log.rotation.size=256m
dbms.tx_log.rotation.retention_policy=100M size

读写分离优化

java
// 应用层实现读写分离
// 写操作 - 发送到核心节点
Driver writeDriver = GraphDatabase.driver("bolt://neo4j-core-01:7687", AuthTokens.basic("neo4j", "password"));

// 读操作 - 发送到只读副本
Driver readDriver = GraphDatabase.driver("bolt://neo4j-replica-01:7687", AuthTokens.basic("neo4j", "password"));

2. 监控优化

添加集群监控指标

yaml
# Prometheus告警规则
- alert: Neo4jClusterNodeDown
  expr: neo4j_cluster_member_count < 3
  for: 5m
  labels:
    severity: critical
  annotations:
    summary: "Neo4j集群节点离线"
    description: "Neo4j集群节点数量不足3个,当前数量: {{ $value }}"

- alert: Neo4jReplicationDelayHigh
  expr: neo4j_transaction_puller_delay_seconds > 30
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "Neo4j复制延迟过高"
    description: "Neo4j复制延迟超过30秒,当前延迟: {{ $value }}秒"

常见问题(FAQ)

Q1: 冷迁移和热迁移各有什么优缺点?

A1: 冷迁移和热迁移的优缺点比较:

方案优点缺点
冷迁移简单可靠,数据一致性高需停机,影响业务
热迁移无需停机,业务连续性好配置复杂,风险较高

Q2: 迁移过程中如何确保数据一致性?

A2: 确保数据一致性的方法:

  1. 迁移前执行数据完整性检查
  2. 迁移过程中停止写入操作(冷迁移)
  3. 迁移后验证数据数量和内容
  4. 使用事务保证数据一致性
  5. 监控数据复制延迟

Q3: 集群迁移后性能下降怎么办?

A3: 集群迁移后性能下降的解决方法:

  1. 检查查询执行计划,优化查询
  2. 调整集群配置,如增加复制线程数
  3. 优化网络配置,减少延迟
  4. 增加只读副本数量,分散读负载
  5. 调整页缓存大小

Q4: 如何处理迁移过程中的错误?

A4: 处理迁移错误的步骤:

  1. 记录错误信息,分析原因
  2. 回滚到迁移前的状态
  3. 修复错误后重新迁移
  4. 如果是热迁移,确保单实例仍可正常运行
  5. 测试修复后的配置

Q5: 迁移后如何管理集群?

A5: 集群管理的最佳实践:

  1. 定期备份集群数据
  2. 监控集群状态和性能
  3. 定期检查节点健康状况
  4. 实施自动化部署和配置管理
  5. 制定集群扩展和缩容策略

Q6: 如何实现跨可用区部署?

A6: 跨可用区部署的步骤:

  1. 在不同可用区部署集群节点
  2. 配置合适的网络延迟和带宽
  3. 启用数据加密
  4. 配置跨可用区负载均衡
  5. 测试跨可用区故障转移

Q7: 迁移后如何进行扩容?

A7: 集群扩容的步骤:

  1. 部署新的集群节点
  2. 配置节点加入现有集群
  3. 启动新节点
  4. 验证节点加入集群
  5. 调整负载均衡配置

Q8: 如何备份集群数据?

A8: 集群数据备份的方法:

  1. 使用neo4j-admin backup命令备份集群
  2. 配置定期自动备份
  3. 备份到异地存储
  4. 测试备份恢复流程
  5. 监控备份状态