redis集群搭建
1.安装redis(windows版)
Redis官方是不支持windows的,但是 Microsoft Open Tech group 在 GitHub上开发了一个Win64的版本
项目地址:https://github.com/MSOpenTech/redis
进入后点击releases,选择合适的版本下载,本例子中下载了Redis-x64-3.2.100.zip
将压缩包解压6份放到自己建立的cluster-test文件夹下,并分别取名为7000,7001,7002,7003,7004,7005,本例子中cluster-test放在E盘下
因为要让集群正常运作至少需要三个主节点,因此我们创建6个节点,三个主节点三个从节点
2.配置redis
将每个redis文件夹下的redis.windows.conf文件对应位置做如下修改
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
注意端口号port需要和每个redis端口号对应
参数说明
cluster-enabled 选项用于打开实例的集群模式,
cluster-conf-file 选项则设定了保存节点配置文件的路径, 默认值为nodes.conf 。
nodes.conf 节点配置文件无须人为修改, 它由 Redis 集群在启动时创建, 并在有需要时自动进行更新。
3.创建启动脚本
在redis文件夹下创建7000.bat用于快速启动redis服务器
@echo off
redis-server.exe redis.windows.conf
@pause
其他redis同理
4.准备ruby环境
下载 Ruby 2.4.1-2 (x64)并安装 地址http://rubyinstaller.org/downloads/
5.安装RubyGems
下载rubygems-2.5.1.zip解压,运行里面的setup.rb
因为ruby自带的源很慢,这里切换源
在cmd下运行
gem sources –remove https://rubygems.org/删掉原来的源
gem sources -a https://gems.ruby-china.org/ 添加新的源
gem sources -l 查看现有的源
gem install redis 安装redis依赖
6.创建集群
启动6个redis服务器
从https://github.com/antirez/redis的 unstable
分支中取出最新的 Redis 源码,即点击branches后,点击unstable,点击Clone or download进行下载redis-unstable.zip
解压缩后在命令行中进入解压后的文件夹其中的src文件夹执行
redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
打印出配置信息,意思是现在的master是 7000 7001 7002这三台机,redis会对key 做 CRC16 校验和后分别存储这三台机上。没问题就输入 yes。
配置说明
7000端口 分配了 slots:0-5460 的意思是:
对key 做 CRC16 校验和后,值在 0-5460范围内都会存到这台机器里
例如 key=288 对应的CRC16校验和 为 4258,应该存在7000这台机里
PS:使用前应该对业务做梳理,根据系统中key的特点来调整各个机器的slots范围,
不然系统的key基本集中在一两台机器上集群的效果就不大了
参数说明
redis-trib.rb
create, 这表示我们希望创建一个新的集群。
选项 –replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
之后跟着的其他参数则是实例的地址列表, 我们希望程序使用这些地址所指示的实例来创建新集群。
创建了一个包含三个主节点和三个从节点的集群。
7.利用Jedis(纯java)使用集群
Redis Cluster 缺少客户端库实现。这里采用 Jedis Cluster 进行实现
7.1 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>com.yztc</groupId>
<artifactId>JedisImplForRedisCluster_java</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.3</version>
</dependency>
</dependencies>
</project>
7.2 测试类
import org.junit.Test;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.util.JedisClusterCRC16;
import java.util.HashSet;
import java.util.Set;
public class TestCluster {
@Test
public void cluster(){
String key = "1417";
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7000));
JedisCluster jc = new JedisCluster(jedisClusterNodes);
jc.setnx(key, "bar");
String value = jc.get(key);
System.out.println("key-"+key+" slot-"+ JedisClusterCRC16.getSlot(key)+" value-"+value);
String key2 = "288";
jc.setnx(key2, "bar2");
String value2 = jc.get(key);
System.out.println("key-"+key2+" slot-"+JedisClusterCRC16.getSlot(key2)+" value-"+value2);
}
}
Jedis Cluster 会自动去发现集群中的节点,所以JedisClusterNodes只需要 add一个实例
输出结果如下
key=288算出来的 CRC16校验和是 4258,根据配置 应该存在 7000这台机上
key=1417 算出来的 CRC16校验和是 13096,根据配置 应该存在 7002 这台机上
用redis客户端查看数据存到哪台机器上
在命令行进入任意一个redis的文件夹下输入redis-cli.exe -c -p 7000
8.spring+Jedis使用集群
8.1 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>com.yztc</groupId>
<artifactId>JredisImplForRedisCluster_spring</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<finalName>springmvc_redis</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>
4.12
</version>
</dependency>
<!--集成spring环境-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!--集成spring对redis的支持-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.8.3.RELEASE</version>
</dependency>
<!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<!--对原生api的支持-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!--需要用到jsp对应标签-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--日志包-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
</dependencies>
</project>
8.2 redis.properties
#redis config
redis.host=127.0.0.1
redis.port=7000
redis.timeout=100000
redis.maxIdle=300
redis.maxTotal=600
redis.timeBetweenEvictionRunsMillis=30000
redis.minEvictableIdleTimeMillis=30000
redis.testOnBorrow=true
8.3 applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:property-placeholder location="classpath:redis.properties"/>
<!--==================== redis配置 start ====================-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}" />
<property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="jedisClusterFactory" class="com.redis.cluster.util.JedisClusterFactory" >
<constructor-arg ref ="jedisPoolConfig"/>
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="${redis.port}"/>
</bean>
<bean id="redisProvide" class="com.redis.cluster.util.RedisProvide">
<constructor-arg ref ="jedisClusterFactory" />
</bean>
<!--==================== redis配置 end ====================-->
</beans>
8.4 JedisClusterFactory类
传入host 、port 和JedisPoolConfig 类
package com.redis.cluster.util;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
import java.util.HashSet;
import java.util.Set;
public class JedisClusterFactory {
private JedisCluster jedisCluster;
public JedisCluster getJedisCluster() {
return jedisCluster;
}
public JedisClusterFactory(JedisPoolConfig jedisPoolConfig, String host, int port){
Set<HostAndPort> jedisClusterNodes= new HashSet<HostAndPort>();
//Jedis Cluster will attempt to discover cluster nodes automatically
jedisClusterNodes.add(new HostAndPort(host,port));
jedisCluster=new JedisCluster(jedisClusterNodes,jedisPoolConfig);
}
}
8.5 CacheSecondLevel接口
package com.redis.cluster.util;
public interface CacheSecondLevel {
public Object get(String key);
public Object[] gets(String[] keys);
public void set(String key, Object obj);
public void delete(String key);
}
8.6 RedisProvide类
工具类,主要是封装些常用的操作
package com.redis.cluster.util;
import redis.clients.jedis.JedisCluster;
public class RedisProvide implements CacheSecondLevel{
private JedisCluster jedisCluster;
public RedisProvide(JedisClusterFactory jedisClusterFactory){
jedisCluster=jedisClusterFactory.getJedisCluster();
}
@Override
public Object get(String key){
return jedisCluster.get(key);
}
@Override
public Object[] gets(String[] keys) {
// TODO Auto-generated method stub
return null;
}
@Override
public void set(String key, Object obj) {
// TODO Auto-generated method stub
jedisCluster.set(key, obj.toString());
}
@Override
public void delete(String key) {
// TODO Auto-generated method stub
jedisCluster.del(key);
}
}
8.7 测试类
import com.redis.cluster.util.RedisProvide;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class TestCluster {
@Autowired
private RedisProvide provide;
@Test
public void test1() {
provide.set("student", "zhangsan");
provide.set("customer", "zhaosi");
System.out.println(provide.get("student"));
System.out.println(provide.get("customer"));
}
}
输出结果
用redis客户端查看数据存到哪台机器上