redis5的集群搭建使用
配置修改
-
将下载好的redis解压完成后,复制六份redis.conf文件
-
对应修改每个文件的相关配置
port XXX 对应端口 bind 本机ip 如果是需要外网访问的话可以注释掉,然后创建集群的时候指定外网ip cluster-enabled yes 开启集群模式 daemonize yes 开启后台运行,不用每次都nohup cluster-node-timeout 15000 节点超时时间 cluster-config-file "nodes-XXX.conf" 集群内部配置文件
-
启动各个节点
-
./redis-server ../conf/XXX.conf
-
这是如果你的系统版本比较低的话,可能会提示你需要安装
GLIBC_2.14' not found
,这个安装需要十分谨慎,因为很有可能导致你的系统崩溃无法登录。尽可能的去找运维专业的帮你安装,如果没办法只能自己安装的话,首先一定要做好备份 ,在这里我个人比较推荐下面两种方案,相对安全。备份!备份!备份!- 通过rpm来安装别人已经编译好的模块
链接: https://pan.baidu.com/s/1KCsAdQE6uaJ0DQEewQxEnQ 提取码: sbui 通过这个链接下载好文件,解压后执行下面的代码
sbui 通过这个rpm -Uvh glibc-2.14.1-6.x86_64.rpm glibc-common-2.14.1-6.x86_64.rpm glibc-headers-2.14.1-6.x86_64.rpm glibc-devel-2.14.1-6.x86_64.rpm nscd-2.14.1-6.x86_64.rpm
安装完输入:
strings /lib64/libc.so.6 | grep GLIBC
-
如果出现上图标识代表安装成功
2. 第二种方法侵入更小 glibc编译安装
下载地址:http://ftp.gnu.org/gnu/glibc/
tar xvf glibc-2.17.tar.gz
cd glibc-2.17
mkdir build # 在glibc-2.17目录下建立build文件夹
cd ./build # 进入build目录
../configure --prefix=/opt/glibc-2.17 # 配置glibc并设置当前glibc-2.17安装目录
make -j4 && make install # 编译安装glibc-2.17库
编译安装完成之后不要去ln替换系统文件,那样会很危险,其实可以直接使用了
# 指定编译的glibc的库文件地址
LD_PRELOAD=/opt/glibc-2.17/lib/libc.so.6 /data/server/nginx/sbin/nginx -t
-
如果升级库出现问题,可以参照以下博客
https://blog.csdn.net/june_young_fan/article/details/89552941 https://blog.csdn.net/ai2000ai/article/details/78983461
-
当库升级好了之后再启动,然后再执行集群命令
-
./redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1
-
注意 这里的ip如果你需要外网访问的话,一定要注释配置文件中的bind,然后这里的ip必须是外网ip
-
执行会出现一个界面,会展示哪些是主,哪些是从,然后输入yes,等一会安装完成
-
-
通过
./redis-cli -h ip -p 端口 -c
进入客户端,然后执行cluster nodes会看到集群情况 -
-
-
至此安装完成
-
还有三个问题需要注意下
-
一个是如果需要设置密码,有两种方法
-
修改所有Redis集群中的redis.conf文件
-
masterauth 1234 requirepass 1234
-
注意:所有节点的密码都必须一致,masterauth也要加的。 需要重启节点
-
-
进入各个实例通过config set设置
-
[root@iZj6c7eeosj2t5vjw8rf4xZ redis_cluster]# redis-cli -c -p 7000 127.0.0.1:7000> config set masterauth 1234 OK 127.0.0.1:7000> config set requirepass 1234 OK 127.0.0.1:7000> auth 1234 OK 127.0.0.1:7000> config rewrite OK 127.0.0.1:7000> exit [root@iZj6c7eeosj2t5vjw8rf4xZ redis_cluster]# redis-cli -c -p 7000 -a 1234
-
-
-
使用jedis 连接redis集群的时候发现集群
getClusterNodes
的nodes节点中的地址有一个是内网地址,明明创建集群的时候是指定的外网ip的,重新创建集群,重启都是不起作用的。找了很长时间找到如下方法- 杀死节点(不是停止集群,否则不生效)
- 找到所有节点的nodes.conf文件,把内网地址改成你的ip
- 重启节点
-
使用jedis连接集群的时候第一次访问redis正常,第二次就报错,在多次测试和翻看源码发现,jediscluster内部已经释放了连接,我们不需要再手动释放
-
private T runWithRetries(final int slot, int attempts, boolean tryRandomNode, JedisRedirectionException redirect) { if (attempts <= 0) { throw new JedisClusterMaxAttemptsException("No more cluster attempts left."); } Jedis connection = null; try { //此处为空,走else if (redirect != null) { connection = this.connectionHandler.getConnectionFromNode(redirect.getTargetNode()); if (redirect instanceof JedisAskDataException) { // TODO: Pipeline asking with the original command to make it faster.... connection.asking(); } } else { //此处是false,走else if (tryRandomNode) { connection = connectionHandler.getConnection(); } else { //这里会从池中获取一个Jedis对象 connection = connectionHandler.getConnectionFromSlot(slot); } } //这里调用最开始实现的execute方法 return execute(connection); } catch (JedisNoReachableClusterNodeException jnrcne) { throw jnrcne; } catch (JedisConnectionException jce) { // release current connection before recursion releaseConnection(connection); connection = null; if (attempts <= 1) { //We need this because if node is not reachable anymore - we need to finally initiate slots //renewing, or we can stuck with cluster state without one node in opposite case. //But now if maxAttempts = [1 or 2] we will do it too often. //TODO make tracking of successful/unsuccessful operations for node - do renewing only //if there were no successful responses from this node last few seconds this.connectionHandler.renewSlotCache(); } return runWithRetries(slot, attempts - 1, tryRandomNode, redirect); } catch (JedisRedirectionException jre) { // if MOVED redirection occurred, if (jre instanceof JedisMovedDataException) { // it rebuilds cluster's slot cache recommended by Redis cluster specification this.connectionHandler.renewSlotCache(connection); } // release current connection before recursion releaseConnection(connection); connection = null; return runWithRetries(slot, attempts - 1, false, jre); } finally { //此处释放了连接 releaseConnection(connection); } }
-
进入releaseConnection 发现实际上是通过Jedis.close()关闭的,和我们用单节点时,是一样的关闭方式
-
private void releaseConnection(Jedis connection) { if (connection != null) { connection.close(); } }
-
-
总结
- 使用JedisCluster时,不需要手动释放连接
- 在调用的过程中,会自动释放连接
- 实际上是JedisCluster中通过JedisPool获取Jedis来执行命令
-
-
-
redis 集群官方中文教程
http://www.redis.cn/topics/cluster-tutorial.html