Redis學習05:Springboot集成Redis集群cluster


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM