一文轻松搞懂redis集群原理及搭建与使用
今天早上由于zookeeper和redis集群不在同一虚拟机导致出了点很小错误(人为),所以这里总结一下redis集群的搭建以便日后所需同时也希望能对你有所帮助。
笔主这里使用的是Centos7.如果你碰到任何问题都可以来问我,留言或者加我微信:bwcx9393.
关于Linux的一些资料
链接:https://pan.baidu.com/s/1Opgu6kQe_b1IRJbxTGD6XA 密码:8yk4
一 redis的安装
Redis是c语言开发的。
安装redis需要c语言的编译环境。如果没有gcc需要在线安装:yum install gcc-c++
第一步:获取源码包:wget http://download.redis.io/releases/redis-3.0.0.tar.gz
第二步:解压缩redis:tar zxvf redis-3.0.0.tar.gz
第三步:编译。进入redis源码目录(cd redis-3.0.0)。执行 make
第四步:安装。make install PREFIX=/usr/local/redis
PREFIX参数指定redis的安装目录。一般软件安装到/usr目录下
这样Redis就成功装在了我们的usr/local/redis目录下。
第五步:设置后台启动:
[root@localhost redis-3.0.0]# cp redis.conf /usr/local/redis/bin/
(把/root/redis-3.0.0/redis.conf复制到/usr/local/redis/bin目录下)
修改配置文件:把daemonize后面的参数改为yes
测试启动:[root@localhost bin]# ./redis-server redis.conf
查看redis进程:
[root@localhost bin]# ps aux|grep redis
二 redis集群的搭建
2.1 redis集群(redis-cluster)原理
3.0版本之前的redis是不支持集群的,3.0版本之前想要搭建redis集群的话需要中间件来找到存值和取值的对应节点。
3.0版本以后的redis集群架构图:
那么这是如何实现的呢???
Redis 集群中内置了 16384个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
根据下图应该更容易理解了。(图片来源:http://www.cnblogs.com/liyasong/p/redis_jiqun.html)
redis集群投票机制
redis集群中有多台redis服务器不可避免会有服务器挂掉。redis集群服务器之间通过互相的ping-pong判断是否节点可以连接上。如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机了。
上面就是我们常说的为了容错而生的redis集群投票机制。
2.2 redis集群(redis-cluster)的搭建
redis集群搭建起来很简单,我们这里用一台虚拟机模拟搭建包含6个redis服务器的集群,实际工作中与使用多台服务器搭建是一个操作。
我们上面已经装好了一个redis实例,现在我们需要把它复制6份并修改相应端口。
第一步: 新建redis-cluster文件夹
第二步:复制redis实例
[root@Snailclimb local]# cp redis/bin redis-cluster/redis1
如果你复制过去的redis实例有dump.rdb文件的话最好也要删除。
第三步:修改配置文件
修改bin目录下的redis.conf配置文件
第四步:继续复制5个redis实例
我们用上面的redis实例复制5个redis实例,然后把他们的配置文件的端口号改为7002-7006
第五步 :新建一个执行脚本:
[root@Snailclimb redis-cluster]# vim start-all.sh
脚本内容如下:
cd redis1/bin
./redis-server redis.conf
cd ..
cd ..
cd redis2/bin
./redis-server redis.conf
cd ..
cd ..
cd redis3/bin
./redis-server redis.conf
cd ..
cd ..
cd redis4/bin
./redis-server redis.conf
cd ..
cd ..
cd redis5/bin
./redis-server redis.conf
cd ..
cd ..
cd redis6/bin
./redis-server redis.conf
为脚本赋予执行权限:
[root@Snailclimb redis-cluster]# chmod u+x start-all.sh
同时启动6个redis实例:
[root@Snailclimb redis-cluster]# ./start-all.sh
第六步:将redis-trib.rb复制到redis-cluster目录下面:
并为脚本赋予执行权限:
[root@Snailclimb redis-cluster]# chmod u+x redis-trib.rb
第七步:安装ruby和ruby运行环境
yum install ruby
yum install rubygems
gem install redis-3.0.0.gem
第八步:使用ruby脚本搭建集群:
[root@Snailclimb redis-cluster]#./redis-trib.rb create –replicas 1 192.168.25.130:7001 192.168.25.130:7002 192.168.25.130:7003 192.168.25.130:7004 192.168.25.130:7005 192.168.25.130:7006
查看集群:
注意:端口修改错误或者没有将cluster-enabled yes前的注释去掉都会导致集群搭建失败。总的来说,redis集群搭建还是很简单的。
这样一个完整的redis集群就已经搭建完毕了。。。
三 redis单机版与集群版的测试使用
添加Maven依赖:
<!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
单机版redis测试:
@Test
public void testJedis() throws Exception {
// 创建一个连接Jedis对象,参数:host、port
Jedis jedis = new Jedis("192.168.25.130", 6379);
// 直接使用jedis操作redis。所有jedis的命令都对应一个方法。
jedis.set("bwcx9393", "欢迎关注Java面试通关手册");
String string = jedis.get("bwcx9393");
System.out.println(string);//输出内容:欢迎关注微信公众号:Java面试通关手册
// 关闭连接
jedis.close();
}
使用连接池测试单机版redis:
@Test
public void testJedisPool() throws Exception {
// 创建一个连接池对象,两个参数host、port
JedisPool jedisPool = new JedisPool("192.168.25.130", 6379);
// 从连接池获得一个连接,就是一个jedis对象。
Jedis jedis = jedisPool.getResource();
// 使用jedis操作redis
String string = jedis.get("bwcx9393");
System.out.println(string);//输出内容:欢迎关注微信公众号:Java面试通关手册
// 关闭连接,每次使用完毕后关闭连接。连接池回收资源。
jedis.close();
// 关闭连接池。
jedisPool.close();
}
测试集群版redis:
@Test
public void testJedisCluster() throws Exception {
// 创建一个JedisCluster对象。有一个参数nodes是一个set类型。set中包含若干个HostAndPort对象。
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.25.130", 7001));
nodes.add(new HostAndPort("192.168.25.130", 7002));
nodes.add(new HostAndPort("192.168.25.130", 7003));
nodes.add(new HostAndPort("192.168.25.130", 7004));
nodes.add(new HostAndPort("192.168.25.130", 7005));
nodes.add(new HostAndPort("192.168.25.130", 7006));
JedisCluster jedisCluster = new JedisCluster(nodes);
// 直接使用JedisCluster对象操作redis。
jedisCluster.set("test", "123");
String string = jedisCluster.get("test");
System.out.println(string);
// 关闭JedisCluster对象
jedisCluster.close();
}
四 如何在JavaWeb项目中实现单机和集群无缝切换使用
我们如何才能在项目中实现自己想用的单机redis就用单机redis想用redis集群就用redis集群而不要修改项目代码呢???
创建相应类和接口
接口:
import java.util.List;
public interface JedisClient {
String set(String key, String value);
String get(String key);
Boolean exists(String key);
Long expire(String key, int seconds);
Long ttl(String key);
Long incr(String key);
Long hset(String key, String field, String value);
String hget(String key, String field);
Long hdel(String key, String... field);
Boolean hexists(String key, String field);
List<String> hvals(String key);
Long del(String key);
}
集群版使用:
import java.util.List;
import redis.clients.jedis.JedisCluster;
public class JedisClientCluster implements JedisClient {
private JedisCluster jedisCluster;
public JedisCluster getJedisCluster() {
return jedisCluster;
}
public void setJedisCluster(JedisCluster jedisCluster) {
this.jedisCluster = jedisCluster;
}
@Override
public String set(String key, String value) {
return jedisCluster.set(key, value);
}
@Override
public String get(String key) {
return jedisCluster.get(key);
}
@Override
public Boolean exists(String key) {
return jedisCluster.exists(key);
}
@Override
public Long expire(String key, int seconds) {
return jedisCluster.expire(key, seconds);
}
@Override
public Long ttl(String key) {
return jedisCluster.ttl(key);
}
@Override
public Long incr(String key) {
return jedisCluster.incr(key);
}
@Override
public Long hset(String key, String field, String value) {
return jedisCluster.hset(key, field, value);
}
@Override
public String hget(String key, String field) {
return jedisCluster.hget(key, field);
}
@Override
public Long hdel(String key, String... field) {
return jedisCluster.hdel(key, field);
}
@Override
public Boolean hexists(String key, String field) {
return jedisCluster.hexists(key, field);
}
@Override
public List<String> hvals(String key) {
return jedisCluster.hvals(key);
}
@Override
public Long del(String key) {
return jedisCluster.del(key);
}
}
单机版使用:
import java.util.List;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class JedisClientPool implements JedisClient {
private JedisPool jedisPool;
public JedisPool getJedisPool() {
return jedisPool;
}
public void setJedisPool(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
@Override
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String result = jedis.set(key, value);
jedis.close();
return result;
}
@Override
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
}
@Override
public Boolean exists(String key) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.exists(key);
jedis.close();
return result;
}
@Override
public Long expire(String key, int seconds) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.expire(key, seconds);
jedis.close();
return result;
}
@Override
public Long ttl(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.ttl(key);
jedis.close();
return result;
}
@Override
public Long incr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.incr(key);
jedis.close();
return result;
}
@Override
public Long hset(String key, String field, String value) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hset(key, field, value);
jedis.close();
return result;
}
@Override
public String hget(String key, String field) {
Jedis jedis = jedisPool.getResource();
String result = jedis.hget(key, field);
jedis.close();
return result;
}
@Override
public Long hdel(String key, String... field) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hdel(key, field);
jedis.close();
return result;
}
@Override
public Boolean hexists(String key, String field) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.hexists(key, field);
jedis.close();
return result;
}
@Override
public List<String> hvals(String key) {
Jedis jedis = jedisPool.getResource();
List<String> result = jedis.hvals(key);
jedis.close();
return result;
}
@Override
public Long del(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.del(key);
jedis.close();
return result;
}
}
applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 连接redis单机版 -->
<bean id="jedisClientPool" class="xx.xx.xx.JedisClientPool">
<property name="jedisPool" ref="jedisPool"></property>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.25.130"/>
<constructor-arg name="port" value="6379"/>
</bean>
<!-- 连接redis集群 -->
<!-- <bean id="jedisClientCluster" class="xx.xx.xx.JedisClientCluster">
<property name="jedisCluster" ref="jedisCluster"/>
</bean>
<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg name="nodes">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.130"></constructor-arg>
<constructor-arg name="port" value="7001"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.130"></constructor-arg>
<constructor-arg name="port" value="7002"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.130"></constructor-arg>
<constructor-arg name="port" value="7003"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.130"></constructor-arg>
<constructor-arg name="port" value="7004"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.130"></constructor-arg>
<constructor-arg name="port" value="7005"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.130"></constructor-arg>
<constructor-arg name="port" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
</bean> -->
</beans>
测试代码:
public class JedisClientTest {
@Test
public void testJedisClient() throws Exception {
//初始化spring容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
//从容器中获得JedisClient对象
JedisClient jedisClient = applicationContext.getBean(JedisClient.class);
jedisClient.set("aaa", "111");
String string = jedisClient.get("aaa");
System.out.println(string);
}
}
这样在实际项目中我们无需修改代码就可以实现单机和集群版的相关切换。。
欢迎关注我的微信公众号:”Java面试通关手册”(坚持原创,分享美文,分享各种Java学习资源,面试题,以及企业级Java实战项目回复关键字免费领取):。
一文轻松搞懂redis集群原理及搭建与使用的更多相关文章
- Redis | 一文轻松搞懂redis集群原理及搭建与使用
转载:https://juejin.im/post/5ad54d76f265da23970759d3 作者:SnailClimb 这里总结一下redis集群的搭建以便日后所需同时也希望能对你有所帮助. ...
- redis单点、redis主从、redis哨兵sentinel,redis集群cluster配置搭建与使用
目录 redis单点.redis主从.redis哨兵 sentinel,redis集群cluster配置搭建与使用 1 .redis 安装及配置 1.1 redis 单点 1.1.2 在命令窗口操作r ...
- redis集群环境的搭建和错误分析
redis集群环境的搭建和错误分析 redis集群时,出现的几个异常问题 09 redis集群的搭建 以及遇到的问题
- 超详细,多图文介绍redis集群方式并搭建redis伪集群
超详细,多图文介绍redis集群方式并搭建redis伪集群 超多图文,对新手友好度极好.敲命令的过程中,难免会敲错,但为了截好一张合适的图,一旦出现一点问题,为了好的演示效果,就要从头开始敲.且看且珍 ...
- Redis项目实战---应用及理论(二)---Redis集群原理
一. Redis官方推荐集群方案:Redis Cluster 适用于redis3.0以后版本, redis cluster 是redis官方提供的分布式解决方案,在3.0版本后推出的,有 ...
- redis 集群方案及搭建
由于Redis出众的性能,其在众多的移动互联网企业中得到广泛的应用.Redis在3.0版本前只支持单实例模式,虽然现在的服务器内存可以到100GB.200GB的规模,但是单实例模式限制了Redis没法 ...
- Redis集群~windows下搭建Sentinel环境及它对主从模式的实际意义
回到目录 关于redis-sentinel出现的原因 Redis集群的主从模式有个最大的弊端,就是当主master挂了之前,它的slave从服务器无法提升为主,而在redis-sentinel出现之后 ...
- redis集群原理
redis是单线程,但是一般的作为缓存使用的话,redis足够了,因为它的读写速度太快了. 官方的一个简单测试: 测试完成了50个并发执行100000个请求. 设置和获取的值是一个256字节字符串 ...
- Redis 集群环境的搭建
下载与解压 [root@localhost ~]# cd /usr/temp/ [root@localhost temp]# wget http://download.redis.io/release ...
随机推荐
- mysql中用户和权限
用户管理 用户数据所在位置: mysql中的所有用户,都存储在系统数据库(mysql)中的user 表中——不管哪个数据库的用户,都存储在这里. 表初始内容如下: 创建用户: 形式: create ...
- 在DbGrid中,不按下Ctrl,单击鼠标如何实现多选?谢谢
解决方案 » 有了dbgrid1.options.dgmultiselect:=true;必须按下Ctrl键,才能实现多选, 修改源代码,把以下内容if Select and (ssShift i ...
- 阿里巴巴分布式数据库服务DRDS研发历程
淘宝TDDL研发历史和背景 分布式关系型数据库服务(Distribute Relational Database Service,简称DRDS)是一种水平拆分.可平滑扩缩容.读写分离的在线分布式数据库 ...
- 【Python】Python流程控制
1)if条件测试 Python的比较操作 所有的Python对象都支持比较操作 测试操作符('=='操作符测试值的相等性: 'is'表达式测试对象的一致性) Python中不同类型的比较方法 数字:通 ...
- noip模拟题《戏》game
[问题背景] zhx 和他的妹子(们) 做游戏.[问题描述] 考虑 N 个人玩一个游戏,任意两个人之间进行一场游戏(共 N*(N-1)/2 场),且每场一定能分出胜负. ...
- BZOJ5017 Snoi2017炸弹(线段树+强连通分量+缩点+传递闭包)
容易想到每个炸弹向其能引爆的炸弹连边,tarjan缩点后bitset传递闭包.进一步发现每个炸弹能直接引爆的炸弹是一段连续区间,于是线段树优化建图即可让边的数量降至O(nlogn).再冷静一下由于能间 ...
- 🔺 Garbage Remembering Exam UVA - 11637()
题目大意:给你N个单词,有两种方法随机排列,一种随机排成一行,另一种随机排成一圈,当两个单词之间的距离在两种排列中都严格小于K时,则这两个单词构成无效单词,问无效单词的期望. 解题思路:首先对于一排单 ...
- 制作VR视频播放器
最近VR火的不要不要的,但是综合起来,VR资源最多的还是全景图片和全景视频,今天在这里给大家简单介绍一下如何用Unity制作简单的VR视频播放器. 首先找到EasyMovieTexture这个插件,A ...
- 《Java程序设计》第8周学习总结 20165218 2017-2018-1
20165218 2017-2018-1 <Java程序设计>第8周学习总结 教材学习内容总结 第12章 java多线程机制 java中的线程 计算机在任何给定时刻只能执行一个线程,多线程 ...
- WebDriver的定位元素方法
如果把页面上的元素看作人的话,在现实世界如何找到某人呢?方法有三: 一.通过人本身的属性,例如他的姓名,手机号,身份证号,性别,这些可区别他人的属性.在web页面上的元素也有这些属性,例如,id.na ...