1、下载redis
2、安装redis
- 上传安装文件到服务器的/usr/local目录下
- 解压tar –zxvf redis-4.0.9.tar.gz
- 进入redis目录,cd redis-4.0.9安装:make && make install
3、redis集群配置
1)在/usr/local创建redis_cluster文件夹
2)进入到redis_cluster创建 9000、9001、9002、9003、9004、9005六个文件夹
3)在redis-4.0.9目录下找到redis.conf,复制redis.conf文件到9000、9001、9002、9003、9004、9005
4)修改9000、9001、9002、9003、9004、9005目录下的redis.conf配置(每个节点下的文件都需要修改,可以使用vi命令去修改,也可以在本地改好,在上传到服务器)
port 9000 //端口9000、9001、9002、9003、9004、9005
bind 192.168.145.177 //默认ip为192.168.145.177需要改为其他节点机器可访问的ip 否则创建集群时无法访问对应的端口,无法创建集群
daemonize yes //redis后台运行
pidfile /var/run/redis_9000.pid //pidfile文件对应9000、9001、9002、9003、9004、9005
cluster-enabled yes //开启集群 把注释#去掉
cluster-config-file nodes_7000.conf //集群的配置 9000、9001、9002、9003、9004、9005
cluster-node-timeout 15000 //请求超时 默认15秒,可自行设置
appendonly yes //aof日志开启 有需要就开启,它会每次写操作都记录一条日志
4、启动redis
在/usr/local目录下运行下面程序(redis-server这个命令在/usr/local/bin下面)
./bin/redis-server redis_cluster/9000/redis.conf
./bin/redis-server redis_cluster/9001/redis.conf
./bin/redis-server redis_cluster/9002/redis.conf
./bin/redis-server redis_cluster/9003/redis.conf
./bin/redis-server redis_cluster/9004/redis.conf
./bin/redis-server redis_cluster/9005/redis.conf
批量停止redis命令:pkill -9 redis
5、redis集群
redis运行环境需要ruby,因此需先按照ruby运行环境。
5.1、安装运行环境ruby
1)安装ruby
命令:yum -y install ruby ruby-devel rubygems rpm-build
2)安装rvm
命令:curl -L get.rvm.io | bash -s stable
第一次会失败,弹出需要公钥,然后
运行一下 gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
后面的这个串,每台机器都不一样,具体操作,看报错的信息。
再运行一次curl -L get.rvm.io | bash -s stable,即可安装rvm成功。
3)source环境,让rvm可用
source /usr/local/rvm/scripts/rvm
4)rvm list known查看可用的ruby
[ruby-]1.8.6[-p420]
[ruby-]1.8.7[-head] # security released on head
[ruby-]1.9.1[-p431]
[ruby-]1.9.2[-p330]
[ruby-]1.9.3[-p551]
[ruby-]2.0.0[-p648]
[ruby-]2.1[.10]
[ruby-]2.2[.7]
[ruby-]2.3[.4]
[ruby-]2.4[.1]
5)rvm install 2.4.1 选最新的安装
6)编译环境
gem install redis
7)安装rubygems
yum install -y rubygems
注意:如果yum用不了,需要先安装yum
https://jingyan.baidu.com/article/ed2a5d1f5a9fbe09f6be17ea.html
5.2、创建集群
命令:
/usr/local/redis-4.0.9/src/redis-trib.rb create --replicas 1 192.168.145.177:9000 192.168.145.177:9001 192.168.145.177:9002 192.168.145.177:9003 192.168.145.177:9004 192.168.145.177:9005
--replicas 1表示为集群的master节点创建1个副本。那么6个实例里,有三个master,有三个是slave。
提示Can I set the above configuration? (type 'yes' to accept):
输入yes
即可
5.2验证集群
在目录/usr/local下,输入
命令:./bin/redis-cli -h 192.168.145.177 -p 9000 -c
输入:cluster info查看集群信息
输入:cluster nodes查看集群节点
测试:set test neusoft
get test
5.3验证集群容灾情况
1)查看redis进程:ps –ef|grep redis
2)关闭一台主redis,杀掉9001进程:kill -9 12783
3)再次进入9000的redis实例,查看现有的redis集群节点情况。
./bin/redis-cli -h 192.168.145.177 -p 9000 –c
cluster nodes
可以看到9001已经fail了,现在少了一台主redis。
4)启动9001,检测9001
/usr/local/redis-4.0.9/src/redis-trib.rb check 192.168.145.177:9001
查看集群节点信息:
9001变成从redis,9004变为主redis
6、jedis开发
6.1、Maven依赖
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.2</version> </dependency>
6.2、编码
RedisCacheUtil(Redis缓存操作类)
import org.apache.log4j.Logger;
import org.codehaus.jackson.type.TypeReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Redis缓存操作类
*
* @author: alex
* @time: 2018-06-04
* @version: 1.0
*/
public class RedisCacheUtil {
private static Logger log = Logger.getLogger(RedisCacheUtil.class);
/**
* 存放String类型的值
*
* @param key key值
* @param value value值
* @throws Exception
*/
public void setString(String key, String value) throws Exception {
try {
RedisConfigUtil.getJedisCluster().set(key, value);
} catch (Exception e) {
log.error(e);
throw new Exception("存储String对象的值出错");
}
}
/**
* 获取String类型的值
*
* @param key key值
* @return 取得对应值
* @throws Exception
*/
public String getString(String key) throws Exception {
String value = null;
try {
value = RedisConfigUtil.getJedisCluster().get(key);
} catch (Exception e) {
log.error(e);
throw new Exception("获取String对象的值出错");
}
return value;
}
/**
* 设置对象
*
* @param key key值
* @param object 对象
* @throws Exception
*/
public void setObject(String key, Object object) throws Exception {
try {
String json = JsonConvertUtil.objectConvertJSON(object);
RedisConfigUtil.getJedisCluster().set(key, json);
} catch (Exception e) {
log.error(e);
throw new Exception("存储Object对象的值出错");
}
}
/**
* 获取对象
*
* @param key key值
* @param type 获取对象的类型
* @return 对象类型
* @throws Exception
*/
public Object getObject(String key, TypeReference<?> type) throws Exception {
Object obj = null;
try {
if (RedisConfigUtil.getJedisCluster().exists(key)) {
String json = RedisConfigUtil.getJedisCluster().get(key);
obj = JsonConvertUtil.jsonConvertObject(json, type);
}
} catch (Exception e) {
log.error(e);
throw new Exception("获取Object对象的值出错");
}
return obj;
}
/**
* 根据key、field取hash值,转换为对象
*
* @param key
* @param field
* @return
* @throws Exception
*/
public Object hGet(String key, String field, TypeReference<?> type) throws Exception {
try {
if (RedisConfigUtil.getJedisCluster().exists(key)) {
String json = RedisConfigUtil.getJedisCluster().hget(key, field);
return JsonConvertUtil.jsonConvertObject(json, type);
}
return null;
} catch (Exception e) {
log.error(e);
throw new Exception("获取Hash时出错");
}
}
/**
* 取key对应的所有hash,返回hashmap
*
* @param key
* @return
* @throws Exception
*/
public Map hGetAll(String key) throws Exception {
try {
if (RedisConfigUtil.getJedisCluster().exists(key)) {
return RedisConfigUtil.getJedisCluster().hgetAll(key);
}
return null;
} catch (Exception e) {
log.error(e);
throw new Exception("获取HashAll时出错");
}
}
/**
* 存放到缓存中,并设置失效时间
*
* @param key key值
* @param object 实体
* @param min 失效时间
* @throws Exception
*/
public void setObjectByExpire(String key, Object object, int min) throws Exception {
int seconds = min * 60;
try {
String json = JsonConvertUtil.objectConvertJSON(object);
RedisConfigUtil.getJedisCluster().set(key, json);
RedisConfigUtil.getJedisCluster().expire(key, seconds);
} catch (Exception e) {
log.error(e);
throw new Exception("存储Object对象的值并设置失效时间操作出错");
}
}
/**
* 获取缓存信息
*
* @param key key值
* @param type 实体类型
* @return 获取的对象
* @throws Exception
*/
public Object getExistObject(String key, TypeReference<?> type) throws Exception {
try {
if (RedisConfigUtil.getJedisCluster().exists(key)) {
String json = RedisConfigUtil.getJedisCluster().get(key);
return JsonConvertUtil.jsonConvertObject(json, type);
}
return null;
} catch (Exception e) {
log.error(e);
throw new Exception("获取Object对象的值并设置失效时间操作出错");
}
}
/**
* 判断缓存中是否存在此key
*
* @param key key值
* @return true存在,false不存在
* @throws Exception
*/
public boolean isExists(String key) throws Exception {
boolean flag = false;
try {
flag = RedisConfigUtil.getJedisCluster().exists(key);
} catch (Exception e) {
log.error(e);
throw new Exception("判断缓存中是否存在此key时出错");
}
return flag;
}
/**
* 根据key值删除缓存内容
*
* @param key key值
* @throws Exception
*/
public void deleteByKey(String key) throws Exception {
try {
if (RedisConfigUtil.getJedisCluster().exists(key)) {
RedisConfigUtil.getJedisCluster().del(key);
}
} catch (Exception e) {
log.error(e);
throw new Exception("删除此key时出错");
}
}
/**
* 将相同key值放入到链表中
*
* @param key key值
* @param object 对象
* @throws Exception
*/
public void setList(String key, Object object) throws Exception {
try {
String json = JsonConvertUtil.objectConvertJSON(object);
RedisConfigUtil.getJedisCluster().rpush(key, json);
} catch (Exception e) {
log.error(e);
throw new Exception("存储列表对象的值出错");
}
}
/**
* 获取列表对象
*
* @param key key值
* @param type 获取对象的类型
* @return 对象类型
* @throws Exception
*/
public List<Object> getList(String key, TypeReference<?> type) throws Exception {
try {
List<Object> list = new ArrayList<Object>();
Long size = RedisConfigUtil.getJedisCluster().llen(key);
List<String> bis = RedisConfigUtil.getJedisCluster().lrange(key, 0, size.intValue() - 1);
for (String bi : bis) {
Object obj = JsonConvertUtil.jsonConvertObject(bi, type);
list.add(obj);
}
return list;
} catch (Exception e) {
log.error(e);
throw new Exception("获取列表对象出错");
}
}
/**
* 保存对象到set集合中,去掉重复数据
*
* @param key key值
* @param object 对象
* @throws Exception
*/
public void setSadd(String key, Object object) throws Exception {
try {
String json = JsonConvertUtil.objectConvertJSON(object);
RedisConfigUtil.getJedisCluster().sadd(key, json);
} catch (Exception e) {
log.error(e);
throw new Exception("保存对象到set集合中出错");
}
}
/**
* 获取所有set集合中的对象
*
* @param key key值
* @param type 获取对象的类型
* @return 对象类型
* @throws Exception
*/
public List<Object> getSmembers(String key, TypeReference<?> type) throws Exception {
try {
List<Object> list = new ArrayList<Object>();
java.util.Set<String> bis = RedisConfigUtil.getJedisCluster().smembers(key);
for (String bi : bis) {
Object obj = JsonConvertUtil.jsonConvertObject(bi, type);
list.add(obj);
}
return list;
} catch (Exception e) {
log.error(e);
throw new Exception("获取所有set集合中的对象出错");
}
}
}
RedisConfigUtil(Redis配置类)
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
import java.util.LinkedHashSet;
import java.util.Set;
public class RedisConfigUtil {
private static JedisCluster jedisCluster = null;
private static Set<HostAndPort> nodes = null;
private static JedisPoolConfig poolConfig = new JedisPoolConfig();
static {
nodes = new LinkedHashSet<HostAndPort>();
nodes.add(new HostAndPort("192.168.145.177", 9000));
nodes.add(new HostAndPort("192.168.145.177", 9001));
nodes.add(new HostAndPort("192.168.145.177", 9002));
nodes.add(new HostAndPort("192.168.145.177", 9003));
nodes.add(new HostAndPort("192.168.145.177", 9004));
nodes.add(new HostAndPort("192.168.145.177", 9005));
// 最大连接数
poolConfig.setMaxTotal(1);
// 最大空闲数
poolConfig.setMaxIdle(1);
// 最大允许等待时间,如果超过这个时间还未获取到连接,则会报JedisException异常:
poolConfig.setMaxWaitMillis(60000);
}
public static JedisCluster getJedisCluster() {
if(jedisCluster == null) {
jedisCluster = new JedisCluster(nodes, poolConfig);
}
return jedisCluster;
}
}
json转换类JsonConvertUtil
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import java.io.IOException;
/**
* JSON转换
* @author: alex
* @time: 2018-06-04
* @version: 1.0
*/
public class JsonConvertUtil {
private static Logger log = Logger.getLogger(JsonConvertUtil.class);
/**
* 对象转换为JSON
* @param obj
* @return
*/
public static String objectConvertJSON(Object obj) {
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(obj);
} catch (IOException e) {
log.error("对象转换为JSON出错", e);
}
return null;
}
/**
* 对象转换为JSON
* @param obj
* @return
*/
public static String toJSON(Object obj) {
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(obj);
} catch (IOException e) {
log.error("对象转换为JSON出错", e);
}
return null;
}
/**
* json转换为对象
* @param json
* @param
* @return
*/
public static Object jsonConvertObject(String json,TypeReference<?> type){
Object obj = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, type);
} catch (IOException e) {
log.error("JSON转换为对象出错", e);
}
return obj;
}
/**
* json转换为对象
* @param json
* @param
* @return
*/
public static Object jsonConvertObject(String json,Class<?> clazz){
Object obj = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, clazz);
} catch (IOException e) {
log.error("JSON转换为对象出错", e);
}
return obj;
}
}
测试类:
import com.google.gson.reflect.TypeToken;
import org.codehaus.jackson.type.TypeReference;
public class RedisTest {
public static void main(String[] args) {
RedisCacheUtil redisUtil = new RedisCacheUtil();
try {
// redisUtil.setObject("test","alex");
// redisUtil.getObject("test", new TypeReference<String>() {});
redisUtil.setString("test", "hello world!");
System.out.println(redisUtil.getString("test"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
6.3、运行报错
No reachable node in cluster
原因:访问不了redis集群信息。
解决办法:
1)关闭防火墙:
systemctl stop firewalld
2)安装iptables:
yum install -y iptables
yum install iptables-services
3)编辑可访问端口:
vi /etc/sysconfig/iptables
增加的位置很重要,不能改变顺序
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 9000 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 9001 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 9002 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 9003 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 9004 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 9005 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
4)重启
systemctl restart iptables.service
or
service iptables restart
7、参考文档
https://www.cnblogs.com/yingchen/p/6763524.html
https://www.cnblogs.com/kangoroo/p/7657616.html
https://blog.csdn.net/appleyk/article/details/78325499
https://blog.csdn.net/wojiushifeng1992/article/details/729040