170103、Redis官方集群方案 Redis Cluster
前面我们谈了Redis Sharding多服务器集群技术,Redis Sharding是客户端Sharding技术,对于服务端来说,各个Redis服务器彼此是相互独立的,这对于服务端根据需要灵活部署Redis非常轻便,Redis Sharding具有很好的灵活性、可伸缩性,是一种轻量级集群技术。
本篇,介绍另外一种多Redis服务器集群技术,即Redis Cluster。Redis Cluster是一种服务器Sharding技术,3.0版本开始正式提供。
Redis Cluster中,Sharding采用slot(槽)的概念,一共分成16384个槽,这有点儿类似前面讲的pre sharding思路。对于每个进入Redis的键值对,根据key进行散列,分配到这16384个slot中的某一个中。使用的hash算法也比较简单,就是CRC16后16384取模。
Redis集群中的每个node(节点)负责分摊这16384个slot中的一部分,也就是说,每个slot都对应一个node负责处理。当动态添加或减少node节点时,需要将16384个槽做个再分配,槽中的键值也要迁移。当然,这一过程,在目前实现中,还处于半自动状态,需要人工介入。
Redis集群,要保证16384个槽对应的node都正常工作,如果某个node发生故障,那它负责的slots也就失效,整个集群将不能工作。
为了增加集群的可访问性,官方推荐的方案是将node配置成主从结构,即一个master主节点,挂n个slave从节点。这时,如果主节点失效,Redis Cluster会根据选举算法从slave节点中选择一个上升为主节点,整个集群继续对外提供服务。这非常类似前篇文章提到的Redis Sharding场景下服务器节点通过Sentinel监控架构成主从结构,只是Redis Cluster本身提供了故障转移容错的能力。
Redis Cluster的新节点识别能力、故障判断及故障转移能力是通过集群中的每个node都在和其它nodes进行通信,这被称为集群总线(cluster bus)。它们使用特殊的端口号,即对外服务端口号加10000。例如如果某个node的端口号是6379,那么它与其它nodes通信的端口号是16379。nodes之间的通信采用特殊的二进制协议。
对客户端来说,整个cluster被看做是一个整体,客户端可以连接任意一个node进行操作,就像操作单一Redis实例一样,当客户端操作的key没有分配到该node上时,Redis会返回转向指令,指向正确的node,这有点儿像浏览器页面的302 redirect跳转。
Redis Cluster是Redis 3.0以后才正式推出,时间较晚,目前能证明在大规模生产环境下成功的案例还不是很多,需要时间检验。
集群搭建R
下面,我们就实际操作建立一个Redis Cluster。我们将建立3个node,每个node架构成一主一从,故总共有6个redis实例,端口号从7000-7005。
Cluster下的Redis实例,和普通Redis实例一样,只是处于cluster模式方式下运行。
实操步骤如下:
1. 以3.0.5为例,建立cluster目录,其下再建6个子目录代表6实例环境
mkdir cluster
mkdir 7000 7001 7002 7003 7004 7005
2. 将redis.conf模板分别copy到上面6子目录中,并做如下修改,以7000为例:
修改如下信息
daemonize yes
pidfile /var/run/redis-7000.pid
port 7000
logfile "/var/log/redis-7000.log"
注释掉如下信息, 不需要RDB持久化
#save 900 1
#save 300 10
#save 60 10000
修改如下信息
appendonly yes
appendfilename "appendonly-7000.aof"
取消如下注释,让Redis在集群模式下运行
cluster-enabled yes 启动cluster模式
cluster-config-file nodes-7000.conf 集群信息文件名,由redis自己维护
cluster-node-timeout 15000 15秒中联系不到对方node,即认为对方有故障可能
3. 在各个目录下执行 redis-server redis.conf 启动redis实例
这时,这几个实例都是各自是一个集群状态在运行,并没有形成一个整体集群态,我们需要Redis提供的基于ruby开发的工具进行人工设置。
4.安装ruby环境
yum install ruby ruby-devel rubygems
5.安装Redis的ruby依赖接口
gem install redis
6.利用脚本工具建立集群
./redis-trib.rb create --replicas 1 192.168.1.142:7000 192.168.1.142:7001 192.168.1.142:7002 192.168.1.142:7003 192.168.1.142:7004 192.168.1.142:7005
该脚本自动执行节点分配方案,将前3个redis实例作为主节点,后三个作为从节点,如图:
按提示敲入"yes",执行方案,将6个节点组成集群,3主3从。
执行redis-cli -p 7000 info Replication 命令,观察7000这个节点,发现其复制配置信息已配置成主节点,并有一个从节点7003
再执行redis-cli -p 7003 info Replication发现,该节点已设置成从节点。这些主从设置,都是在创建集群时自动完成的。
至此,3主3从的Redis集群建立起来了。接下来我们做个故障转移试验,将主节点7001 shutdown掉,看看发生什么?
我们看到,从节点7004会上升为主节点继续提供集群服务。那又重新启动7001节点呢?
我们发现7001节点已经成为从节点,不会成为取代7004成为主节点。那如果将主节点7001和从节点7004都shutdown掉呢?
这时,整个cluster是拒绝提供服务的。因为原来7001分配的slot现在无节点接管,需要人工介入重新分配slots。
增删集群节点R
下面我们操作下,如果修改集群节点架构:
删除一个从节点。注意,如果删除主节点,其负责的slots必须为空。
./redis-trib.rb del-node 192.168.1.142:7000 ee2fc0ea6e630f54e3b811caedf8896b26a99cba
将7001节点的slot都转移到7000
./redis-trib.rb reshard 192.168.1.142:7000
按提示操作即可。
加一个节点。注意新添加的节点还没有分配slot,用reshard给它分配一定比例的slots
./redis-trib.rb add-node 192.168.1.142:7001 192.168.1.142:7000
给指定一个主节点添加一个从节点。
./redis-trib.rb add-node --slave --master-id f4d17d56a9dda1a102da7cd799192beff7cba69e 192.168.1.142:7004 192.168.1.142:7000
注意如果此redis实例参与过集群,需先cluster reset 清除重置一下。
Jedis客户端访问R
上面介绍了服务端Redis Cluster搭建过程。下面来看看客户端如何使用?
Java语言的客户端驱动Jedis是支持Redis Cluster的。我们具体实操下:
1. pom.xml中配置jedis jar包
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version> <!-- 最近升级了 -->
</dependency>
2. spring配置文件中配置JedisCluster
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="4096"/>
<property name="maxIdle" value="200"/>
<property name="maxWaitMillis" value="3000"/>
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="true" />
</bean>
<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.142" />
<constructor-arg index="1" value="7002" />
</bean>
</set>
</constructor-arg>
<constructor-arg index="1" value="2000" type="int"/>
<constructor-arg index="2" value="2" type="int"/>
<constructor-arg index="3" ref="poolConfig"/>
</bean>
3.编写测试代码
@Test
public void basicOpTestForCluster(){
long begin = System.currentTimeMillis();
for(int i=0;i<10000; i++){
jedis.set("person." + i + ".name", "frank");
jedis.set("person." + i + ".city", "beijing");
String name = jedis.get("person." + i + ".name");
String city = jedis.get("person." + i + ".city");
assertEquals("frank",name);
assertEquals("beijing",city);
jedis.del("person." + i + ".name");
Boolean result = jedis.exists("person." + i + ".name");
assertEquals(false,result);
result = jedis.exists("person." + i + ".city");
assertEquals(true,result);
}
long end = System.currentTimeMillis();
System.out.println("total time: " + (end-begin)/1000);
}
170103、Redis官方集群方案 Redis Cluster的更多相关文章
- Redis缓存集群方案
由于单台Redis服务器的内存管理能力有限,使用过大内存的Redis又会使得服务器的性能急剧下降,一旦服务器发生故障将会影响更大范围业务,而Redis 3.0 beta1支持的集群功能还不适合生产环境 ...
- docker1.12 安装redis第三方集群方案 codis
docker1.12 安装redis第三方集群方案 codis
- Redis的集群方案之Sentinel(哨兵模式)(待实践)
哨兵模式是主从切换的一种方案,但是可以借助此方案实现集群,达到高可用. 先收集教程,待实践. 参考: https://redis.io/topics/sentinel(官方文档) http://ife ...
- Redis集群方案应该怎么做
方案1:Redis官方集群方案 Redis Cluster Redis Cluster是一种服务器sharding分片技术.Redis Cluster集群如何搭建请参考我的另一篇博文:http://w ...
- Redis集群方案<转>
为什么集群? 通常,为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取.Redis是一个很好的Cache工具.大型网站应用,热点数据量往往巨大,几十G上百G是很正常的事儿,在 ...
- Redis集群方案(来自网络)
参考: https://www.zhihu.com/question/21419897 http://www.cnblogs.com/haoxinyue/p/redis.html 为什么集群? 通常, ...
- redis集群与分片(1)-redis服务器集群、客户端分片
下面是来自知乎大神的一段说明,个人觉得非常清晰,就收藏了. 为什么集群? 通常,为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取.Redis是一个很好的Cache工具.大型 ...
- Redis集群方案及实现
在作出Redis群集解决方案,他跑了小半个.行表现得非常稳定在几乎相同的经历与大家分享,我写在前面的文章数据在线服务的一些探索经验,能够做为背景阅读 应用 我们的Redis集群主要承担了下面服务:1. ...
- Redis集群方案
Redis集群方案 前段时间搞了搞Redis集群,想用做推荐系统的线上存储,说来挺有趣,这边基础架构不太完善,因此需要我们做推荐系统的自己来搭这个存储环境,就自己折腾了折腾.公司所给机器的单机性能其实 ...
随机推荐
- webdriverAPI-Java
1.1 下载selenium2.0的lib包 http://code.google.com/p/selenium/downloads/list 官方UserGuide:http://seleniu ...
- PAT (Basic Level) Practise 1045 快速排序(离散化+主席树区间内的区间求和)
1045. 快速排序(25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CAO, Peng 著名的快速排序算法里有一个经典的划分 ...
- div span
无牵无挂,不带任何样式,因此经常使用div完成整体样式的构建,span完成细微样式的构建. div为块级元素,span为行内元素. 使用div完成显示区域的居中.左右浮动等,完成整体的样式布局,然后在 ...
- ASP.Net一键自动化更新代码、编译、合并dll、压缩js、css、混淆dll、zip打包、发布到测试环境的bat批处理
不废话,直接代码: D: cd D:\src\testproj\PrecompiledWeb svn revert ../ -R svn update .. rmdir BS /S /Q C:\Win ...
- 给定一个double类型的数组arr,其中的元素可正可负可0,返回子数组累乘的最大乘积。例如arr=[-2.5,4,0,3,0.5,8,-1],子数组[3,0.5,8]累乘可以获得最大的乘积12,所以返回12。
分析,是一个dp的题目, 设f[i]表示以i为结尾的最大值,g[i]表示以i结尾的最小值,那么 f[i+1] = max{f[i]*arr[i+1], g[i]*arr[i+1],arr[i+1]} ...
- iOS 模拟器变的很多的问题
运行一下命令 xcrun simctl list devices | grep -v '^[-=]' | cut -d "(" -f2 | cut -d ")" ...
- 用mac的terminal通过公私钥和ssh登录Linux
刚开始使用mac,会觉得很难用,在网上找的方法也差强人意,经过自己的实践,找到下面这种方法,很好用,步骤也很简单 1.在mac本的个人目录下创建一个文件夹:.ssh. 在这个文件夹下使用ssh- ...
- Java 的静态代理 动态代理(JDK和cglib)
转载:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是 ...
- php 入门1
一.php在引入文件和js引入文件的区别 1.php在引入文件是用代码控制,而js是通过标签的属性src引入: 2.php引入可以在引入下写代码,而js是不可以的 3.静态效果的js可以引入的时间,引 ...
- C#类和接口
1.类的定义 C#使用类关键字class定义类,如: public class MyClass { } 2.类的继承 类继承使用: public class BaseClass { } public ...