• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

一文轻松搞懂redis集群原理及搭建与使用

技术杂谈 勤劳的小蚂蚁 3个月前 (01-13) 97次浏览 已收录 0个评论 扫描二维码
这里总结一下redis集群的搭建以便日后所需同时也希望能对你有所帮助。关于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 脚本内容如下:
  1. cd redis1/bin
  2. ./redis-server redis.conf
  3. cd ..
  4. cd ..
  5. cd redis2/bin
  6. ./redis-server redis.conf
  7. cd ..
  8. cd ..
  9. cd redis3/bin
  10. ./redis-server redis.conf
  11. cd ..
  12. cd ..
  13. cd redis4/bin
  14. ./redis-server redis.conf
  15. cd ..
  16. cd ..
  17. cd redis5/bin
  18. ./redis-server redis.conf
  19. cd ..
  20. cd ..
  21. cd redis6/bin
  22. ./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.155:7001 192.168.25.155:7002 192.168.25.155:7003 192.168.25.155:7004 192.168.25.155:7005 192.168.25.155:7006
查看集群:
注意:端口修改错误或者没有将cluster-enabled yes前的注释去掉都会导致集群搭建失败。总的来说,redis集群搭建还是很简单的。
这样一个完整的redis集群就已经搭建完毕了。。。

三 redis单机版与集群版的测试使用

添加Maven依赖:
  1.        <!-- Redis客户端 -->
  2.        <dependency>
  3.            <groupId>redis.clients</groupId>
  4.            <artifactId>jedis</artifactId>
  5.            <version>2.7.2</version>
  6.        </dependency>
  7.        <dependency>
  8.            <groupId>junit</groupId>
  9.            <artifactId>junit</artifactId>
  10.            <version>4.12</version>
  11.            <scope>test</scope>
  12.        </dependency>
单机版redis测试:
  1.    @Test
  2.    publicvoid testJedis()throwsException{
  3.        // 创建一个连接Jedis对象,参数:host、port
  4.        Jedis jedis =newJedis("192.168.25.155",6379);
  5.        // 直接使用jedis操作redis。所有jedis的命令都对应一个方法。
  6.        jedis.set("bwcx9393","欢迎关注Java面试通关手册");
  7.        String string = jedis.get("bwcx9393");
  8.        System.out.println(string);//输出内容:欢迎关注微信公众号:Java面试通关手册
  9.        // 关闭连接
  10.        jedis.close();
  11.    }
使用连接池测试单机版redis:
  1.    @Test
  2.    publicvoid testJedisPool()throwsException{
  3.        // 创建一个连接池对象,两个参数host、port
  4.        JedisPool jedisPool =newJedisPool("192.168.25.155",6379);
  5.        // 从连接池获得一个连接,就是一个jedis对象。
  6.        Jedis jedis = jedisPool.getResource();
  7.        // 使用jedis操作redis
  8.        String string = jedis.get("bwcx9393");
  9.        System.out.println(string);//输出内容:欢迎关注微信公众号:Java面试通关手册
  10.        // 关闭连接,每次使用完毕后关闭连接。连接池回收资源。
  11.        jedis.close();
  12.        // 关闭连接池。
  13.        jedisPool.close();
  14.    }
测试集群版redis:
  1.    @Test
  2.    publicvoid testJedisCluster()throwsException{
  3.        // 创建一个JedisCluster对象。有一个参数nodes是一个set类型。set中包含若干个HostAndPort对象。
  4.        Set<HostAndPort> nodes =newHashSet<>();
  5.        nodes.add(newHostAndPort("192.168.25.155",7001));
  6.        nodes.add(newHostAndPort("192.168.25.155",7002));
  7.        nodes.add(newHostAndPort("192.168.25.155",7003));
  8.        nodes.add(newHostAndPort("192.168.25.155",7004));
  9.        nodes.add(newHostAndPort("192.168.25.155",7005));
  10.        nodes.add(newHostAndPort("192.168.25.155",7006));
  11.        JedisCluster jedisCluster =newJedisCluster(nodes);
  12.        // 直接使用JedisCluster对象操作redis。
  13.        jedisCluster.set("test","123");
  14.        String string = jedisCluster.get("test");
  15.        System.out.println(string);
  16.        // 关闭JedisCluster对象
  17.        jedisCluster.close();
  18.    }

四 如何在JavaWeb项目中实现单机和集群无缝切换使用

