(转)Spring +Redis 集群集成
项目实现spring 和redis集群集成说明文档
Redis集群方案
选择redis集群方案有:redis3.0版本以上使用Redis Cluster, 3.0版本以下使用Redis +Sentinel 。
Redis +Sentinel 方案
参考: https://wizardforcel.gitbooks.io/redis-doc/content/doc/8.html
http://wiki.jikexueyuan.com/project/redis-guide/high-availability-b.html
优点
- 监控:监控主从是否正常运行
- 提醒:问题提醒
- 故障转移:主从节点自动转移
缺点
- Sentinel 存在单节点问题,需要对Sentinel进行搭建高可用服务
- 每个节点需要有Sentinel监控,包含master和slave节点
Redis Cluster方案
参考: https://wizardforcel.gitbooks.io/redis-doc/content/doc/8.html
http://wiki.jikexueyuan.com/project/redis-guide/high-availability-b.html
优点
- 有Sentinel的监控能力和自动切换主从功能
- 在扩展添加内存 比较容易
- 分片功能
缺点
- 其中一个主从节点服务停止,出现缓存不能使用,hash slot 无法使用,不是很强的数据一致性
- 存在数据一致性问题,主要体现在数据正在写入的主节点,此节点停止,出现数据写入此节点的数据丢失
- 添加节点需要分担已有节点的hash slot
Redis Cluster 环境搭建
Redis Cluster 安装
下载最新的redis稳定版本 :http://redis.io/ 3.07版本
-
安装 c编译工具:
yum install Development Tools -
执行编译安装
cd /root/redis-3.0.7make install -
建立单独文件夹:
mkdir -p /redis-cluster - 建立节点目录,
mkdir 9000 9001 9002 9003 9004 9005 -
拷贝配置文件和执行文件到redis-cluster中,
拷贝执行脚本:scp redis-cli redis-server redis-trib.rb /redis-cluster/bin拷贝配置文件:scp redis.conf /redis-cluster/etc -
配置一个节点的配置文件,以端口为9000开始节点开始为例,将redis.conf 拷贝到9000文件夹下,并修改一下名称:
[root@computer redis-cluster]# scp etc/redis.conf 9000 [root@computer 9000]# mv redis.conf redis-9000.conf - 修改redis-9000.conf的配置文件,修改点:端口,后台启动,持久化模式,绑定ip
daemonize yes --后台启动
port 9000 --端口
bind 192.168.85.15 绑定
dir /redis-cluster/9000 持久胡保文件目录
appendfsync everysec -保存数据策略,每秒保存写入数据
cluster-config-file nodes-9000.conf --节点文件 可以随意命名
cluster-enabled yes --支持=分布式
- 复制redis-9000.conf的文件到9001,9002,9003,9004,9005,按照9000的修改方式,这里我这放置一台机器上,只修改一个端口号即可,使用替换命名:
[root@computer 9000]# scp redis-9000.conf ../9001/
[root@computer 9000]# scp redis-9000.conf ../9002/
[root@computer 9000]# scp redis-9000.conf ../9003/
[root@computer 9000]# scp redis-9000.conf ../9004/
[root@computer 9000]# scp redis-9000.conf ../9005/
替换命名:
%s/9000/9001/g
- 启动各节点
[root@computer bin]# ./redis-server /redis-cluster/9000/redis-9000.conf
[root@computer bin]# ./redis-server /redis-cluster/9001/redis-9001.conf
[root@computer bin]# ./redis-server /redis-cluster/9002/redis-9001.conf
9002/
[root@computer bin]# ./redis-server /redis-cluster/9002/redis-9002.conf
[root@computer bin]# ./redis-server /redis-cluster/9003/redis-9003.conf
[root@computer bin]# ./redis-server /redis-cluster/9004/redis-9004.conf
[root@computer bin]# ./redis-server /redis-cluster/9005/redis-9005.conf
[root@computer bin]# ps -ef|grep redis
root 16514 1 0 23:25 ? 00:00:00 ./redis-server 192.168.85.15:9000 [cluster]
root 16518 1 0 23:25 ? 00:00:00 ./redis-server 192.168.85.15:9001 [cluster]
root 16522 1 0 23:25 ? 00:00:00 ./redis-server 192.168.85.15:9002 [cluster]
root 16526 1 0 23:25 ? 00:00:00 ./redis-server 192.168.85.15:9003 [cluster]
root 16530 1 0 23:25 ? 00:00:00 ./redis-server 192.168.85.15:9004 [cluster]
root 16534 1 0 23:25 ? 00:00:00 ./redis-server 192.168.85.15:9005 [cluster]
root 16538 2286 0 23:25 pts/0 00:00:00 grep --color=auto redis
-
各节节点关联成一个集群,每个主节点只有一个slave模式,需要安装Ruby 安装包,以及ruby 安装redis,此过程需要点时间
yum install ruby -y [root@computer bin]# gem install redis Fetching: redis-3.2.2.gem (100%) - 关联redis节点 变成一个集群
[root@computer bin]# ./redis-trib.rb create --replicas 1 192.168.85.15:9000 192.168.85.15:9001 192.168.85.15:9002 192.168.85.15:9003 192.168.85.15:9004 192.168.85.15:9005
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.85.15:9000
192.168.85.15:9001
192.168.85.15:9002
Adding replica 192.168.85.15:9003 to 192.168.85.15:9000
Adding replica 192.168.85.15:9004 to 192.168.85.15:9001
Adding replica 192.168.85.15:9005 to 192.168.85.15:9002
M: d922ee9e4d7dd0ccce63e6b4e7f04faed2d51181 192.168.85.15:9000
slots:0-5460 (5461 slots) master
M: 5c15d98e5f0316a8ec8309689ece938bdae4c200 192.168.85.15:9001
slots:5461-10922 (5462 slots) master
M: dd02b536abd6fe98b2fd025d45b87e38aa4c321b 192.168.85.15:9002
slots:10923-16383 (5461 slots) master
S: 52aee1c458ed407d4ae0121f6c101c46a640a13f 192.168.85.15:9003
replicates d922ee9e4d7dd0ccce63e6b4e7f04faed2d51181
S: 9c4c7cbccfc52b6b864fef38a8844fa4ed499969 192.168.85.15:9004
replicates 5c15d98e5f0316a8ec8309689ece938bdae4c200
S: ae0616372c550085a4035b1b720aef7af0e351a0 192.168.85.15:9005
replicates dd02b536abd6fe98b2fd025d45b87e38aa4c321b
验证集群
- 默认情况下所有的slave的节点不支持读,写操作,所以在所有的slave节点上执行readonly即可。
以下可以看出主节点的端口是:9000,9001,9002 slave节点的端口:9003,9004,9005
即在9003,9004,9005节点上执行readonly命令,不执行的话,在slave节点是不能读取数据的。
[root@computer log]# redis-cli -h 192.168.85.15 -p 9000 cluster nodes
d922ee9e4d7dd0ccce63e6b4e7f04faed2d51181 192.168.85.15:9000 myself,master - 0 0 1 connected 0-5460
dd02b536abd6fe98b2fd025d45b87e38aa4c321b 192.168.85.15:9002 master - 0 1458059365417 3 connected 10923-16383
ae0616372c550085a4035b1b720aef7af0e351a0 192.168.85.15:9005 slave dd02b536abd6fe98b2fd025d45b87e38aa4c321b 0 1458059364406 6 connected
9c4c7cbccfc52b6b864fef38a8844fa4ed499969 192.168.85.15:9004 slave 5c15d98e5f0316a8ec8309689ece938bdae4c200 0 1458059366427 5 connected
52aee1c458ed407d4ae0121f6c101c46a640a13f 192.168.85.15:9003 slave d922ee9e4d7dd0ccce63e6b4e7f04faed2d51181 0 1458059368449 4 connected
5c15d98e5f0316a8ec8309689ece938bdae4c200 192.168.85.15:9001 master - 0 1458059367436 2 connected 5461-10922
[root@computer log]# redis-cli -h 192.168.85.15 -p 9003
192.168.85.15:9003> readonly
OK
192.168.85.15:9003>
[root@computer log]# redis-cli -h 192.168.85.15 -p 9004
192.168.85.15:9004> readonly
OK
192.168.85.15:9004>
[root@computer log]# redis-cli -h 192.168.85.15 -p 9005
192.168.85.15:9005> readonly
OK
192.168.85.15:9005> keys *
(empty list or set)
192.168.85.15:9005>
[root@computer log]# redis-cli -h 192.168.85.15 -p 9003
192.168.85.15:9003> keys *
1) "hello"
192.168.85.15:9003> get hello
"word"
192.168.85.15:9003>
Spring和Redis Cluster集成
采用spring boot ,redis,maven集成一个demo实例。
- maven依赖的spring的jar,pom.xml如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Spring-RedisCluster</groupId>
<artifactId>com.yirui.nestoop.spring.redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>com.yirui.nestoop.spring.redis</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>
</project>
- 开始运行App.java,直接上代码,如是看
package com.yirui.nestoop.redis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.yirui.nestoop.redis.*")
@EnableConfigurationProperties
@EnableAutoConfiguration(exclude = HibernateJpaAutoConfiguration.class)
public class App {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(App.class);
System.out.println("redis cache 测试 start!");
application.run(args);
}
}
- 设置spring boot 集成tomcat的端口号,需要在src 下建立一个resource资源文件夹,文件名命名为:application.properties,内容是端口:9005
server.port=9005
- 连接Reis Cluster的配置加载的类:RedisConfig.java
package com.yirui.nestoop.redis.spring.conf;
import java.util.HashSet;
import java.util.Set;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@EnableCaching
public class RedisConfig {
@Bean
public JedisCluster jedisCluster() {
String hosts = "192.168.85.15:9000,192.168.85.15:9001,192.168.85.15:9002,192.168.85.15:9003,192.168.85.15:9004,192.168.85.15:9005";
Set<HostAndPort> nodes = new HashSet<HostAndPort>();
for (String host : hosts.split(",")) {
String[] hs = host.split(":");
nodes.add(new HostAndPort(hs[0], paseInt(hs[1])));
}
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(1000);
config.setMaxIdle(100);
config.setTestOnBorrow(true);
return new JedisCluster(nodes, config);
}
@Bean
public CacheManager cacheManager(JedisCluster jedisCluster){
return null;
}
public int paseInt(String number){
return Integer.parseInt(number);
}
}
- 创建一个Controller ,实现通过浏览器,向redis cluster集群插入数据,测试需要,只写了插入数据和查询数据的方法。代码:RedisController.java
package com.yirui.nestoop.redis.spring.controller;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.yirui.nestoop.redis.spring.service.RedisCacheService;
@RestController
public class RedisController {
@Resource
private RedisCacheService redisCacheService;
@RequestMapping(value = "add", method = RequestMethod.GET)
public int addCache(){
return redisCacheService.pushKeyAndValue("test", "test");
}
@RequestMapping(value = "query", method = RequestMethod.GET)
public String queryCacheNum(){
return redisCacheService.pullBykey("test");
}
}
-
创建controller访问的service
service接口
package com.yirui.nestoop.redis.spring.service; public interface RedisCacheService { public int pushKeyAndValue(String key,String value); public String pullBykey(String key); }
service 实现
package com.yirui.nestoop.redis.spring.service.impl;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.yirui.nestoop.redis.spring.conf.RedisConfig;
import com.yirui.nestoop.redis.spring.service.RedisCacheService;
import redis.clients.jedis.JedisCluster;
@Service(value="redisCacheService")
public class RedisCacheServiceImpl implements RedisCacheService{
@Resource
private RedisConfig redisConfig;
/**
*
* 加入缓存数据
*/
public int pushKeyAndValue(String key,String value){
JedisCluster jedisCluster =redisConfig.jedisCluster();
String ss=jedisCluster.set(key.getBytes(), value.getBytes());
System.out.println("set ss==="+ss);
return 1;
}
/**
* 查询数据
*/
public String pullBykey(String key) {
JedisCluster jedisCluster =redisConfig.jedisCluster();
byte[] byte_value=jedisCluster.get(key.getBytes());
if(byte_value !=null && byte_value.length>0){
System.out.println(String.format("查询缓存 key:%s,value:%s", key,new String(byte_value)));
return new String(byte_value);
}
return "null";
}
}
-
操作缓存:
插入缓存数据:http://localhost:9005/add
- 在测试时需要使用的的命令,停止一个redis 的主节点,查看slave 节点是否变为master节点。
查看所有节点情况:redis-cli -h ip -p port cluster nodes
[root@computer ~]# redis-cli -h 192.168.85.15 -p 9000 cluster nodes
52aee1c458ed407d4ae0121f6c101c46a640a13f 192.168.85.15:9003 master - 0 1458136357102 7 connected 0-5460
ae0616372c550085a4035b1b720aef7af0e351a0 192.168.85.15:9005 slave dd02b536abd6fe98b2fd025d45b87e38aa4c321b 0 1458136359453 6 connected
5c15d98e5f0316a8ec8309689ece938bdae4c200 192.168.85.15:9001 master,fail - 1458136116693 1458136113431 2 disconnected
9c4c7cbccfc52b6b864fef38a8844fa4ed499969 192.168.85.15:9004 master - 0 1458136358127 8 connected 5461-10922
d922ee9e4d7dd0ccce63e6b4e7f04faed2d51181 192.168.85.15:9000 myself,slave 52aee1c458ed407d4ae0121f6c101c46a640a13f 0 0 1 connected
dd02b536abd6fe98b2fd025d45b87e38aa4c321b 192.168.85.15:9002 master - 0 1458136359147 3 connected 10923-16383
关闭一个节点:redis-cli -h ip -p port shutdown

浙公网安备 33010602011771号