环境
IP | Redis version |
---|---|
10.240.30.100 | 6.0.8 |
10.240.30.101 | 6.0.8 |
10.240.30.102 | 6.0.8 |
Redis 集群必须3台机器,否则报错
配置文件
两台服务器修改配置文件允许集群。
cluster-enabled yes
为了安全我们设置每台redis 服务器的密码
requirepass xxxxxxxx
其他配置,如果不懂可以看这里 Redis配置文件详解
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
protected-mode yes
logfile "/home/db/redis.log"
启动服务器
启动服务器
./redis-server ../redis.conf
启动报错了,出现这样的意思是启动的时候会加载 rdb 文件,如果之前不是集群启动而生成了 rdb 文件,以集群方式启动就会报这样的错误,可以删除之前的 rdb 文件,然后配置正确的 rdb 路径。
You can't have keys in a DB different than DB 0 when in Cluster mode. Exiting.
正确配置
dbfilename dump.rdb
dir /home/db/
集群方式启动客户端,cluster-replicas 是集群 主从复制服务的 从的数量为1,但我没有就不要了,改为0。
./redis-cli -a 密码 --cluster create 10.240.30.100:6379 10.240.30.101:6379 10.240.30.102:6379 --cluster-replicas 0
启动成功,这里分享一个坑。
Redis集群TCP端口,每个Redis集群节点都需要打开两个TCP连接。用于为客户端提供服务的普通Redis TCP端口,例如6379,加上通过向数据端口添加10000获得的端口,因此示例中为16379。16379 端口用于集群总线,即使用二进制协议的节点到节点通信通道。节点使用集群总线进行故障检测,配置更新,故障转移授权等。客户端永远不应尝试与集群总线端口通信,但始终使用正常的Redis命令端口,请确保在防火墙中打开两个端口,否则Redis集群节点将无法通信。
我们往往只想着6379这个端口打开,原来16379也需要,这个就是等了半个多小时,集群一直在 Waiting for the cluster to join 的原因。
[root@localhost src]# ./redis-cli -a xxxxxx --cluster create 10.240.30.100:6379 10.240.30.101:6379 10.240.30.102:6379 --cluster-replicas 0
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 3 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
M: 31ad2f2e833072482f1af69318d56cbd4dd79e5f 10.240.30.100:6379
slots:[0-5460] (5461 slots) master
M: 1334c0969358ab231c6b0cc029d9ebcd84ca3b85 10.240.30.101:6379
slots:[5461-10922] (5462 slots) master
M: d6bea72d70b5416e8b2394e71d1cf2e63adfec01 10.240.30.102:6379
slots:[10923-16383] (5461 slots) master
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 10.240.30.100:6379)
M: 31ad2f2e833072482f1af69318d56cbd4dd79e5f 10.240.30.100:6379
slots:[0-5460] (5461 slots) master
M: d6bea72d70b5416e8b2394e71d1cf2e63adfec01 10.240.30.102:6379
slots:[10923-16383] (5461 slots) master
M: 1334c0969358ab231c6b0cc029d9ebcd84ca3b85 10.240.30.101:6379
slots:[5461-10922] (5462 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
登上任意一个客户端验证集群成功
127.0.0.1:6379> CLUSTER NODES
1334c0969358ab231c6b0cc029d9ebcd84ca3b85 10.240.30.101:6379@16379 master - 0 1601461538851 2 connected 5461-10922
31ad2f2e833072482f1af69318d56cbd4dd79e5f 10.240.30.100:6379@16379 master - 0 1601461539868 1 connected 0-5460
d6bea72d70b5416e8b2394e71d1cf2e63adfec01 10.240.30.102:6379@16379 myself,master - 0 1601461535000 3 connected 10923-16383
命令配置集群
检查集群状态
127.0.0.1:6379> CLUSTER NODES
a28899554fa1eaa949c1d4d0e8075c5137d92923 :6379@16379 myself,master - 0 0 0 connected
第二个命令把 102 加入集群
127.0.0.1:6379> CLUSTER MEET 10.240.30.102 6379
OK
spring boot redis 集群
普通的客户端是无法做到 key 的散列算法然后分配到某个集群库中,也就是我们常用的 redis-cli 不能帮我们做 key 的分发,如在A服务器上操作的命令set,只能在A服务器上get,这是我测试的结果,但是官网说可以,我也没办法的呢。所以我这里准备还实用 spring boot redis 测试。这里切记 集群模式下,只能使用redis 的第一个库 也就是 0。
maven 配置
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
配置文件
redis:
cluster:
nodes:
- 10.240.30.100:6379
- 10.240.30.101:6379
- 10.240.30.102:6379
max-redirects: 3
enable: true
password: xxxxxxx
database: 0
timeout: 0
lettuce:
pool:
max-active: 32
max-idle: 16
min-idle: 8
max-wait: 15000
配置类
package com.giant.cloud.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
/**
* @author big uncle
* @date 2020/11/17 11:57
* @module
**/
@Configuration
@Slf4j
@ConditionalOnExpression("${spring.redis.cluster.enable:false}")
public class RedisClusterConfig {
@Autowired
RedisProperties redisProperties;
/**
* GenericObjectPoolConfig 连接池配置
*/
@Bean
public GenericObjectPoolConfig genericObjectPoolConfig() {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle());
genericObjectPoolConfig.setMinIdle(redisProperties.getLettuce().getPool().getMinIdle());
genericObjectPoolConfig.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive());
genericObjectPoolConfig.setMaxWaitMillis(redisProperties.getLettuce().getPool().getMaxWait().toMillis());
return genericObjectPoolConfig;
}
@Bean
public LettuceConnectionFactory redisConnectionFactory(GenericObjectPoolConfig genericObjectPoolConfig) {
// 集群
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
redisClusterConfiguration.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());
redisClusterConfiguration.setPassword(redisProperties.getPassword());
// 配置池
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.commandTimeout(redisProperties.getTimeout())
.poolConfig(genericObjectPoolConfig)
.build();
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration,clientConfig);
log.debug("redis 集群启动");
return lettuceConnectionFactory;
}
}
测试代码
public void test4(){
for(int i=0;i<300;i++) {
String key = "32021420001:90000300009999:1000"+i+":1601198414621";
redisSdk.set(key,i+"");
}
System.out.println("结束");
}
100 服务器结果
127.0.0.1:6379> dbsize
(integer) 100
101 服务器结果
127.0.0.1:6379> dbsize
(integer) 108
102 服务器结果
127.0.0.1:6379> dbsize
(integer) 92
集群相关命令了解
Redis集群入门版
Redis集群进阶版