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环境
安装ruby
yum install ruby yum install rubygems
解决方法是删除生成的配置文件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测试数据/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository测试数据/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>普通测试:
@Test
public 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://HdhCmsTestspringframework.org/schema/beans"
xmlns:xsi="http://HdhCmsTestw3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://HdhCmsTestspringframework.org/schema/beans http://HdhCmsTestspringframework.org/schema/beans/spring-beans.xsd">
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大连接数 -->
<property name="maxTotal" value="30" />
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="10" />
<!-- 每次释放连接的最大数目 -->
<property name="numTestsPerEvictionRun" value="1024" />
<!-- 释放连接的扫描间隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<!-- 连接最小空闲时间 -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在获取连接的时候检查有效性, 默认false -->
<property name="testOnBorrow" value="true" />
<!-- 在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="true" />
<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<!-- redis集群 -->
<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.100.66"></constructor-arg>
<constructor-arg index="1" value="7001"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.100.66"></constructor-arg>
<constructor-arg index="1" value="7002"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.100.66"></constructor-arg>
<constructor-arg index="1" value="7003"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.100.66"></constructor-arg>
<constructor-arg index="1" value="7004"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.100.66"></constructor-arg>
<constructor-arg index="1" value="7005"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.100.66"></constructor-arg>
<constructor-arg index="1" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
<constructor-arg index="1" ref="jedisPoolConfig"></constructor-arg>
</bean>
</beans>测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-config.xml"})
public class RedisClusterTest {
@Autowired
private JedisCluster jedisCluster;
@Test
public void redisClusterTest2(){
jedisCluster.set("username","小明啦啦");
String name=jedisCluster.get("username");
System.out.println(name);
}
}更多redis知识请关注redis数据库教程栏目。
以上就是redis分布式集群搭建介绍的详细内容,更多请关注Gxlcms其它相关文章!