自已撸的,一针一线,有图有真相
Step1准备好redis-5.0.8.tar.gz 包
Step2 上传到centos7 /root 目录下面
Step3 解压 tar -zxvf redis-5.0.8.tar.gz
Step4 编译 make
Step5 安装 make install
若报error,基本上是没有安装gcc ,make 等lib库
yum install -y gcc g++ gcc-c++ make
Step6 安装成功以后。配置环境变量
vim /etc/profile
export PATH=${JAVA_HOME}/bin:/root/redis-5.0.8/src:${ZOOKEEPER_HOME}/bin:${KAFKA_HOME}/bin:/usr/local/openssh-8.1p1/sbin:/usr/local/openssh-8.1p1/bin:$PATH
执行 source /etc/profile 生效
Step7文件目录定位到/root/redis-5.0.8/
在机器ip为172.16.104.219 ,机器ip为,机器ip为 上面分别创建cluster 用于配置文件里面的dir路径。
mkdir cluster
pwd 查询路径 正确样式为/root/redis-5.0.8/cluster
Step8 修改三台机器的redis.conf 文件
Master 机器
vim /root/redis-5.0.8/redis.conf
port 6379
#bind 172.16.104.198
masterauth "123456."
requirepass "123456."
daemonize yes
pidfile "/var/run/redis_6379.pid"
protected-mode no
#cluster-enabled no
#cluster-config-file nodes_6379.conf
#cluster-node-timeout 15000
appendonly yes
logfile "/tmp/redis6379.log"
dir "/root/redis-5.0.8/cluster"
Slave1机器
vim /root/redis-5.0.8/redis.conf
port 6379
#bind 172.16.104.210
masterauth "123456."
requirepass "123456."
daemonize yes
pidfile "/var/run/redis_6379.pid"
protected-mode no
#cluster-enabled no
#cluster-config-file nodes_6379.conf
#cluster-node-timeout 15000
appendonly yes
logfile "/tmp/redis6379.log"
dir "/root/redis-5.0.8/cluster"
slaveof 172.16.104.198 6379
Slave2机器
vim /root/redis-5.0.8/redis.conf
port 6379
#bind 172.16.104.219
masterauth "123456."
requirepass "123456."
daemonize yes
pidfile "/var/run/redis_6379.pid"
protected-mode no
#cluster-enabled no
#cluster-config-file nodes_6379.conf
#cluster-node-timeout 15000
appendonly yes
logfile "/tmp/redis6379.log"
dir "/root/redis-5.0.8/cluster"
slaveof 172.16.104.198 6379
修改 三台机器的 哨兵 配置 文件 sentinel.conf
配置一样
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel_6379.pid"
logfile "/tmp/sentinel6379.log"
dir "/tmp"
protected-mode no
sentinel monitor mymaster 172.16.104.198 6379 2
sentinel down-after-milliseconds mymaster 15000
sentinel failover-timeout mymaster 60000
sentinel auth-pass mymaster 123456.
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel current-epoch 1
Step8 完成以上配置进行启动,先启动主master机器 上的redis ,然后在启动从slave机器上的redis。再启动 分别三台机上面sentinel
主(ip:172.16.104.198)机器redis-server /root/redis-5.0.8/redis.conf
从redis-server /root/redis-5.0.8/redis.conf
从redis-server /root/redis-5.0.8/redis.conf
redis-sentinel /root/redis-5.0.8/sentinel.conf
redis-sentinel /root/redis-5.0.8/sentinel.conf
redis-sentinel /root/redis-5.0.8/sentinel.conf
ps -ef|grep redis 查看启动情况
图片1.pngStep9测试连接
连接主节点redis-cli -h 172.16.104.198 -p 6379 -a 123456.
连接从节点redis-cli -h 172.16.104.210 -p 6379 -a 123456.
图片2.png另外一种连接方式
图片3.png主节点和备用的从节点数据是一致的。
图片4.png主节点可读可写,从节点做为备份节点只读。
图片5.png通过 info查看节点当前的角色
图片6.png退出redis客户端连接使用exit
图片7.pngStep10下面测试sentinel哨兵 故障转移
先kill掉主节点的redis 进程
ps-ef|grep redis
图片8.png当主节点redis进程被杀死以后,再次去连接主节点将失败。
图片9.png此时,哨兵sentinel就开始通过上面的配置timeout时间,多个sentinel认定主节点客观宕机。多个sentinel自己进行选举出新的主节点。
客户端连接 172.16.104.210 机器 通过info查看Replication信息发现此时它已经是master主节点了。
redis-cli -h 172.16.104.210 -p 6379 -a 123456. 图片10.png 图片11.png通过上面的图,清晰的看到 sentinel已经完成了故障转移,主备的切换。
在有了哨兵模式的主从架构,可靠性明显提升了。
为了做到高可用。使用 supervisor守护进程, 每台机器把redis,sentinel服务加进去。supervisor本身设置开机启动。还可以直接把进程做成开机自启动 通过/etc/rc.d/init.d 编写shell命令启动脚本,然后添加软连接到rc3.d和rc5.d下面。服务部署至此完结!
JavaAPI
先建立spring-sentinels-redis.xml文件
<?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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<description>redis 相关类 Spring 托管</description>
<!--载入 redis 配置文件-->
<context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"/>
<bean id = "poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大空闲数 -->
<property name="maxIdle" value="50"></property>
<!-- 最大连接数 -->
<property name="maxTotal" value="100"></property>
<!-- 最大等待时间 -->
<property name="maxWaitMillis" value="20000"></property>
</bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<constructor-arg name="poolConfig" ref="poolConfig"></constructor-arg>
<constructor-arg name="sentinelConfig" ref="sentinelConfig"></constructor-arg>
<property name="password" value="123456."></property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
</bean>
<!-- 哨兵配置 -->
<bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<!-- 服务名称 -->
<property name="master">
<bean class="org.springframework.data.redis.connection.RedisNode">
<property name="name" value="mymaster"></property>
</bean>
</property>
<!-- 哨兵服务IP和端口 -->
<property name="sentinels">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="172.16.104.198"></constructor-arg>
<constructor-arg name="port" value="26379"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="172.16.104.210"></constructor-arg>
<constructor-arg name="port" value="26379"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="172.16.104.219"></constructor-arg>
<constructor-arg name="port" value="26379"></constructor-arg>
</bean>
</set>
</property>
</bean>
</beans>
创建Test测试类
package com.wenjin.zhu.redis;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:redis/spring-sentinels-redis.xml")
public class Test{
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@SuppressWarnings("unchecked")
@Test
public void testSentinel() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10);
jedisPoolConfig.setMaxIdle(5);
jedisPoolConfig.setMinIdle(5);
Set<String> sentinels = new HashSet<String>(
Arrays.asList("172.16.104.198:26379","172.16.104.210:26379", "172.16.104.219:26379"));
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, jedisPoolConfig, "123456.");
Jedis jedis = pool.getResource();
// 执行两个命令
jedis.set("name", "wenjin.zhu");
String value = jedis.get("testname");
System.err.println(value+jedis.get("tt"));
System.err.println("***"+redisTemplate.opsForValue().get("testname"));
Map<String, String> map = new HashMap<String, String>();
map.put("name", "jack");
map.put("age", "27");
map.put("class", "1");
redisTemplate.opsForHash().putAll("hashOps", map);
List<Object> kes = new ArrayList<Object>();
kes.add("name");
kes.add("age");
kes.add("class");
System.out.println(redisTemplate.opsForHash().multiGet("hashOps", kes));
}
@SuppressWarnings("unchecked")
@Test
public void testOpsValue() {
redisTemplate.opsForValue().set("testname","Amy");
System.err.println("***"+redisTemplate.opsForValue().get("testname"));
}
}
操作中遇到问题,欢迎在评论区留言一起探讨!
如果对你有帮助,点个赞。关注的话,可以在主页中看我更多的技术文档
网友评论