首页 > 代码库 > Redis-3.2.4集群配置(RedisCluster+SpringBoot+Jedis)

Redis-3.2.4集群配置(RedisCluster+SpringBoot+Jedis)

此文由本人参考其他大神文档和资料,再结合当前环境做出的配置,有什么问题请联系我.



部署计划
部署6个redis节点,为3主3从。
端口IP地址
6379192.168.101.121
6379
192.168.101.199
6379
192.168.101.123
6379
192.168.101.127
6379
192.168.101.125
6379
192.168.101.126

目录结构
/data/redis
|-- bin
|   |-- redis-benchmark
|   |-- redis-check-aof
|   |-- redis-check-dump
|   |-- redis-cli
|   |-- redis-sentinel -> redis-server
|   `-- redis-server
|-- data
|   `-- 6379
|-- conf
|   `-- redis.conf
`-- log

编译安装
    (所有关于权限问题全部sudo,启动服务 sudo ./redis-server /data/redis/conf/redis.conf)

创建目录
    mkdir redis
    cd redis
下载解压安装包
    wget http://download.redis.io/releases/redis-3.2.4.tar.gz
    tar zxvf redis-3.2.4.tar.gz
    cd redis-3.2.4
    make
    make install PREFIX=/data/redis-3.2.4    //默认安装到/usr/local/bin目录下。这里指定安装目录data/redis-3.2.4
    ln -s /data/redis-3.2.4 /data/redis    //软连接
    mkdir /data/redis/conf    //创建目录结构
    mkdir /data/redis/log
    mkdir /data/redis/data
    cp /home/redis/redis/redis-3.2.4/redis.conf /data/redis/conf/    //copy配置文件
    vim /data/redis/conf/redis.conf

redis的配置
    protected-mode no    //关闭保护模式
    port 6379    //端口
    daemonize yes    //守护进程开启,默认服务从后台启动
    loglevel verbose    //日志级别
    logfile /data/redis/log/redis-6379.log    //日志文件位置
    ==redis持久化rdb,AOF相关==
    dbfilename dump.rdb    //redis持久化文件名称
    dir /data/redis/data/6379    //redis持久化文件路径,默认为当前路径
    appendonly yes    //开启AOF
    appendfilename "appendonly.aof"    //AOF文件名称
    no-appendfsync-on-rewrite yes    //子进程在做rewrite时,主进程不调用fsync(由内核默认调度)
    ==REPLICATION==
    slave-serve-stale-data yes    //当slave与master断开连接,slave继续提供服务
    slave-read-only yes
    repl-ping-slave-period 1    //slave ping master的时间间隔,单位为秒
    repl-timeout 10    //复制超时,单位为秒,须大于repl-ping-slave-period的值
     ==REDIS CLUSTER==
    cluster-enabled yes    //开启集群配置
    cluster-config-file nodes-6379.conf    //节点配置文件,这个文件是服务启动时自己配置创建的
    cluster-node-timeout 5000    //集群中各节点相互通讯时,允许"失联"的最大毫秒数,如果超过没向其它节点汇报成功,就认为该节点已挂。
    cluster-slave-validity-factor 0    //将该项设置为0,不管slave节点和master节点间失联多久都会一直尝试failover
    repl-ping-slave-period 1

其他5台机器配置
    相同操作目录可直接远程拷贝
    scp -r redis@192.168.101.126:/data/redis/data /data/redis/
    scp -r redis@192.168.101.126:/data/redis/conf /data/redis/
    scp -r redis@192.168.101.126:/data/redis/log /data/redis/

创建和启动redis cluster前的准备工作
    yum -y install ruby    //安装ruby    
    yum -y install rubygems    //安装rubygems    
    wget https://rubygems.org/downloads/redis-3.3.1.gem    //安装redis-3.3.1.gem
    gem install -l redis-3.3.1.gem
    cp redis-3.2.4/src/redis-trib.rb /data/redis/bin/    //redis-trib.rb是redis官方提供的redis cluster管理工具,使用ruby实现。
    ./redis-server /data/redis/conf/redis.conf    //启动6台服务
创建redis cluster
    redis-trib.rb create --replicas 1 192.168.101.121:6379 192.168.101.199:6379 192.168.101.123:6379 192.168.101.127:6379 192.168.101.125:6379 192.168.101.126:6379
    #redis-trib.rb的create子命令构建  
    #--replicas 则指定了为Redis Cluster中的每个Master节点配备几个Slave节点 

进入redis客户端
    redis-cli -c -p 6379    //-c进入集群模式
    info//查看信息
    cluster nodes//查看节点信息
    CLUSTER SLOTS//查看插槽信息

节点操作
    ./redis-trib.rb del-node 192.168.101.121:6379 ‘2ff326bc9084236ee6540d58d307893662ceff0b‘//删除节点
    ./redis-trib.rb add-node --slave --master-id 0ecc54ed34cc7e2e1ebca168ab4564b803992094 192.168.101.121:6379 192.168.101.125:6379//添加从节点,添加前需要删除已存在的node.conf,rdb,aof文件
    ./redis-trib.rb reshard 192.168.101.121:6379//为新节点分配slot
    ./redis-trib.rb check 192.168.101.121:6379    //检查集群运行状态,只要输入任意集群中节点即可,会自动检查所有相关节点。
    ./redis-trib.rb fix 192.168.101.121:6379    //修复集群(若node移除了,但是并没有移除node上面的slot,从而导致了slot总数没有达到16384,其实也就是slots分布不正确。所以在删除节点的时候一定要注意删除的是否是Master主节点)。

