redis分布式集群搭建介绍
Redis集群架构图
上图蓝色为redis集群的节点。
节点之间通过ping命令来测试连接是否正常,节点之间没有主区分,连接到任何一个节点进行操作时,都可能会转发到其他节点。
1、Redis的容错机制
节点之间会定时的互相发送ping命令,测试节点的健康状态,当节点接受到ping命令后,会返回一个pong字符串。
投票机制:如果一个节点A给节点B发送ping没有得到pong返回,会通知其他节点再次给B发送ping,如果集群中有超过一半的节点收不B节点的pong。那么就认为B节点挂了。一般会为每个节点提供一个备份节点,如果挂掉会切换到备份节点。
2、Redis集群存储原理
Redis对于每个存放的key会进行hash操作,生成一个[0-16384]的hash值(先进行
crc 算法再对16384取余)。
集群的情况下,就是把[0-16384]的区间进行拆分,放到不同的redis中。
3、Redis的持久化
Snapshotting:定时的将Redis内存中的数据保存到硬盘中
AOF:将所有的command操作保存到aof中,AOP的同步频率很高,数据即使丢失,粒度也很小,但会在性能上造成影响。
二、集群环境搭建
redis集群管理工具redis-trib.rb依赖ruby环境,首先需要安装ruby环境
安装rubyyum install rubyyum install rubygems安装ruby和redis的接口程序
拷贝redis-3.0.0.gem至/usr/local下
执行:gem install /usr/local/redis-3.0.0.gem三、创建Redis集群
在一台服务器上,可以用不同端口号来表示不同redis服务器。
Redis集群最少需要三台服务器,而每台服务器有需要备用服务器,所以最少需要6台服务器。端口规划如下:
主服务器:192.168.100.66 :7001:7002:7003
从服务器:192.168.100.66 :7004:7005:7006
在/usr/local 创建文件夹用来存放服务器程序
mkdir 7001 7002 7003 7004 7005 7006
如果想让redis支持集群需要修改redis.config配置文件的cluster-enabled yes
本例中我们以端口来区别不同的redis服务,所以还需要修改redis.config的port为对应端口
修改完配置文件,将redis安装目录的bin复制到上面每个目录中。
分别进入7001/bin/ 7002/bin .....
启动服务./redis-server ./redis.conf
查看redis进程:ps -aux|grep redis 如下图则说明启动成功
创建集群:
将之前解压的文件夹的redis-3.0.0/src/redis-trib.rb复制到redis-cluster目录
运行./redis-trib.rb create --replicas 1 192.168.100.66:7001 192.168.100.66:7002 192.168.100.66:7003 192.168.100.66:7004 192.168.100.66:7005192.168.100.66:7006如果执行时报如下错误:[ERR] Node XXXXXX is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0解决方法是删除生成的配置文件nodes.conf,如果不行则说明现在创建的结点包括了旧集群的结点信息,需要删除redis的持久化文件后再重启redis,比如:appendonly.aof、dump.rdb
如果成功最终输入如下:
查询集群信息:
说明:
./redis-cli -c -h 192.168.101.3 -p 7001 ,其中-c表示以集群方式连接redis,-h指定ip地址,-p指定端口号
cluster nodes 查询集群结点信息
cluster info 查询集群状态信息
hash槽重新分配
第一步:连接上集群
./redis-trib.rb reshard 192.168.101.3:7001(连接集群中任意一个可用结点都行)
第二步:输入要分配的槽数量
输入 500表示要分配500个槽
第三步:输入接收槽的结点id
这里准备给7007分配槽,通过cluster nodes查看7007结点id为15b809eadae88955e36bcdbb8144f61bbbaf38fb
输入:15b809eadae88955e36bcdbb8144f61bbbaf38fb
第四步:输入源结点id
这里输入all
第五步:输入yes开始移动槽到目标结点id
添加从节点
集群创建成功后可以向集群中添加节点,下面是添加一个slave从节点。
添加7008从结点,将7008作为7007的从结点。
./redis-trib.rb add-node --slave --master-id 主节点id 添加节点的ip和端口 集群中已存在节点ip和端口
执行如下命令:
./redis-trib.rb add-node --slave --master-id cad9f7413ec6842c971dbcc2c48b4ca959eb5db4192.168.101.3:7008 192.168.101.3:7001
cad9f7413ec6842c971dbcc2c48b4ca959eb5db4是7007结点的id,可通过cluster nodes查看。
注意:如果原来该结点在集群中的配置信息已经生成cluster-config-file指定的配置文件中(如果cluster-config-file没有指定则默认为nodes.conf),这时可能会报错:
[ERR] Node XXXXXX is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0
解决方法是删除生成的配置文件nodes.conf,删除后再执行./redis-trib.rb add-node指令
查看集群中的结点,刚添加的7008为7007的从节点:
删除结点:./redis-trib.rb del-node 127.0.0.1:7005 4b45eb75c8b428fbd77ab979b85080146a9bc017删除已经占有hash槽的结点会失败,报错如下:[ERR] Node 127.0.0.1:7005 is not empty! Reshard data away and try again.需要将该结点占用的hash槽分配出去(参考hash槽重新分配章节)。
测试:Maven:<dependencies><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.7.0</version></dependency><!-- https://mvnrepository.com/artifact/junit/junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-test --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>4.3.10.RELEASE</version><scope>test</scope></dependency></dependencies>普通测试:@Testpublic void redisClusterTest1(){JedisPoolConfig config=new JedisPoolConfig();config.setMaxTotal(30);config.setMaxIdle(2);Set<HostAndPort> jedisNode=new HashSet<HostAndPort>();jedisNode.add(new HostAndPort("192.168.100.66",7001));jedisNode.add(new HostAndPort("192.168.100.66",7002));jedisNode.add(new HostAndPort("192.168.100.66",7003));jedisNode.add(new HostAndPort("192.168.100.66",7004));jedisNode.add(new HostAndPort("192.168.100.66",7005));jedisNode.add(new HostAndPort("192.168.100.66",7006));JedisCluster jc=new JedisCluster(jedisNode,config);jc.set("name","老王");String value=jc.get("name");System.out.println(value);}Spring测试:
配置文件:<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"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.xsd"><!-- 连接池配置 --><bean id="jedisPoolConfig">测试类:@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({"classpath:spring-config.xml"})public class RedisClusterTest {@Autowiredprivate JedisCluster jedisCluster;@Testpublic void redisClusterTest2(){jedisCluster.set("username","小明啦啦");String name=jedisCluster.get("username");System.out.println(name);}}更多redis知识请关注redis数据库教程栏目。以上就是redis分布式集群搭建介绍的详细内容,更多请关注小潘博客其它相关文章!