redis5的集群搭建使用

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 ,这个安装需要十分谨慎,因为很有可能导致你的系统崩溃无法登录。尽可能的去找运维专业的帮你安装,如果没办法只能自己安装的话,首先一定要做好备份 ,在这里我个人比较推荐下面两种方案,相对安全。备份!备份!备份!

      1. 通过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,等一会安装完成

    • img

    • 通过./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

猜你喜欢

转载自blog.csdn.net/wkfyynh/article/details/106380757