一、Redis分片存在的问题
问题说明:当使用redis分片时,如果发现redis节点宕机时,将直接影响redis分片的使用。
解决方案:准备3台redis服务器.当其中一台redis节点宕机时.则另外的服务器可以实现自动的故障迁移.
前提:得实现主从复制,内存数据的复制
二、主从复制的配置(数据同步)
由于分片机制和哨兵机制属于不同的实现逻辑.为了不产生干扰,需要将分片的配置全部关闭

准备3台服务器. 6379主机, 6380/6381从机.
复制shards文件目录改名为sentinel.
cp -r shards sentinel

删除sentinel目录下dump.rdb文件
rm -f dump.rdb

启动三台redis
redis-server 6379.conf
业务逻辑: 6379主机 6380/6381当从机
如果主机的中set数据,则从机会实时同步内存数据.
检查节点的状态
info replication

将6380/6381都挂载到6379上
slaveof

测试数据是否同步,检查状态信息

三、Redis 哨兵的原理
前提:redis主从搭建成功之后开始实现哨兵的高可用.
1、 哨兵会定期向主机发送心跳检测(PING-PONG),如果主机连续3次没有返回数据(PONG).哨兵断定主机宕机了.哨兵监听主机的同时,会记录主机的全部的主从状态信息
2、根据选举机制,选择新的主机
3、如果哨兵选举了新的主节点.那么其他节点将动态的修改主从的配置.充当新节点的从机

编辑哨兵的配置文件
将redis根目录下哨兵的配置文件sentinel.conf复制到sentinel下
cp sentinel.conf sentinel/
关闭保护模式,redis的默认条件下,保护模式开开启的.保护模式开启.程序不能远程访问

开启后台启动

修改哨兵的监听

Redis哨兵高可用测试
启动哨兵命令:
redis-sentinel sentinel.conf

将redis主机宕机,30秒之后,检查是否有新的服务器当做主机.
将原有主机再次启动,检查服务器是否为从机!!!!

检测原有服务器:

四、SpringBoot整合哨兵
编辑redis.properties配置文件
redis.sentinel=192.168.126.174:26379
编辑配置类
配置类的核心思想,整合哨兵的配置
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
/**
* 整合redis哨兵
* 创建哨兵的池对象
*/
@Value("${redis.sentinel}")
private String redisSentinel;
@Bean
public JedisSentinelPool jedisSentinelPool() {
Set<String> sentinels = new HashSet<>();
sentinels.add(redisSentinel);
return new JedisSentinelPool("mymaster",sentinels);
}
/**
* 动态获取池中的jedis对象
* 问题说明:如何在方法中,动态获取bean对象
* 知识点说明:
* 1.Spring @Bean注解工作时,如果发现方法有参数列表.则会自动的注入.
* 2.@Qualifier利用名称,实现对象的动态赋值
* sentinelJedis:jedis对象
*/
@Bean
@Scope("prototype")//设置为多例,用户什么时候使用,什么时候创建对象
public Jedis sentinelJedis(JedisSentinelPool jedisSentinelPool) {
//该jedis有高可用的效果.
return jedisSentinelPool.getResource();
}
}
编辑CacheAOP
@Component //将对象交给spring容器管理
@Aspect //自定义切面
public class CacheAOP {
@Autowired//1.按照类型进行注入 2.按照名称匹配
@Qualifier("sentinelJedis") //指定bean的名称进行注入
private Jedis jedis; //从哨兵中获取jedis
@Around("@annotation(cacheFind)")
public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind) {
//调用方法,获取key
String key = getKey(joinPoint, cacheFind);
String value = jedis.get(key);
Object object = null;
try {
if (StringUtils.isEmpty(value)) {
//缓存中没有数据,查询数据库
object = joinPoint.proceed();
String json = ObjectMapperUtil.toJson(object);
//判断是否需要超时设定
if (cacheFind.seconds() > 0) {
jedis.setex(key, cacheFind.seconds(), json);
} else {
//该数据永不超时
jedis.set(key, json);
}
System.out.println("AOP查询数据库!!!");
} else {
//需要动态的获取返回值类型
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Class<?> targetClass = methodSignature.getReturnType();
object = ObjectMapperUtil.toObject(value, targetClass);
System.out.println("AOP查询缓存!!!");
}
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
jedis.close();
return object;
}
//动态获取key
private String getKey(ProceedingJoinPoint joinPoint, CacheFind cacheFind) {
//1.检查用户是否传递key
String key = cacheFind.key();
if (StringUtils.isEmpty(key)) {
//包名.类名.方法名::第一个参数
String className = joinPoint.getSignature().getDeclaringTypeName();
String mothedName = joinPoint.getSignature().getName();
Object arg0 = joinPoint.getArgs()[0];
key = className + "." + mothedName + "::" + arg0;
}
return key;
}
}
修改Service实现类
//@Autowired
private Jedis jedis;
报错说明

哨兵在注入时,需要指定jedis注入的类型.否则可能会产生歧义.如上图所示.
文章详细介绍了Redis分片存在的问题及解决方案,包括在节点宕机时通过3台服务器实现故障迁移和数据同步。接着,它阐述了Redis主从复制的配置步骤,确保数据实时同步。然后,讨论了哨兵的原理和配置,如何在主机宕机后自动选举新主机。最后,展示了如何在SpringBoot中整合哨兵以实现高可用性,以及在实际应用中可能出现的问题和解决策略。

4564

被折叠的 条评论
为什么被折叠?



