在redis3.0之前,采用哨兵机制来保证高可用。哨兵存在一些问题,比如master挂掉后,哨兵不是立即切换,中间需要一个时间来确认master是不是挂掉了。这个时间内会写入数据失败。
在redis3.0之后,出现了集群的概念。很好的解决了哨兵的不足。
redis集群需要3个master。
如果没有那么多机器的话,那么在一台机器上面启动几个redis实例也是可以的。不过每个机器都要对应一个redis.conf文件,把端口给改一下
daemonize yes #设置后台启动
bind hadoop4 #绑定本地ip
dir /usr/local/redis-cluster/01 #数据持久化路径,注意不要用相对路径,相对路径是相对于启动redis服务时的路径,这个路径是可变的。
cluster-enabled yes #开启集群模式
cluster-config-file nodes-6379.conf #指定集群单节点配置文件,注意端口号要对上
appendonly yes #开启aof持久化模式
要安装ruby
yum install ruby
yum install rubygems
gem install redis #相当于redis与ruby的接口
分别启动6个redis实例,检查一下是否都启动成功了。
此时还并不是集群,要把这6台机器纳入集群的管理后,才是创建了集群
用ruby来创建集群
redis-trib.rb create --replicas 1 192.168.137.130:7001 192.168.137.130:7002 192.168.137.130:7003 192.168.137.130:7004 192.168.137.130:7005 192.168.137.130:7006
注意,要用ip,而不是主机名,否则报错。因为ruby对域名解析做的不好。
其中1表示主从节点的比例,这里设置为1,具体就是各3个。
如果创建失败了,那么可能就是以前创建的时候的错误信息写入config-node-file指定的文件中了,需要把所有的redis都停掉,手动删除这个文件,然后重启redis。再执行一次上面的命令即可。更多信息可以看此篇博客:http://blog.csdn.net/ownfire/article/details/46624005
客户端连接集群
redis-cli -c -h hadoop4 -p 7001
-c表示集群的意思
客户端命令
cluster nodes #查看集群状态
cluster info #查看集群信息
对于java来说,
因为redis的集群配置比较多,为了便于管理,这里采用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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:redis.properties" />
<context:component-scan base-package="lagou.redis">
</context:component-scan>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.cluster.maxIdle}" />
</bean>
<bean id="hostport1" class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis.cluster.ip1}" />
<constructor-arg name="port" value="${redis.cluster.port1}" />
</bean>
<bean id="hostport2" class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis.cluster.ip2}" />
<constructor-arg name="port" value="${redis.cluster.port2}" />
</bean>
<bean id="hostport3" class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis.cluster.ip3}" />
<constructor-arg name="port" value="${redis.cluster.port3}" />
</bean>
<bean id="hostport4" class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis.cluster.ip4}" />
<constructor-arg name="port" value="${redis.cluster.port4}" />
</bean>
<bean id="hostport5" class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis.cluster.ip5}" />
<constructor-arg name="port" value="${redis.cluster.port5}" />
</bean>
<bean id="hostport6" class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis.cluster.ip6}" />
<constructor-arg name="port" value="${redis.cluster.port6}" />
</bean>
<bean id="redisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg name="nodes">
<set>
<ref bean="hostport1" />
<ref bean="hostport2" />
<ref bean="hostport3" />
<ref bean="hostport4" />
<ref bean="hostport5" />
<ref bean="hostport6" />
</set>
</constructor-arg>
<constructor-arg name="timeout" value="6000" />
<constructor-arg name="poolConfig">
<ref bean="jedisPoolConfig" />
</constructor-arg>
</bean>
</beans>
动态增加集群节点,ip2为集群中的任意节点(master跟slave都可以)。ip1为要加入的节点。因为ip2属于集群的一员,他知道所有的节点ip。所以ip1知道了ip2,就知道了整个集群。默认新加入的节点为master
redis-trib.rb add-node ip1:port1 ip2:port2
新加入的master节点因为没有分配slot,所以不能存储数据。需要进行以下操作
redis-trib.rb reshard ip1:port1
1提示一:是希望你需要多少个槽移动到新的节点上,可以自己设置,比如200个槽。
2提示二:是你需要把这200个slot槽移动到那个节点上去(需要指定节点id),并且下个 提示是输入all为从所有主节点(7001 7002 7003)中分别抽取响应的槽数(一共为200个槽到指定的新节点中!,并且会打印执行分片的计划。)
3提示三:输入yes确认开始执行分片任务。
如果把新加入的节点变为从节点(默认是主节点,但没有分配槽),
比如加入的节点为ip:port
ip:port> cluster replicate 382634a4025778c040b7213453fd42a709f79e28
下面的这个id为要挂在到master节点的id。
移除节点
如果发现杀鸡用牛刀了,就可以移除节点。
下面是移除slave节点
redis-trib.rb
del-node ip:port 97b0e0115326833724eb0ffe1d0574ee34618e9f
要移除master节点的话,就比较麻烦,因为master是分配了槽的(slot).所以我们这里必须先把7007里的slot槽放入到其他的可用主节点中去,然后再进行移除节点操作才行,不然会出现数据丢失问题
步骤一:删除7007(master)节点之前,我们需要先把其全部的数据(slot槽)移动到其他节点上去(目前只能把master的数据迁移到一个节点上,暂时做不了平均分配功能)。
redis-trib.rb reshard ip:port
下面根据提示移动槽就可以了。移动完槽后,执行删除节点的命令。
redis-trib.rb del-node
ip:port 382634a4025778c040b7213453fd42a709f79e28
集群是用来做高可用的。
当master挂掉后,slave还会补上。但是当master跟其所隶属的所有slave都挂掉后,则会导致丢数据(重启挂点的机器后,数据还会找回来)