在linux环境下redis集群的搭建,需要准备的工作:
1.1. 此次直接讲解redis集群,单节点版暂且不讲;redis集群至少需要3个节点,因为容错机制要求超过半数节点认为某个节点挂了该节点才是挂了,所以2个节点无法构成集群;
1.2. 要保证集群的高可用,需要每个节点都有从节点,也就是备份节点,所以Redis集群至少需要6台服务器。但是我没有那么多服务器,所在这里搭建的是伪分布式集群,即一台服务器虚拟运行6个redis实例,修改端口号为(7001-7006);
1.3. 安装redis5.0.0;
1.4. 关闭防火墙,因为后续客户端访问redis服务器需要由有口权限,为了搭建方便,暂时关闭防火墙;在生产环境中,最好不要直接关闭防火墙,给相应的端口开通访问权限即可;
•关闭防火墙命令:systemctl stop firewalld
•启用防火墙命令:systemctl enable firewalld
•查看防火墙状态命令:systemctl start firewalld
•查看防火墙状态 :systemctl status firewalld
1.5. 安装ruby;
•安装ruby的命令:yum install ruby
2.1.在usr/local目录下新建redis-cluster目录,用于存放集群节点
进入local目录命令:cd /usr/local/
创建目录的命令:mkdir redis-cluster
2.2把redis目录下的bin目录下的所有文件复制到/usr/local/redis-cluster/redis01目录下
执行命令:cp -r redis/bin/ redis-cluster/redis01
2.3. 删除redis01目录下的快照文件dump.rdb和nodes.conf(有的话就删,没有的话就不用管),并且修改该目录下的redis.conf文件,具体修改两处地方:一是端口号修改为7001,二是开启集群创建模式,打开注释即可。分别如下所示:
•删除dump.rdb文件命令:rm -rf dump.rdb
•删除nodes.conf命令:rm -rf nodes.conf
•修改端口号:将redis.conf文件中port参数改为7001
开启集群:将cluster-enabled yes的注释打开
关于redis.conf中ip的配置问题,一开始我以为和单机点配置是一样的,ip需要配置服务器的ip,假设我的服务器ip是192.168.1.110,即redis.conf中ip需要配置为
bind 192.168.1.110,最后发现启动的时候还是客户端连接redis服务的时候,一直失败,具体原因我也忘记了;后来发现就是ip配置的有问题,所以在redis-cluster模式下,ip无需配置也可以;
再来这里说下为什么要删除nodes.conf这个文件,因为我在搭建过程的后期,在启动redis集群的时候经常会报错,报错的原因是redis.conf中配置的ip或者端口配置的有问题,然而配置文件中的配置项数据会存到nodes.conf中;所以如果有关于ip或者端口配置的有问题,需要重新配置的时候,需要删除nodes.conf文件,否则即使修改了redis.conf文件,集群启动仍然会有问题;
2.5将redis-cluster/redis01文件复制5份到redis-cluster目录下(redis02-redis06),创建6个redis实例,模拟Redis集群的6个节点。然后将其余5个文件下的redis.conf里面的端口号分别修改为7002-7006。
2.6启动redis节点:
•进入到redis01目录下:cd /usr/local/redis-cluster/redis01
•执行启动命令:./redis-server redis.conf
然后,挨个启动各个节点
2.7安装redis-3.0.0.gem
下载地址:https://rubygems.org/gems/redis/versions/3.0.0
安装命令:gem install redis-3.0.0.gem
2.8将redis解压文件的源代码里,即redis/src目录下的redis-cli文件拷贝到/usr/local/redis/下
然后执行集群启动命令:
./redis-cli --cluster create 192.168.1.110:7001 192.168.1.110:7002 192.168.1.110:7003 192.168.1.110:7004 192.168.1.110:7005 192.168.1.110:7006
这个地方是个坑,网上很多文章是用./redis-trib.rb create --replicas来启动,其实对于redis5.0.0版本,这个命令已经没法用了,但是具体是从哪个版本开始,我倒是忘记了;所以,对于不同的版本,redis集群版本启动命令是不一样的,这点大家要注意;
2.9启动成功后,进入redis01节点目录下,执行连接命令:./redis-cli -p 7001 -c ,测试下
springboot中的jedis版本为1.8.6,redis.clients版本为2.9.0
3.1.pom文件添加依赖:
org.springframework.boot
spring-boot-starter-data-redis
redis.clients
jedis
3.2application.yml文件配置:
redisCluster:
jedisClusterNode:
192.168.1.110:7001 192.168.1.110:7002 192.168.1.110:7003 192.168.1.110:7004 192.168.1.110:7005 192.168.1.110:7006
connectionTimeout: 20000
soTimeout: 3000
maxAttempts: 10
poolConfig:
maxIdle: 6
minIdle: 0
maxActive: 6
maxWait: -1
3.3创建一个redis配置对象,即RedisProperties.java
/**
* @Description:redis集群模式配置文件
* @Date: 2019/8/9 18:12
*/
@Component
@ConfigurationProperties(prefix = "redisCluster")
@Data
public class RedisProperties {
//集群节点的ip和端口
private String jedisClusterNode;
//集群连接超时时间
private int connectionTimeout;
//读取数据超时
private int soTimeout;
//最大尝试次数
private int maxAttempts;
//集群密码
private String password;
}
3.4创建JedisClusterConfig.java
/**
* @Description:redis集群配置类,用于初始化连接池和集群实例,集群实例用于操作redis数据库
* @Date: 2019/8/9 18:10
*/
@Configuration
public class JedisClusterConfig {
@Autowired
private GenericObjectPoolConfig poolConfig;
@Autowired
private RedisProperties redisProperties;
/*
*初始化连接池
*/
@Bean
@ConfigurationProperties(prefix = "redisCluster.poolConfig")
public GenericObjectPoolConfig getRedisConfig(){
GenericObjectPoolConfig poolConfig=new GenericObjectPoolConfig();
poolConfig.setMaxIdle(1000);
return poolConfig;
}
/*
* 该类在spring初始化时,会调用该方法,并将JedisCluster 集群实例注册到spring中
* 这里的JedisCluster是单例的,可以直接注入到其他类中使用
*/
@Bean
public JedisCluster getJedisCluster(){
String [] serverArray=redisProperties.getJedisClusterNode().split(Constants.COMMA);
Set nodes=new HashSet();
for(String ipPort:serverArray){
String[] ipPortPair=ipPort.split(Constants.COLON);
nodes.add(new HostAndPort(ipPortPair[0].trim(),Integer.valueOf(ipPortPair[1].trim())));
}
if(StringUtils.isEmpty(redisProperties.getPassword())){
return new JedisCluster(nodes,redisProperties.getConnectionTimeout(),
redisProperties.getSoTimeout(),redisProperties.getMaxAttempts(),poolConfig);
}else{
return new JedisCluster(nodes,redisProperties.getConnectionTimeout(),
redisProperties.getSoTimeout(),redisProperties.getMaxAttempts(),
redisProperties.getPassword(),poolConfig);
}
}
}
3.5创建RedisClusterTemplate.java,用于java端直接操作redis库
/**
* @Description:redis集群操作类,可通过集群实例直接操作redis库
* @Date: 2019/8/9 19:38
*/
@Component
@Slf4j
public class RedisClusterTemplate {
@Autowired
private JedisCluster jedisCluster;
/*
*发布
*/
public void publish(){
System.out.println(jedisCluster.publish("channel1","test"));
}
/*
*订阅
*/
public void psubscribe(){
jedisCluster.subscribe(new JedisPubSubListener(),"channel1");
}
/*
*设置key
*/
public void set(String key, String value) {
jedisCluster.set(key, value );
}
/*
*设置key
*/
public void setObject(String key, Object value) {
String objStr= JsonUtil.parseObject2Str(value);
jedisCluster.set(key, objStr );
}
/*
*设置key
*/
public void setObject(String key, Object value, int expiration) {
String objStr= JsonUtil.parseObject2Str(value);
jedisCluster.setex(key, expiration, objStr );
}
/*
*设置key及有效期
*/
public void set(String key, String value, int expiration) {
jedisCluster.setex(key, expiration, value);
}
/*
*取key对应value
*/
public String get(String key) {
return jedisCluster.get(key);
}
/*
*取key对应value
*/
public T getObject(String key, Class resultClass) {
String returnStr=jedisCluster.get(key);
if(StringUtils.isNotEmpty(returnStr)){
return JsonUtil.parseObj(returnStr,resultClass);
}else{
return null;
}
}
}
然后,在相应的业务模块,只直接通过注入RedisClusterTemplate 实例,即可直接操作redis数据,详细的操作方式在这里就不细写了。特别强调下,使用这种方式,RedisClusterTemplate 操作redis的数据的读取只能使用json字符串,不能直接使用java对象,所以要特别注意
1: https://blog.csdn.net/qq_42815754/article/details/82912130
2: https://www.cnblogs.com/lykxqhh/p/5690923.html
以上内容纯属原创,有些地方也是参考了网上不少教程;这篇文章纯属技术分享,不以任何盈利为目的,如果有侵权的地方,请私信我,我将会进行调整,谢谢!