我们如何才能在项目中实现自己想用的单机redis就用单机redis想用redis集群就用redis集群而不要修改项目代码呢???
创建相应类和接口接口:
  1. import java.util.List;
  2. publicinterfaceJedisClient{
  3.    String set(String key,String value);
  4.    String get(String key);
  5.    Boolean exists(String key);
  6.    Long expire(String key,int seconds);
  7.    Long ttl(String key);
  8.    Long incr(String key);
  9.    Long hset(String key,String field,String value);
  10.    String hget(String key,String field);
  11.    Long hdel(String key,String... field);
  12.    Boolean hexists(String key,String field);
  13.    List<String> hvals(String key);
  14.    Long del(String key);
  15. }
集群版使用:
  1. import java.util.List;
  2. import redis.clients.jedis.JedisCluster;
  3. publicclassJedisClientClusterimplementsJedisClient{
  4.    privateJedisCluster jedisCluster;
  5.    publicJedisCluster getJedisCluster(){
  6.        return jedisCluster;
  7.    }
  8.    publicvoid setJedisCluster(JedisCluster jedisCluster){
  9.        this.jedisCluster = jedisCluster;
  10.    }
  11.    @Override
  12.    publicString set(String key,String value){
  13.        return jedisCluster.set(key, value);
  14.    }
  15.    @Override
  16.    publicString get(String key){
  17.        return jedisCluster.get(key);
  18.    }
  19.    @Override
  20.    publicBoolean exists(String key){
  21.        return jedisCluster.exists(key);
  22.    }
  23.    @Override
  24.    publicLong expire(String key,int seconds){
  25.        return jedisCluster.expire(key, seconds);
  26.    }
  27.    @Override
  28.    publicLong ttl(String key){
  29.        return jedisCluster.ttl(key);
  30.    }
  31.    @Override
  32.    publicLong incr(String key){
  33.        return jedisCluster.incr(key);
  34.    }
  35.    @Override
  36.    publicLong hset(String key,String field,String value){
  37.        return jedisCluster.hset(key, field, value);
  38.    }
  39.    @Override
  40.    publicString hget(String key,String field){
  41.        return jedisCluster.hget(key, field);
  42.    }
  43.    @Override
  44.    publicLong hdel(String key,String... field){
  45.        return jedisCluster.hdel(key, field);
  46.    }
  47.    @Override
  48.    publicBoolean hexists(String key,String field){
  49.        return jedisCluster.hexists(key, field);
  50.    }
  51.    @Override
  52.    publicList<String> hvals(String key){
  53.        return jedisCluster.hvals(key);
  54.    }
  55.    @Override
  56.    publicLong del(String key){
  57.        return jedisCluster.del(key);
  58.    }
  59. }
单机版使用:
  1. import java.util.List;
  2. import redis.clients.jedis.Jedis;
  3. import redis.clients.jedis.JedisPool;
  4. publicclassJedisClientPoolimplementsJedisClient{
  5.    privateJedisPool jedisPool;
  6.    publicJedisPool getJedisPool(){
  7.        return jedisPool;
  8.    }
  9.    publicvoid setJedisPool(JedisPool jedisPool){
  10.        this.jedisPool = jedisPool;
  11.    }
  12.    @Override
  13.    publicString set(String key,String value){
  14.        Jedis jedis = jedisPool.getResource();
  15.        String result = jedis.set(key, value);
  16.        jedis.close();
  17.        return result;
  18.    }
  19.    @Override
  20.    publicString get(String key){
  21.        Jedis jedis = jedisPool.getResource();
  22.        String result = jedis.get(key);
  23.        jedis.close();
  24.        return result;
  25.    }
  26.    @Override
  27.    publicBoolean exists(String key){
  28.        Jedis jedis = jedisPool.getResource();
  29.        Boolean result = jedis.exists(key);
  30.        jedis.close();
  31.        return result;
  32.    }
  33.    @Override
  34.    publicLong expire(String key,int seconds){
  35.        Jedis jedis = jedisPool.getResource();
  36.        Long result = jedis.expire(key, seconds);
  37.        jedis.close();
  38.        return result;
  39.    }
  40.    @Override
  41.    publicLong ttl(String key){
  42.        Jedis jedis = jedisPool.getResource();
  43.        Long result = jedis.ttl(key);
  44.        jedis.close();
  45.        return result;
  46.    }
  47.    @Override
  48.    publicLong incr(String key){
  49.        Jedis jedis = jedisPool.getResource();
  50.        Long result = jedis.incr(key);
  51.        jedis.close();
  52.        return result;
  53.    }
  54.    @Override
  55.    publicLong hset(String key,String field,String value){
  56.        Jedis jedis = jedisPool.getResource();
  57.        Long result = jedis.hset(key, field, value);
  58.        jedis.close();
  59.        return result;
  60.    }
  61.    @Override
  62.    publicString hget(String key,String field){
  63.        Jedis jedis = jedisPool.getResource();
  64.        String result = jedis.hget(key, field);
  65.        jedis.close();
  66.        return result;
  67.    }
  68.    @Override
  69.    publicLong hdel(String key,String... field){
  70.        Jedis jedis = jedisPool.getResource();
  71.        Long result = jedis.hdel(key, field);
  72.        jedis.close();
  73.        return result;
  74.    }
  75.    @Override
  76.    publicBoolean hexists(String key,String field){
  77.        Jedis jedis = jedisPool.getResource();
  78.        Boolean result = jedis.hexists(key, field);
  79.        jedis.close();
  80.        return result;
  81.    }
  82.    @Override
  83.    publicList<String> hvals(String key){
  84.        Jedis jedis = jedisPool.getResource();
  85.        List<String> result = jedis.hvals(key);
  86.        jedis.close();
  87.        return result;
  88.    }
  89.    @Override
  90.    publicLong del(String key){
  91.        Jedis jedis = jedisPool.getResource();
  92.        Long result = jedis.del(key);
  93.        jedis.close();
  94.        return result;
  95.    }
  96. }
