(单机多节点为例)安装redis,将redis.conf文件复制几份并设置不同得监听端口(8001-8006),我在redis目录下新加了nodes-conf目录来存放我设置了六个不同端口的配置文件。
如果需要密码,配置文件中添加
masterauth 123456
requirepass 123456
requirepass:每个节点的独立密码,可以相同可以不同。
masterauth:从节点从主节点同步数据时使用的主节点的密码
使用脚本start.sh和stop.sh可以方便集群得启停操作,启动每个端口的节点
echo 'start redis cluster ...'
REDISBASE="/opt/app/redis-5.0.4"
cd $REDISBASE
./src/redis-server $REDISBASE/nodes-conf/cluster-node-8001.conf
./src/redis-server $REDISBASE/nodes-conf/cluster-node-8002.conf
./src/redis-server $REDISBASE/nodes-conf/cluster-node-8003.conf
./src/redis-server $REDISBASE/nodes-conf/cluster-node-8004.conf
./src/redis-server $REDISBASE/nodes-conf/cluster-node-8005.conf
./src/redis-server $REDISBASE/nodes-conf/cluster-node-8006.conf
echo 'start redis cluster finish !'
ps -ef|grep cluster
echo 'shutdown redis cluster...'
REDISBASE="/opt/app/redis-5.0.4"
$REDISBASE/src/redis-cli -p 8001 shutdown
$REDISBASE/src/redis-cli -p 8002 shutdown
$REDISBASE/src/redis-cli -p 8003 shutdown
$REDISBASE/src/redis-cli -p 8004 shutdown
$REDISBASE/src/redis-cli -p 8005 shutdown
$REDISBASE/src/redis-cli -p 8006 shutdown
echo 'shutdown redis cluster finish !'
ps -ef|grep cluster
在redis得5+版本之后,使用redis-trib.rb创建集群提示。
[root@localhost src]# ./redis-trib.rb create --replicas 1 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 127.0.0.1:8004 127.0.0.1:8005 127.0.0.1:8006
WARNING: redis-trib.rb is not longer available!
You should use redis-cli instead.
All commands and features belonging to redis-trib.rb have been moved
to redis-cli.
In order to use them you should call redis-cli with the --cluster
option followed by the subcommand name, arguments and options.
Use the following syntax:
redis-cli --cluster SUBCOMMAND [ARGUMENTS] [OPTIONS]
Example:
redis-cli --cluster create 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 127.0.0.1:8004 127.0.0.1:8005 127.0.0.1:8006 --cluster-replicas 1
To get help about all subcommands, type:
redis-cli --cluster help
(好像是redis在5.0已上得版本不再使用redis-trib.rb创建集群,这样也生下了ruby的安装和版本问题带来的麻烦)
redis-cli --cluster create 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 127.0.0.1:8004 127.0.0.1:8005 127.0.0.1:8006 --cluster-replicas 1
然后会输出一些提示。之后进入一个节点
输入cluster nodes会显示出当前集群得节点表示集群创建成功。
一般我们直接使用配置JedisCluster连接redis集群,这里使用工厂类。
首先我们写一个redis集群ip:port的配置文件
address1=172.28.18.74:8001
address2=172.28.18.74:8002
address3=172.28.18.74:8003
address4=172.28.18.74:8004
address5=172.28.18.74:8005
address6=172.28.18.74:8006
redis.pass=123456
配置jectPoolConfig和工厂类
/WEB-INF/config/redis-cluster.properties
工厂类JedisClusterFactory.java
(这个方法也是从网上看到的,原方法上使用的是无密码的jedisCluster构造方法,此处使用使用含有密码参数的构造方法)
package com.my.frame.redis.cluster;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
public class JedisClusterFactory implements FactoryBean, InitializingBean {
private Resource addressConfig;
private String addressKeyPrefix ;
private JedisCluster jedisCluster;
private Integer timeout;
private Integer maxRedirections;
private String password;
private GenericObjectPoolConfig genericObjectPoolConfig;
private Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$");
@Override
public JedisCluster getObject() throws Exception {
return jedisCluster;
}
@Override
public Class extends JedisCluster> getObjectType() {
return (this.jedisCluster != null ? this.jedisCluster.getClass() : JedisCluster.class);
}
@Override
public boolean isSingleton() {
return true;
}
private Set parseHostAndPort() throws Exception {
try {
Properties prop = new Properties();
prop.load(this.addressConfig.getInputStream());
Set haps = new HashSet();
for (Object key : prop.keySet()) {
if (!((String) key).startsWith(addressKeyPrefix)) {
continue;
}
String val = (String) prop.get(key);
boolean isIpPort = p.matcher(val).matches();
if (!isIpPort) {
throw new IllegalArgumentException("ip 或 port 不合法");
}
String[] ipAndPort = val.split(":");
HostAndPort hap = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
haps.add(hap);
}
return haps;
} catch (IllegalArgumentException ex) {
throw ex;
} catch (Exception ex) {
throw new Exception("解析 jedis 配置文件失败", ex);
}
}
@Override
public void afterPropertiesSet() throws Exception {
Set haps = this.parseHostAndPort();
if(genericObjectPoolConfig == null) {
genericObjectPoolConfig = new GenericObjectPoolConfig();
}
//jedisCluster = new JedisCluster(haps, timeout, maxRedirections,genericObjectPoolConfig);
/*public JedisCluster(Set jedisClusterNode, int timeout, int maxAttempts, GenericObjectPoolConfig poolConfig) {
super(jedisClusterNode, timeout, maxAttempts, poolConfig);
}*/
jedisCluster = new JedisCluster(haps, timeout,timeout,maxRedirections,password,genericObjectPoolConfig);
/*public JedisCluster(Set jedisClusterNode, int connectionTimeout, int soTimeout, int maxAttempts, String password, GenericObjectPoolConfig poolConfig) {
super(jedisClusterNode, connectionTimeout, soTimeout, maxAttempts, password, poolConfig);
}*/
}
public void setAddressConfig(Resource addressConfig) {
this.addressConfig = addressConfig;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public void setMaxRedirections(int maxRedirections) {
this.maxRedirections = maxRedirections;
}
public void setAddressKeyPrefix(String addressKeyPrefix) {
this.addressKeyPrefix = addressKeyPrefix;
}
public void setGenericObjectPoolConfig(GenericObjectPoolConfig genericObjectPoolConfig) {
this.genericObjectPoolConfig = genericObjectPoolConfig;
}
public void setPassword(String password) {
this.password = password;
}
}
通过注入jedisCluster我们就可以获得一个JedisCluster示例(工厂类注入实际获得工厂类产生的对象),我们可以封装一个接口对一些基础的方法进行封装,实际使用时通过spring注入我们的接口即可。
package com.my.frame.redis.cluster;
import redis.clients.jedis.JedisCluster;
import java.util.Map;
public class RedisCluster {
private JedisCluster jedis;
//Hash
public boolean set(String key, String field, String value) {
boolean b = false;
if(!"".equals(field)) {
jedis.hset(key, field, value);
b=true;
}else {
}
return b;
}
public String get(String key, String field) {
String value = "";
if(!"".equals(field)) {
value = jedis.hget(key, field);
}
return value;
}
public Map getAll(String key) {
Map stringStringMap = jedis.hgetAll(key);
return stringStringMap;
}
//清空
public void clear(String name){
jedis.del(name);
}
//移除
public void remove(String key,String field){
jedis.hdel(key, field);
}
//获取数量
public long len(String key){
return jedis.hlen(key.getBytes());
}
public void setJedis(JedisCluster jedis) {
this.jedis = jedis;
}
}