Redis(10) -- redis集群
Redis最开始使用主从模式做集群,若master宕机需要手动配置slave转为master;后来为了高可用提出来哨兵
模式,该模式下有一个哨兵监视master和slave,若master宕机可自动将slave转为master,但它也有一个问题,就是不能动态扩充
;所以在Redis 3.x提出cluster
集群模式。
1. 引言
Redis Cluster是Redis官方提供的Redis集群功能,为什么要实现Redis Cluster?
- 主从复制不能实现高可用
- 随着公司发展,用户数量增多,并发越来越多,业务需要更高的QPS,而主从复制中单机的QPS可能无法满足业务需求;
- 数据量的考虑,现有服务器内存不能满足业务数据的需要时,单纯向服务器添加内存不能达到要求,此时需要考虑分布式需求,把数据分布到不同服务器上;
- 网络流量需求,业务的流量已经超过服务器的网卡的上限值,可考虑使用分布式来进行分流;
- 离线计算,需要中间环节缓冲等其他需求;
在存储引擎框架(MySQL、HDFS、HBase、Redis、Elasticsearch等)中,只要数据量很大时,单机无法承受压力,最好的方式就是:数据分布进行存储管理。对Redis 内存数据库来说:全量数据,单机Redis节点无法满足要求,按照分区规则把数据分到若干个子集当中。
常用数据分布方式:
-
顺序分布:关系型数据库设计
比如:1到100个数字,要保存在3个节点上,按照顺序分区,把数据平均分配三个节点上,此时1号到33号数据保存到节点1上,34号到66号数据保存到节点2上,67号到100号数据保存到节点3上 - 哈希分布:
例如1到100个数字,对每个数字进行哈希hash运算,然后对每个数的哈希结果除以节点数进行取余,余数为1则保存在第1个节点上,余数为2则保存在第2个节点上,余数为0则保存在第3个节点,这样可以保证数据被打散,同时保证数据分布的比较均匀。
哈希分布方式分为三个分区方式:- 节点取余分区:比如有100个数据,对每个数据进行hash运算之后,与节点数进行取余运算,根据余数不同保存在不同的节点上
- 一致性哈希分区:将所有的数据当做一个token环,token环中的数据范围是0到2的32次方。然后为每一个数据节点分配一个token范围值,这个节点就负责保存这个范围内的数据。
- 虚拟槽分区:虚拟槽分区是Redis Cluster采用的分区方式,预设虚拟槽,每个槽就相当于一个数字,有一定范围。每个槽映射一个数据子集,一般比节点数大。Redis Cluster中预设虚拟槽的范围为0到16383。
2. Redis Cluster 设计
Redis Cluster是分布式架构,有多个节点,每个节点都负责进行数据读写操作,每个节点之间会进行通信。Redis Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
结构特点:
- 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽;
- 节点的fail是通过集群中超过半数的节点检测失效时才生效;
- 客户端与redis节点直连,不需要中间proxy层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可;
- redis-cluster 把所有的物理节点映射到
[0-16383]slot
上(不一定是平均分配),cluster 负责维护node<->slot<->value
; - Redis集群预分好16384个桶(Slot),当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) & 16384的值,决定将一个key放到哪个桶中;
Redis 集群的优势:
- 缓存永不宕机(有些夸张,哈哈):启动集群,永远让集群的一部分起作用。主节点失效了子节点能迅速改变角色成为主节点,整个集群的部分节点失败或者不可达的情况下能够继续处理命令;
- 迅速恢复数据:持久化数据,能在宕机后迅速解决数据丢失的问题;
- Redis可以使用所有机器的内存,变相扩展性能;
- 使Redis的计算能力通过简单地增加服务器得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长;
- Redis集群没有中心节点,不会因为某个节点成为整个集群的性能瓶颈;
- 异步处理数据,实现快速读写;
Redis 3.0以后,节点之间通过去中心化的方式提供了完整的sharding(数据分片)、replication(复制机制、Cluster具备感知准备的能力)、failover解决方案。
3. Redis Cluster 搭建
Redis3.0及以上版本实现,集群中至少应该有奇数个节点,所以至少有三个节点,官方推荐三主三从
的配置方式。Redis 3.x和Redis4.x 搭建集群是需要手动安装ruby
组件的,比较麻烦。
2018年十月 Redis 发布了稳定版本的 5.0 版本,推出了各种新特性,其中一点是放弃 Ruby的集群方式,改为 使用 C语言编写的redis-cli的方式,是集群的构建方式复杂度大大降低。Redis cluster tutorial 。
基于Redis-5.0.8版本,在三台机器上搭建6个节点的Redis集群:三主三从架构。
3.1 环境准备
关闭以前Redis主从复制和哨兵模式监控的所有服务,备注:如果以前没有安装过Redis服务,不用执行此步骤操作。
# ============= node1、node2和node3 =============
# 关闭哨兵服务SentinelServer
ps -ef|grep redis
kill -9 哨兵的进程ID
# 关闭Redis服务
redis-cli -h node1 -p 6379 SHUTDOWN
redis-cli -h node2 -p 6379 SHUTDOWN
redis-cli -h node3 -p 6379 SHUTDOWN
安装Redis编译环境:GCC和TCL。
yum -y install gcc-c++ tcl
3.2 上传和解压
将Redis-5.0.8软件安装包上传至 /export/software 目录,并解压与安装。
# node01, 上传安装包至/export/softwares
cd /export/software
rz
# 解压
cd /export/software
chmod u+x redis-5.0.8.tar.gz
tar -zxvf redis-5.0.8.tar.gz -C /export/servers/
3.3 编译安装
编译Redis 源码,并安装至【/export/servers/redis-5.0.8-bin】目录。
# node01, 编译、安装、创建软连接
# 进入源码目录
cd /export/servers/redis-5.0.8
# 编译
make
# 安装至指定目录
make PREFIX=/export/servers/redis-5.0.8-bin install
# 创建安装目录软连接
cd /export/servers
ln -s redis-5.0.8-bin redis
配置环境变量(如果以前安装过Redis,配置过环境变量,就不用配置)。
# 配置环境变量
vim /etc/profile
# ======================== 添加如下内容 ========================
# REDIS HOME
export REDIS_HOME=/export/servers/redis
export PATH=:$PATH:$REDIS_HOME/bin
# 执行生效
source /etc/profile
3.4 拷贝配置文件
从Redis-5.0.8源码目录下拷贝配置文件:redis.conf至Redis 安装目录。
# ====================== node01 上操作 ======================
# 拷贝配置文件
cd /export/servers/redis-5.0.8
cp redis.conf /export/servers/redis
3.5 修改配置文件
每台机器上启动2个Redis服务,一个主节点服务:7001,一个从节点服务:7002,如下图所示:
在Redis安装目录下创建7001和7002目录,分别存储Redis服务配置文件、日志及数据文件。
# 创建目录:7001和7002
cd /export/servers/redis
mkdir -p 7001 7002
拷贝配置文件:redis.conf至7001目录,并重命名为redis_7001.conf。
cd /export/servers/redis
cp redis.conf 7001/redis_7001.conf
编辑配置文件:redis_7001.conf,内容如下:
cd /export/servers/redis/7001
vim redis_7001.conf
## =========================== 修改内容说明如下 ===========================
## 69行,配置redis服务器接受链接的网卡
bind 0.0.0.0
## 88行,关闭保护模式
protected-mode no
## 92行,设置端口号
port 7001
## 136行,redis后台运行
daemonize yes
## 158行,Redis服务进程PID存储文件名称
pidfile /var/run/redis_7001.pid
## 171行,设置redis服务日志存储路径
logfile "/export/servers/redis-5.0.8-bin/7001/log/redis.log"
## 263行,设置redis持久化数据存储目录
dir /export/servers/redis-5.0.8-bin/7001/data/
## 699行,启动AOF方式持久化
appendonly yes
## 832行,启动Redis Cluster
cluster-enabled yes
## 840行,Redis服务配置保存文件名称
cluster-config-file nodes-7001.conf
## 847行,超时时间
cluster-node-timeout 15000
创建日志目录和数据目录:
mkdir -p /export/servers/redis/7001/log
mkdir -p /export/servers/redis/7001/data
配置7002端口号启动Redis服务,操作命令如下:
## 拷贝配置文件
cd /export/servers/redis
cp 7001/redis_7001.conf 7002/redis_7002.conf
## 修改配置文件:redis_7002.conf
cd /export/servers/redis/7002
vim redis_7002.conf
# 进入vim编辑之后,执行以下代码将7001全部替换成7002
:%s/7001/7002/g # 表示:%s/old/new/g g表示全部替换
# 创建目录
mkdir -p /export/servers/redis/7002/log
mkdir -p /export/servers/redis/7002/data
3.6 发送安装包
将node1上配置好的Redis安装包,发送至node2和node3,每台机器运行2个Redis服务,端口号分别为7001和7002,具体命令如下:
# 发送安装包
cd /export/servers
scp -r redis-5.0.8-bin root@node2:$PWD
scp -r redis-5.0.8-bin root@node3:$PWD
# 在node2和node3创建软连接
cd /export/servers
ln -s redis-5.0.8-bin redis
# 配置环境变量
vim /etc/profile
# ======================== 添加如下内容 ========================
# REDIS HOME
export REDIS_HOME=/export/servers/redis
export PATH=:$PATH:$REDIS_HOME/bin
# 执行生效
source /etc/profile
4. 启动Redis服务
在三台机器node01、node02和node03,分别启动6个Redis服务,命令如下:
# 启动7001端口Redis服务
/export/servers/redis/bin/redis-server /export/servers/redis/7001/redis_7001.conf
# 启动7002端口Redis服务
/export/servers/redis/bin/redis-server /export/servers/redis/7002/redis_7002.conf
Redis服务启动完成以后,查看如下:
4.1 启动集群
Redis5.x版本之后,通过redis-cli客户端命令来进行创建集群,注意:Redis对主机名解析不友好,使用IP地址。
# 任意选择一台机器执行如下命令,创建集群
/export/servers/redis/bin/redis-cli --cluster create 192.168.88.100:7001 192.168.88.101:7002 192.168.88.102:7001 192.168.88.100:7002 192.168.88.101:7001 192.168.88.102:7002 --cluster-replicas 1
启动集群日志信息如下:
>>> Performing hash slots allocation on 6 nodes...
## ====== 进行Slot槽范文划分 ======
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 – 16383
## ====== 主从分配,一主一从 ======
Adding replica 192.168.88.101:7001 to 192.168.88.100:7001
Adding replica 192.168.88.102:7002 to 192.168.88.101:7002
Adding replica 192.168.88.100:7002 to 192.168.88.102:7001
## ====== 主从节点配对信息 ======
M: 97e1d381d59561e075ac813e2df7fed00114687e 192.168.88.100:7001
slots:[0-5460] (5461 slots) master
M: 6e0353e92377a71d691a853152673a8774d11dc2 192.168.88.101:7002
slots:[5461-10922] (5462 slots) master
M: d9bf2ac8eec5637ed7ec50061419ff6b951eef0b 192.168.88.102:7001
slots:[10923-16383] (5461 slots) master
S: b679ac2df0df7509ffd3a1d3b460cb9e13f9dbfa 192.168.88.100:7002
replicates d9bf2ac8eec5637ed7ec50061419ff6b951eef0b
S: b8a76df88aafb19ce38232d0b4c1daf12370f257 192.168.88.101:7001
replicates 97e1d381d59561e075ac813e2df7fed00114687e
S: c038b9e271f5b5dba47d6ef81c4f49548a9f3698 192.168.88.102:7002
replicates 6e0353e92377a71d691a853152673a8774d11dc2
## ====== 是否同意上述划分,一般都是yes ======
Can I set the above configuration? (type 'yes' to accept): yes
## ====== 节点配置更新,进入集群,主从节点,高可用 ======
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 192.168.88.100:7001)
M: 97e1d381d59561e075ac813e2df7fed00114687e 192.168.88.100:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: c038b9e271f5b5dba47d6ef81c4f49548a9f3698 192.168.88.102:7002
slots: (0 slots) slave
replicates 6e0353e92377a71d691a853152673a8774d11dc2
S: b8a76df88aafb19ce38232d0b4c1daf12370f257 192.168.88.101:7001
slots: (0 slots) slave
replicates 97e1d381d59561e075ac813e2df7fed00114687e
S: b679ac2df0df7509ffd3a1d3b460cb9e13f9dbfa 192.168.88.100:7002
slots: (0 slots) slave
replicates d9bf2ac8eec5637ed7ec50061419ff6b951eef0b
M: 6e0353e92377a71d691a853152673a8774d11dc2 192.168.88.101:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: d9bf2ac8eec5637ed7ec50061419ff6b951eef0b 192.168.88.102:7001
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
4.2 测试集群
在任意一台机器,使用redis-cli客户端命令连接Redis服务:
redis-cli -c -p 7001
输入命令:cluster nodes
(查看集群信息)和info replication
(主从信息):
127.0.0.1:7001> cluster nodes
c038b9e271f5b5dba47d6ef81c4f49548a9f3698 192.168.88.102:7002@17002 slave 6e0353e92377a71d691a853152673a8774d11dc2 0 1598239340178 6 connected
b8a76df88aafb19ce38232d0b4c1daf12370f257 192.168.88.101:7001@17001 slave 97e1d381d59561e075ac813e2df7fed00114687e 0 1598239338161 5 connected
b679ac2df0df7509ffd3a1d3b460cb9e13f9dbfa 192.168.88.100:7002@17002 slave d9bf2ac8eec5637ed7ec50061419ff6b951eef0b 0 1598239337000 4 connected
6e0353e92377a71d691a853152673a8774d11dc2 192.168.88.101:7002@17002 master - 0 1598239338000 2 connected 5461-10922
d9bf2ac8eec5637ed7ec50061419ff6b951eef0b 192.168.88.102:7001@17001 master - 0 1598239339170 3 connected 10923-16383
97e1d381d59561e075ac813e2df7fed00114687e 192.168.88.100:7001@17001 myself,master - 0 1598239338000 1 connected 0-5460
127.0.0.1:7001> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.88.101,port=7001,state=online,offset=840,lag=1
master_replid:e669abc55325a3ea3f4273aeed92c3370568fb34
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:854
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:854
测试数据,设置Key值和查询Key的值。
# node1(192.168.88.153:7001),redis-cli登录
127.0.0.1:7001> KEYS *
(empty list or set)
127.0.0.1:7001> set k1 v1
-> Redirected to slot [12706] located at 192.168.88.102:7001 # 自动定向到node03上主服务
OK
192.168.88.102:7001> set k2 v2
-> -> Redirected to slot [449] located at 192.168.88.100:7001 # 自动定向到node02上主服务
OK
192.168.88.100:7001> set k3 v3
OK
192.168.88.100:7001> get k1
-> Redirected to slot [12706] located at 192.168.88.102:7001 # 自动定向到node03上主服务
"v1"
192.168.88.102:7001> get k2
-> Redirected to slot [449] located at 192.168.88.100:7001 # 自动定向到node03上主服务
"v2"
192.168.88.102:7001> get k3
"v3"
192.168.88.100:7001> KEYS *
1) "k3"
2) "k2"
4.3 启动关闭集群
编写脚本,方便启动和关闭Redis集群:redis-cluster-start.sh和redis-cluster-stop.sh。
- 进入Redis安装目录中bin目录,创建脚本文件
cd /export/servers/redis-5.0.8-bin/bin/
touch redis-cluster-start.sh
touch redis-cluster-stop.sh
# 给以执行权限
chmod u+x redis-cluster-start.sh
chmod u+x redis-cluster-stop.sh
- 启动集群:redis-cluster-start.sh
vim redis-cluster-start.sh
#!/bin/bash
REDIS_HOME=/export/server/redis
# Start Server
## node1
ssh node1 "${REDIS_HOME}/bin/redis-server /export/servers/redis/7001/redis_7001.conf"
ssh node1 "${REDIS_HOME}/bin/redis-server /export/servers/redis/7002/redis_7002.conf"
## node02
ssh node2 "${REDIS_HOME}/bin/redis-server /export/servers/redis/7001/redis_7001.conf"
ssh node2 "${REDIS_HOME}/bin/redis-server /export/servers/redis/7002/redis_7002.conf"
## node03
ssh node3 "${REDIS_HOME}/bin/redis-server /export/servers/redis/7001/redis_7001.conf"
ssh node3 "${REDIS_HOME}/bin/redis-server /export/servers/redis/7002/redis_7002.conf"
- 关闭集群:redis-cluster-stop.sh
vim redis-cluster-stop.sh
#!/bin/bash
REDIS_HOME=/export/servers/redis
# Stop Server
## node01
${REDIS_HOME}/bin/redis-cli -h node1 -p 7001 SHUTDOWN
${REDIS_HOME}/bin/redis-cli -h node1 -p 7002 SHUTDOWN
## node02
${REDIS_HOME}/bin/redis-cli -h node2 -p 7001 SHUTDOWN
${REDIS_HOME}/bin/redis-cli -h node2 -p 7002 SHUTDOWN
## node03
${REDIS_HOME}/bin/redis-cli -h node3 -p 7001 SHUTDOWN
${REDIS_HOME}/bin/redis-cli -h node3 -p 7002 SHUTDOWN
4.4 主从切换
测试Redis Cluster中主从服务切换,首先查看集群各个服务状态:
在node3上将7001端口Redis 服务关掉:SHUTDOWN
…/redis-cli -h node3 -p 7001 SHUTDOWN
[root@node3 server]# ps aux | grep redis
root 112830 0.1 0.3 161164 14084 ? Ssl 11:32 0:00 /export/server/redis/bin/redis-server 0.0.0.0:7002 [cluster]
root 112993 0.0 0.0 112812 972 pts/1 S+ 11:36 0:00 grep --color=auto redis
再次查看集群状态信息:
重新启动node03上7001端口Redis服务,查看集群状态信息
127.0.0.1:7001> cluster nodes
c038b9e271f5b5dba47d6ef81c4f49548a9f3698 192.168.88.102:7002@17002 slave 6e0353e92377a71d691a853152673a8774d11dc2 0 1598240006108 6 connected
6e0353e92377a71d691a853152673a8774d11dc2 192.168.88.101:7002@17002 master - 0 1598240004000 2 connected 5461-10922
d9bf2ac8eec5637ed7ec50061419ff6b951eef0b 192.168.88.102:7001@17001 master - 0 1598240007115 3 connected 10923-16383
97e1d381d59561e075ac813e2df7fed00114687e 192.168.88.100:7001@17001 myself,master - 0 1598240004000 1 connected 0-5460
b8a76df88aafb19ce38232d0b4c1daf12370f257 192.168.88.101:7001@17001 slave 97e1d381d59561e075ac813e2df7fed00114687e 0 1598240006000 5 connected
b679ac2df0df7509ffd3a1d3b460cb9e13f9dbfa 192.168.88.100:7002@17002 slave d9bf2ac8eec5637ed7ec50061419ff6b951eef0b 0 1598240004093 4 connected
127.0.0.1:7001> redis-cli –h node3 –p 7001 SHUTDOWN
127.0.0.1:7001> cluster nodes
c038b9e271f5b5dba47d6ef81c4f49548a9f3698 192.168.88.102:7002@17002 slave 6e0353e92377a71d691a853152673a8774d11dc2 0 1598240223000 6 connected
6e0353e92377a71d691a853152673a8774d11dc2 192.168.88.101:7002@17002 master - 0 1598240224000 2 connected 5461-10922
d9bf2ac8eec5637ed7ec50061419ff6b951eef0b 192.168.88.102:7001@17001 master,fail - 1598240171708 1598240170299 3 disconnected
97e1d381d59561e075ac813e2df7fed00114687e 192.168.88.100:7001@17001 myself,master - 0 1598240224000 1 connected 0-5460
b8a76df88aafb19ce38232d0b4c1daf12370f257 192.168.88.101:7001@17001 slave 97e1d381d59561e075ac813e2df7fed00114687e 0 1598240224734 5 connected
b679ac2df0df7509ffd3a1d3b460cb9e13f9dbfa 192.168.88.100:7002@17002 master - 0 1598240223000 7 connected 10923-16383
5. Redis Cluster 管理
redis-cli集群命令帮助:
[root@node01 ~]# redis-cli --cluster help
Cluster Manager Commands:
create host1:port1 ... hostN:portN
--cluster-replicas <arg>
check host:port
--cluster-search-multiple-owners
info host:port
fix host:port
--cluster-search-multiple-owners
reshard host:port
--cluster-from <arg>
--cluster-to <arg>
--cluster-slots <arg>
--cluster-yes
--cluster-timeout <arg>
--cluster-pipeline <arg>
--cluster-replace
rebalance host:port
--cluster-weight <node1=w1...nodeN=wN>
--cluster-use-empty-masters
--cluster-timeout <arg>
--cluster-simulate
--cluster-pipeline <arg>
--cluster-threshold <arg>
--cluster-replace
add-node new_host:new_port existing_host:existing_port
--cluster-slave
--cluster-master-id <arg>
del-node host:port node_id
call host:port command arg arg .. arg
set-timeout host:port milliseconds
import host:port
--cluster-from <arg>
--cluster-copy
--cluster-replace
help
For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
在实际项目中可能由于Redis Cluster中节点宕机或者增加新节点,需要操作命令管理,主要操作如下。
6. JavaAPI操作redis集群
连接Redis集群,需要使用JedisCluster来获取Redis连接。
实现步骤:
- 在com.erainm.redis包下创建一个新的类:RedisClusterTest
- 创建一个HashSet,用于保存集群中所有节点的机器名和端口号
- 创建JedisPoolConfig对象,用于配置Redis连接池配置
- 创建JedisCluster对象
- 使用JedisCluster对象设置一个key,然后获取key对应的值
package com.erainm.redis;
import org.junit.Before;
import org.junit.Test;
import org.testng.annotations.AfterTest;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
import java.io.IOException;
import java.util.HashSet;
public class RedisClusterTest {
private JedisPoolConfig jedisPoolConfig;
private JedisCluster jedisCluster;
@Before
public void beforeTest(){
// 1. 创建一个HashSet<HostAndPort>,用于保存集群中所有节点的机器名和端口号
HashSet<HostAndPort> hostAndPorts = new HashSet<>();
hostAndPorts.add(new HostAndPort("node1",7001));
hostAndPorts.add(new HostAndPort("node1",7002));
hostAndPorts.add(new HostAndPort("node2",7001));
hostAndPorts.add(new HostAndPort("node3",7002));
hostAndPorts.add(new HostAndPort("node3",7001));
hostAndPorts.add(new HostAndPort("node3",7002));
// 2. 创建JedisPoolConfig对象,用于配置Redis连接池配置
jedisPoolConfig = new JedisPoolConfig();
// 最大空闲连接
jedisPoolConfig.setMaxIdle(10);
// 最大等待时间
jedisPoolConfig.setMaxWaitMillis(3000);
// 最大连接数
jedisPoolConfig.setMaxTotal(50);
// 最小空闲连接
jedisPoolConfig.setMinIdle(5);
// 3. 创建JedisCluster对象
jedisCluster = new JedisCluster(hostAndPorts);
}
@Test
public void clusterOpTest(){
jedisCluster.set("pv","1");
System.out.println(jedisCluster.get("pv"));
}
@AfterTest
public void afterTest() {
try {
jedisCluster.close();
} catch (IOException e) {
System.out.println("关闭Cluster集群连接失败!");
e.printStackTrace();
}
}
}
下一篇: 菜鸟尝试超简单三层神经网络回归分析失败