关于集群创建错误
集群创建的时候如果没有创建成功,那么需要删除集群节点配置文件,不然无法重新创建集群
sudo rm /data/redis-3.2.4/data/6379/nodes-6379.conf
技术分享

如果遇到Waiting for the cluster to join .......................................................
 >>> Sending CLUSTER MEET messages to join the cluster
解决方式
sudo ./redis-cli -c -p 6379    //进入客户端
CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中。
技术分享

Jedis的配置
config文件需要添加
github上有这一句,Jedis Cluster 会自动去发现集群中的节点,所以JedisClusterNodes只需要 add一个实例
// JedisCluster
 
@Bean
public JedisCluster JedisClusterFactory() {
LOG.info("JedisCluster创建!!");
LOG.info("redis地址:" + host + ":" + port);
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisClusterNodes.add(new HostAndPort(host, port));
JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes, jedisPoolConfig);
return jedisCluster;
}

dao
package com.unioncast.db.rdbms.core.dao.commonDBDao.impl;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
 
import com.unioncast.common.util.JsonUtil;
import com.unioncast.db.rdbms.core.dao.commonDBDao.RedisDao;
 
import redis.clients.jedis.JedisCluster;
 
@Repository("redisDao")
public class RedisDaoImpl implements RedisDao {
@Autowired
JedisCluster jedisCluster;
 
@Override
public <T> String addByKey(String key, T object) throws IOException {
String object2JsonString = JsonUtil.object2JsonString(object);
String set = jedisCluster.set(key, object2JsonString);
return set;
}
 
@Override
public <T> String add(T object) throws IOException {
String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
String object2JsonString = JsonUtil.object2JsonString(object);
jedisCluster.set(uuid, object2JsonString);
return uuid;
}
 
@Override
public Object getObject(String key) throws IOException {
String string = jedisCluster.get(key);
Object json2Object = JsonUtil.json2Object(string, Object.class);
return json2Object;
}
 
@Override
public <T> List<String> addList(List<T> list) throws IOException {
List<String> sum = new ArrayList<>(70);
String uuid = null;
String str = null;
for (int i = 0; i < list.size(); i++) {
uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
str = JsonUtil.object2JsonString(list.get(i));
jedisCluster.set(uuid, str);
sum.set(i, uuid);
}
return sum;
}
 
@Override
public <T> String addListKey(List<String> strList, List<T> list) throws IOException {
return null;
}
 
@Override
public <T> Long addListKey(Map<String, T> map) throws IOException {
Long sum = (long) 0;
String str = null;
Iterator<Entry<String, T>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, T> entry = (Entry<String, T>) iterator.next();
String key = entry.getKey();
T object = entry.getValue();
str = JsonUtil.object2JsonString(object);
jedisCluster.set(key, str);
sum = sum + 1;
}
 
return sum;
}
 
@Override
public Long deleteByKey(String key) throws IOException {
Long del = jedisCluster.del(key);
 
return del;
}
 
@Override
public Long batchDelete(List<String> strList) throws IOException {
Long sum = (long) 0;
Long del = (long) 0;
for (int i = 0; i < strList.size(); i++) {
del = jedisCluster.del(strList.get(i));
sum = sum + del;
}
 
return sum;
}
 
}

config
package com.unioncast.db.config;
 
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
 
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
 
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
 
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
 
@Configuration
@PropertySource(value = "classpath:/redis.properties")
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
// @Value("${spring.redis.host}")
// private String host;
// @Value("${spring.redis.port}")
// private int port;
// @Value("${spring.redis.timeout}")
// private int timeout;
private static final Logger LOG = LogManager.getLogger(RedisConfig.class);
 
@Value("${spring.redis.host}")
private String host;
 
@Value("${spring.redis.port}")
private int port;
 
@Value("${spring.redis.timeout}")
private int timeout;
 
@Value("${spring.redis.pool.max-idle}")
private int maxIdle;
 
@Value("${spring.redis.pool.max-wait}")
private long maxWaitMillis;
 
/*
* @Value("${spring.redis.password}") private String password;
*/
 
// Jedis连接池
@Bean
public JedisPool redisPoolFactory() {
LOG.info("JedisPool注入成功!!");
LOG.info("redis地址:" + host + ":" + port);
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
 
// JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port,
// timeout, password);
JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout);
return jedisPool;
}
// JedisCluster
 
@Bean
public JedisCluster JedisClusterFactory() {
LOG.info("JedisCluster创建!!");
LOG.info("redis地址:" + host + ":" + port);
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisClusterNodes.add(new HostAndPort(host, port));
JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes, jedisPoolConfig);
return jedisCluster;
}
 
@Bean
public KeyGenerator wiselyKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
 
@Bean
public JedisConnectionFactory redisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setTimeout(timeout); // 设置连接超时时间
return factory;
}
 
@Bean
public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
// Number of seconds before expiration. Defaults to unlimited (0)
cacheManager.setDefaultExpiration(10); // 设置key-value超时时间
return cacheManager;
}
 
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
setSerializer(template); // 设置序列化工具,这样ReportBean不需要实现Serializable接口
template.afterPropertiesSet();
return template;
}
 
private void setSerializer(StringRedisTemplate template) {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
}
}

















    

    

Redis-3.2.4集群配置(RedisCluster+SpringBoot+Jedis)