Redis学习05:Springboot集成Redis集群cluster(Lettuce版)

 

目标

  Redis的三种模式:主从、哨兵、集群;本随笔使用集群模式,配置6个redis服务节点,3主3从,并引入Springboot框架

相关概念:

  1- Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。集群中的每个节点负责处理一部分哈希槽。

 

第一步:安装Redis服务。

  因为项目有两台Linux服务器,打算在两台服务器上都安装redis服务,并分别开启6379,6380,6381三个端口,具体如下(以server_ip1:6379为例):

  1- 安装redis并启动。具体如何安装,这里不在赘述;如下表示安装成功

[root@izbp1aum9uyt0x56d3vepwz ~]# redis-cli  --version
redis-cli 3.2.9

 

  2-设置redis配置文件(redis.conf),为了方便配置文件管理,将./redis/redis.conf文件复制到/etc/redis/redis_6379.conf, 关键配置如下:

#绑定的主机端口(将bind 127.0.0.1注释掉,否则外网无法访问)
#bind 127.0.0.1

#集群内redis如果要相互可见,需要配置protected-mode=no
protected-mode no

#端口号
port 6379

#redis后台运行
daemonize yes

#进程文件
pidfile /var/run/redis-cluster/redis_6379.pid

#数据存放目录(根据实际目录来)
dir /usr/local/redis/data/redis_6379

#日志文件
logfile /usr/local/redis/log/redis_6379.log

#密码
requirepass xuegao1234

#开启集群模式,把注释#去掉
cluster-enabled yes

#集群的配置,配置文件首次启动自动生成
cluster-config-file /usr/local/redis/conf/node_6379.conf

  3- 6380和6381配置和上面一样,将7379替换成6380或6381即可;

  4- 配置结束后,依次启动6台redis;

[root@izbp10ebr6tsvo83iahgzdz redis]# /usr/local/bin/redis-server /etc/redis/redis_6379.conf
[root@izbp10ebr6tsvo83iahgzdz redis]# /usr/local/bin/redis-server /etc/redis/redis_6380.conf
[root@izbp10ebr6tsvo83iahgzdz redis]# /usr/local/bin/redis-server /etc/redis/redis_6379.conf
[root@izbp10ebr6tsvo83iahgzdz redis]# /usr/local/bin/redis-server /etc/redis/redis_6381.conf
[root@izbp1aum9uyt0x56d3vepwz redis]# ps -ef | grep redis
root     16949 15871  0 10:15 pts/0    00:00:00 grep --color=auto redis
root     28373     1  0 Jun18 ?        00:01:04 /usr/local/bin/redis-server *:6379 [cluster]
root     28383     1  0 Jun18 ?        00:01:04 /usr/local/bin/redis-server *:6380 [cluster]
root     28391     1  0 Jun18 ?        00:01:37 /usr/local/bin/redis-server *:6381 [cluster]

 

 

第二步:创建集群

  redis设置集群有多种方式,其中一种是使用redis插件 redis-tri.rb;redis-trib.rb是官方提供的Redis Cluster的管理工具,无需额外下载,默认位于源码包的src目录下,但因该工具是用ruby开发的,所以需要准备相关的依赖环境。

  1- 安装redis-trib.rb运行环境和依赖

##准备redis-trib.rb的运行环境
wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.gz
yum -y install zlib-devel
tar xvf ruby-2.5.1.tar.gz
cd ruby-2.5.1/
./configure -prefix=/usr/local/ruby
make
make install
cd /usr/local/ruby/
cp bin/ruby /usr/local/bin
cp bin/gem /usr/local/bin

 
#安装rubygem redis依赖
wget http://rubygems.org/downloads/redis-3.3.0.gem
gem install -l redis-3.3.0.gem

 

   2- 确认运行环境和依赖安装成功

