Redis Cluster集群主从方案(附Jedis Cluster教程)
2017-04-29 09:56
274 查看
Redis Cluster集群搭建以另一篇文章<<Redis集群搭建为主>>
http://blog.csdn.net/java20150326/article/details/70474248
Redis Cluster集群主从方案(附Jedis Cluster教程)
本文介绍一种通过Jedis和Cluster实现Redis集群(主从)的高可用方案,该方案需要使用Jedis2.8.0(推荐),Redis3.0及以上版本(强制).一、Redis集群介绍
Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.
Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令.
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么: 节点 A 包含 0 到 5500号哈希槽. 节点 B 包含5501 到 11000 号哈希槽. 节点 C 包含11001 到 16384号哈希槽.
二、Redis Cluster集群的优势:
自动分割数据到不同的节点上。整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
支持主从复制模型。(slave->master 选举,集群容错)
三、Redis Cluster集群的主从复制模型:
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,假如有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用.然而如果在集群创建的时候我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了。
四、Redis Cluster模型图
五、Redis的安装以及cluster配置
下载redis最新的安装包wget http://download.redis.io/releases/redis-3.0.7.tar.gz 解压
tar xzf redis-3.0.7.tar.gz
安装支持包tcl
yum install tcl 编译原文件
make
创建集群相关文件(方便管理)
mkdir cluster
cd cluster
mkdir 6379 6380 6381 6382 6383 6384
cluster下面每个目录中都创建一个redis.conf文件. 注意修改文件中的端口号:
port 6379 cluster-enabled yes cluster-config-file nodes_6379.conf cluster-node-timeout 5000 appendonly yes
把redis-server的可执行文件复制到cluster下面的各个目录, 然后打开6个shell终端,进入各个目录,启动每个实例, 命令如下:
./redis-server redis.conf
检查6个服务是否都启动了
搭建集群
./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
–replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
此时报错,发现缺少相应的ruby环境,如下安装相应环境:
yum install ruby
yum install rubygems
gem install redis
安装好环境后再次搭建集群
./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
检测集群节点相关信息
./redis-trib.rb check 127.0.0.1:6379
可以发现系统将前3个服务做了主节点,后3个服务作为了从节点,并且是相对应的。
进入某个节点验证
./redis-cli -c -h 127.0.0.1 -p 6379
可以发现程序根据key对16384取模的值为3488,根据hash槽的分布跳转到了对应的节点上。 可见集群环境正常运行
六、Jedis Cluster教程
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Jedis链接池配置,注意:Jedis版本建议升级到最新 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="100" /> <property name="maxIdle" value="20" /> <property name="minIdle" value="10" /> <property name="blockWhenExhausted" value="true"></property> <property name="maxWaitMillis" value="3000" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <property name="testWhileIdle" value="true" /> <property name="minEvictableIdleTimeMillis" value="60000" /> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <property name="numTestsPerEvictionRun" value="-1" /> </bean> <!-- JedisCluster --> <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster"> <constructor-arg index="0"> <set> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.1.111" /> <constructor-arg index="1" value="7111" type="int" /> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.1.112" /> <constructor-arg index="1" value="7112" type="int" /> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.1.113" /> <constructor-arg index="1" value="7113" type="int" /> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.1.114" /> <constructor-arg index="1" value="7114" type="int" /> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.1.115" /> <constructor-arg index="1" value="7115" type="int" /> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.1.116" /> <constructor-arg index="1" value="7116" type="int" /> </bean> </set> </constructor-arg> <constructor-arg index="1" value="2000" type="int"></constructor-arg> <constructor-arg index="2" value="100" type="int"></constructor-arg> <constructor-arg index="3" ref="jedisPoolConfig"></constructor-arg> </bean> </beans>或者
集群连接池(redis3.2.0)
import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.rules.Stopwatch; import redis.clients.jedis.BinaryJedisCluster; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisCluster; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Jedis Cluster 测试 * Created by yangxin on 2016/7/14. */ public class JedisClusterTest { private JedisCluster jc; @Before public void before() { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(20); config.setMaxIdle(2); Set<HostAndPort> clusters = new HashSet<HostAndPort>(); clusters.add(new HostAndPort("192.168.0.201",6379)); clusters.add(new HostAndPort("192.168.0.201",6380)); clusters.add(new HostAndPort("192.168.0.201",6381)); clusters.add(new HostAndPort("192.168.0.201",16379)); clusters.add(new HostAndPort("192.168.0.201",16380)); clusters.add(new HostAndPort("192.168.0.201",16381)); jc = new JedisCluster(clusters,,5000, 10,50,"yxue110",config); } @Test public void testCluster() { jc.set("name","yangxin"); jc.set("age","27"); String name = jc.get("name"); Assert.assertEquals(name,"yangxin"); String age = jc.get("age"); Assert.assertEquals(age,"27"); } // 无法操作多个key @Test public void testMGet() { List<String> values = jc.mget("name","age"); System.out.println(values); } @Test public void testBatchCluster() { // Jedis cluster不支持pipleline long begin = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { jc.set("key" + i, "value" + i); } long time = System.currentTimeMillis() - begin; System.out.println(time); } @After public void after() { try { jc.close(); } catch (IOException e) { e.printStackTrace(); } } }使用代码如下:
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import redis.clients.jedis.JedisCluster; public class RedisClusterSpringTest { private static final Log log = LogFactory.getLog(RedisClusterSpringTest.class); public static void main(String[] args) { try { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-context.xml"); context.start(); JedisCluster jedisCluster = (JedisCluster) context.getBean("jedisCluster"); int num = 1000; String key = "yingjun"; String value = ""; for (int i=1; i <= num; i++){ // 存数据 //jedisCluster.set(key+i, "yingjun"+i); //jedisCluster.setex(key+i, 60, "yingjun"+i); // 取数据 value = jedisCluster.get(key+i); log.info(key+i + "=" + value); // 删除数据 //jedisCluster.del(key+i); //value = jedisCluster.get(key+i); //log.info(key+i + "=" + value); } context.stop(); } catch (Exception e) { log.error("==>RedisSpringTest context start error:", e); System.exit(0); } finally { log.info("===>System.exit"); System.exit(0); } } }
package wusc.edu.demo.redis; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import redis.clients.jedis.JedisCluster; public class RedisClusterSpringTest { private static final Log log = LogFactory.getLog(RedisClusterSpringTest.class); public static void main(String[] args) { try { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-context.xml"); context.start(); JedisCluster jedisCluster = (JedisCluster) context.getBean("jedisCluster"); int num = 1000; String key = "yingjun"; String value = ""; for (int i=1; i <= num; i++){ // 存数据 //jedisCluster.set(key+i, "yingjun"+i); //jedisCluster.setex(key+i, 60, "yingjun"+i); // 取数据 value = jedisCluster.get(key+i); log.info(key+i + "=" + value); // 删除数据 //jedisCluster.del(key+i); //value = jedisCluster.get(key+i); //log.info(key+i + "=" + value); } context.stop(); } catch (Exception e) { log.error("==>RedisSpringTest context start error:", e); System.exit(0); } finally { log.info("===>System.exit"); System.exit(0); } } }
相关文章推荐
- mongodb架构mongodb分片集群与简易搭建方案---ttlsa教程系列之mongodb
- Redis集群方案一 Redis cluster
- Redis集群主从复制(一主两从)搭建配置教程【Windows环境】
- mongodb架构mongodb分片集群与简易搭建方案---ttlsa教程系列之mongodb(六)
- Redis详解之-集群方案:高性能(Codis3.2+Redis Cluster)(五)
- Redis详解之-集群方案:高性能(使用原生Redis Cluster)(四)
- 基于Redis Sentinel的Redis集群(主从Sharding)高可用方案(转)
- 基于Redis Sentinel主从切换以及Sharding分片的Redis集群高可用方案
- Redis Sentinel主从高可用方案(附Jedis Sentinel教程)
- Redis集群主从复制(一主两从)搭建配置教程【Windows环境】
- Ubuntu 16.04下Redis Cluster集群搭建(官方原始方案)
- Redis 集群方案- 主从切换测试
- 170103、Redis官方集群方案 Redis Cluster
- Redis Sentinel主从高可用方案(附Jedis Sentinel教程)
- 商品分类引入缓存-Redis主从复制-Redis Cluster集群
- Redis集群方案之Twemproxy+HAProxy+Keepalived+Sentinel+主从复制(待实践)
- 11.重新搭建一套主从复制+高可用+多master的redis cluster集群
- MySQL 系列教程(四)【秒杀七年经验 LowB工程师】 主从复制、备份恢复方案生产环境实战
- Redis--(linux安装redis3.2.9主从复制与集群的搭建--教程)
- mongodb架构mongodb分片集群与简易搭建方案---ttlsa教程系列之mongodb