applicationContext-redis.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3.    xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"
  4.    xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"
  5.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  7.    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
  8.    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
  9.    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
  10.    <!-- 连接redis单机版 -->
  11.    <beanid="jedisClientPool"class="xx.xx.xx.JedisClientPool">
  12.        <propertyname="jedisPool"ref="jedisPool"></property>
  13.    </bean>
  14.    <beanid="jedisPool"class="redis.clients.jedis.JedisPool">
  15.        <constructor-argname="host"value="192.168.25.155"/>
  16.        <constructor-argname="port"value="6379"/>
  17.    </bean>
  18.    <!-- 连接redis集群 -->
  19. <!--     <bean id="jedisClientCluster" class="xx.xx.xx.JedisClientCluster">
  20.        <property name="jedisCluster" ref="jedisCluster"/>
  21.    </bean>
  22.    <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
  23.        <constructor-arg name="nodes">
  24.            <set>
  25.                <bean class="redis.clients.jedis.HostAndPort">
  26.                    <constructor-arg name="host" value="192.168.25.155"></constructor-arg>
  27.                    <constructor-arg name="port" value="7001"></constructor-arg>
  28.                </bean>
  29.                <bean class="redis.clients.jedis.HostAndPort">
  30.                    <constructor-arg name="host" value="192.168.25.155"></constructor-arg>
  31.                    <constructor-arg name="port" value="7002"></constructor-arg>
  32.                </bean>
  33.                <bean class="redis.clients.jedis.HostAndPort">
  34.                    <constructor-arg name="host" value="192.168.25.155"></constructor-arg>
  35.                    <constructor-arg name="port" value="7003"></constructor-arg>
  36.                </bean>
  37.                <bean class="redis.clients.jedis.HostAndPort">
  38.                    <constructor-arg name="host" value="192.168.25.155"></constructor-arg>
  39.                    <constructor-arg name="port" value="7004"></constructor-arg>
  40.                </bean>
  41.                <bean class="redis.clients.jedis.HostAndPort">
  42.                    <constructor-arg name="host" value="192.168.25.155"></constructor-arg>
  43.                    <constructor-arg name="port" value="7005"></constructor-arg>
  44.                </bean>
  45.                <bean class="redis.clients.jedis.HostAndPort">
  46.                    <constructor-arg name="host" value="192.168.25.155"></constructor-arg>
  47.                    <constructor-arg name="port" value="7006"></constructor-arg>
  48.                </bean>
  49.            </set>
  50.        </constructor-arg>
  51.    </bean> -->
  52. </beans>
测试代码:
  1. publicclassJedisClientTest{
  2.    @Test
  3.    publicvoid testJedisClient()throwsException{
  4.        //初始化spring容器
  5.        ApplicationContext applicationContext =newClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
  6.        //从容器中获得JedisClient对象
  7.        JedisClient jedisClient = applicationContext.getBean(JedisClient.class);
  8.        jedisClient.set("aaa","111");
  9.        String string = jedisClient.get("aaa");
  10.        System.out.println(string);
  11.    }
  12. }
这样在实际项目中我们无需修改代码就可以实现单机和集群版的相关切换。。

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:一文轻松搞懂redis集群原理及搭建与使用
喜欢 (0)
[247507792@qq.com]
分享 (0)
勤劳的小蚂蚁
关于作者:
温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00