[root@izbp1aum9uyt0x56d3vepwz redis]# cd /usr/local/redis/src/
[root@izbp1aum9uyt0x56d3vepwz src]# ./redis-trib.rb help
Usage: redis-trib <command> <options> <arguments ...>
.......
For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.

 

   3- 使用redis-trib.rb创建集群前的几个细节准备;

  3-1- 确认6个redis节点的IP和端口号(6379~6381以及16379~16381)都开放;包括服务器平台(我的事阿里云ECS)的安全组配置、服务器防火墙(关闭或允许端口开放)、redis.conf的配置文件(#bind 127.0.0.1); 否则创建节点时会报[ERR] Sorry, can't connect to node 47.111.164.6:6380异常

  3-2- redis.conf的配置文件 protected-mode no,确保redis节点相互之间可见

  3-3- 确认集群密码和redis密码一致

[root@izbp1aum9uyt0x56d3vepwz src]# vim /usr/local/ruby/lib/ruby/gems/2.5.0/gems/redis-3.3.0/lib/redis/client.rb
    DEFAULTS = {
      :url => lambda { ENV["REDIS_URL"] },
      :scheme => "redis",
      :host => "127.0.0.1",
      :port => 6379,
      :path => nil,
      :timeout => 5.0,
      :password => "xuegao1234",  ##密码设置和redis密码一致,同时6台redis密码保持一致
      :db => 0,
      :driver => nil,
      :id => nil,
      :tcp_keepalive => 0,
      :reconnect_attempts => 1,
      :inherit_socket => false
    }

 

  4- 创建集群(集群创建失败的情况以及如何处理,见文章附录)

[root@izbp1aum9uyt0x56d3vepwz src]# pwd
/usr/local/redis/src
[root@izbp1aum9uyt0x56d3vepwz src]# ./redis-trib.rb create --replicas 1 47.111.164.6:6379 47.111.164.6:6380 47.111.164.6:6381 120.26.55.92:6379 120.26.55.92:6380 120.26.55.92:6381
>>> Creating cluster
/usr/local/ruby/lib/ruby/gems/2.5.0/gems/redis-3.3.0/lib/redis/client.rb:459: warning: constant ::Fixnum is deprecated
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
......
Waiting for the cluster to join...
>>> Performing Cluster Check (using node 47.111.164.6:6379)
.....
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

 

   特别注意:如果创建集群失败,重现创建集群时,需要确认(1)redis中没有key-value;(2)需要对每一台redis重置集群信息,如下

127.0.0.1:6381> flushall
OK
127.0.0.1:6381> cluster reset
OK
127.0.0.1:6381> quit

 

 

第三步:Springboot集成Redis集群

  集成方式比较简单,使用Lettuce客户端继承。其中Jedis和Lettuce的区别:Jedis 是直连模式,在多个线程间共享一个 Jedis 实例时是线程不安全的,每个线程都去拿自己的 Jedis 实例,当连接数量增多时,物理连接成本就较高了。Lettuce的连接是基于Netty的,连接实例可以在多个线程间共享,不用担心并发线程的数量。通过异步的方式可以让我们更好地利用系统资源。

  1- POM文件(注意commons-pool2.jar)

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
     <!--lettuce.pool缓存连接池--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>

 

  2- application.properities

server.port=80

spring.redis.password=xuegao1234
spring.redis.cluster.nodes=47.111.164.6:6379,120.26.55.92:6379,47.111.164.6:6380,120.26.55.92:6380,47.111.164.6:6381,120.26.55.92:6381
spring.redis.cluster.max-redirects=3
spring.redis.lettuce.pool.max-idle=16
spring.redis.lettuce.pool.max-active=16
spring.redis.lettuce.pool.min-idle=16

  3-  RedisConfiguration.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration  //自动配置
public class RedisConfiguration {


    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        // 构建template
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(factory);
        // 设置key序列化方式为字符串
        template.setKeySerializer(new StringRedisSerializer());
        // 设置value序列化方式为JSON
        template.afterPropertiesSet();
        return template;
    }
}

 

  4- RedisController.java

@RestController
@RequestMapping("/api/redis/")
public class RedisController {

    @Autowired
    private RedisTemplate redisTemplate;

    //1- 字符串string
    @GetMapping("/string/set/{key}/{value}")
    public Object set(@PathVariable String key,@PathVariable String value){
        redisTemplate.opsForValue().set(key,value);
        return "success";
    }

    @GetMapping("/string/get/{key}")
    public Object get(@PathVariable String key){
        return  redisTemplate.opsForValue().get(key);
    }

}

 

 

附录(集成过程中碰到的问题)

  1-  redis-trib.rb创建集群时,报ERR Slot 0 is already busy 或 ERR Slot 5798 is already busy

问题
ERR Slot 0 is already busy (Redis::CommandError)
解决:错误提示是说:slot插槽被占用了、这是因为 搭建集群前时,以前redis的旧数据和配置信息没有清理干净。
对每个节点执行如下操作
127.0.0.1:6381> flushall
OK
127.0.0.1:6381> cluster reset
OK
127.0.0.1:6381> quit

 

  2-  redis-trib.rb创建集群时,一直处于等待中Waiting for the cluster to join

##一直等待中
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join................................................................................................................
..........................................................................................................................

解决:看到上图,这时候就不用再等了,果断Ctrl+C
关闭集群中的所有实例
于此同时删除掉每个节点文件下的 demp.rdb和nodes.conf文件
然后开放你redis实例端口号+10000的端口

 

  3- redis-trib.rb创建集群时,无法连接节点 ERR] Sorry, can't connect to node 47.111.164.6:6380

问题
[ERR] Sorry, can't connect to node 47.111.164.6:6380
解决
可能是因为端口没有开放或者集群密码错误,检查端口是否开放以及设施集群密码(见上文)

 

  4- Spring启动后,使用接口测试Redis,如果报跟Redis相关的错误,基本都是创建集群有问题。

END

posted on 2020-06-19 15:58  我不吃番茄  阅读(6593)  评论(0编辑  收藏  举报