Redis哨兵

admin 2个月前 (07-22) 科技 42 0

博主之前写了一篇Redis哨兵搭建,并没有对哨兵举行解说,本篇填坑。

同时,也为博主写Redis分布式锁(二)做一些前置知识。

挖坑位置:Redis集群搭建(哨兵)

Redis主从

在讲redis哨兵前,需要先简朴解说一下redis主从。

俗话说,鸡蛋放在一个篮子里容易碎,那就把鸡蛋复制一份,放到其他篮子里。所有的高可用基本都是这个思绪。

上一篇文章讲主从设置的时刻,讲到一个设置属性slaveof

# 这个设置是redis-1中没有的,需要在redis-2中新增
# 这里的IP是redis-1的IP地址,端口是redis-1 6379.conf设置文件中port的值,默认值是6379
slaveof 1.1.1.1 6379

这个属性就是设置redis主从的。

这里剖析以下上面这张图,可以发现以下几个特点

  • 客户端可以从三个redis中读取数据
  • 只有主库可以写入数据(负疚,这个没有在图中体现)
  • 两个从库从主库中读取数据

这种redis架构解决了以下问题

  • 主库宕机,仍然可以在从库中读取数据,一定程度上提高了可用性
  • 若是三个redis运行正常,数据应该一致
  • 读取的压力分管到了3个节点上

存在以下几个问题

  • 主库宕机,不能写入
  • 主库不能自动切换,需要手动切换
  • ※主库写入数据乐成,还没来得及同步到从库,主库宕机

基于以上的一些问题,我们引出了redis哨兵

Redis哨兵

主从中存在一些问题是我们不能接受的,好比,主库宕机=无法写入。我们固然期望,宕机一个节点的时刻,仍然可以对外服务,这才是高可用嘛~

哨兵

如果不能自动切换主库,我们该怎么做呢?运维童鞋,先不管主库了(已经宕机了),在从库中选择一个作为新的主库启动,优先提供服务嘛~至于主库,稍后再剖析宕机缘故原由,解决问题。

本着软件能解决的问题,就不使用人力,我们可不可以下一个软件,来取代运维童鞋的这些操作?

这个就是哨兵的功效雏形了。

哨兵监视主从redis,一旦redis主库宕机,哨兵切换主库,客户端再写入数据的时刻,向新的主库中写入。在切换的时刻,给运维童鞋一条通知,运维童鞋再处置。是不是很6?

优化

从上面可以看出,我们只有一个哨兵,若是这个哨兵宕机了,那我们的保障就没有了。

我们可以把哨兵也集群起来,优化结构如下:

剖析

你可以把哨兵理解为zookeeper或者是eureka,哨兵相当于一个注册中央(固然不仅仅是注册中央的功效),客户端也从哨兵读取redis主从库信息。三个哨兵组成了一个集群的注册中央,当有一个哨兵宕机,另有其他哨兵存活,依然可以服务。

这样哨兵Sentinel也集群起来了,redis也有主从,我们这个时刻可以说,提供了一套高可用的redis。

但这样的架构并不是绝对完善的,仍然存在一些问题。

依旧不能解决主从中的一个问题“主库写入数据乐成,还没来得及同步到从库,主库宕机”。

例如主库上写入了一把锁,还没来得及把锁的信息同步到从库,主库挂了,从库切换为了主库,然而这个新的主库上并没有锁。引起了锁失效。

若何解决呢?

  • 手动调整数据吧,少年。

  • 若是是锁的场景,可以用zookeeper来取代redis分布式锁来解决。

哨兵客户端实现

博主使用的springboot来演示,使用工具包lettuce

依赖

<!-- data-redis中集成了lettuce -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis链接池 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<!-- alibaba json -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.72</version>
</dependency>

设置文件

server:
  port: 80
spring:
  redis:
    password: 密码
    sentinel:
      # 这个设置在 哨兵设置文件中
      master: 你的集群名称
      # 26379 端口是哨兵的默认端口
      nodes: 10.101.36.19:26379,10.101.36.20:26379,10.101.36.21:26379
    lettuce:
      pool:
        # 最大链接数
        max-active: 30
        # 链接池中最大空闲链接数
        max-idle: 15
        # 最大壅闭守候链接时长 默认不限制 -1
        max-wait: 2000
        # 最小空闲链接数
        min-idle: 10
      # 链接超时时长
      shutdown-timeout: 10000

Redis 设置类

import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * redis 设置类 将RedisTemplate交给spring托管
 */
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        GenericFastJsonRedisSerializer genericFastJsonRedisSerializer = new GenericFastJsonRedisSerializer();

        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(genericFastJsonRedisSerializer);

        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(genericFastJsonRedisSerializer);

        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }
}

测试类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("test")
public class TestController {

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping
    public String Test(){
        redisTemplate.opsForValue().set("xujp", "sentinel");
        String rst = (String) redisTemplate.opsForValue().get("xujp");
        return rst;
    }

}

测试

postman直接get请求即可

在redis毗邻工具中查看

主库:

从库:

这个时刻把主库手动关闭

查看哨兵日志

可以看到主节点已切换完成

26721:X 20 Jul 2020 15:08:40.941 # +switch-master mymaster 10.101.36.20 6379 10.101.36.19 6379

这时刻,在postman中再次发送请求

请求乐成。

有兴趣的童鞋可以再测试一下内容:

  • 在切换间隙实验获取redis数据
  • kill掉一个sentinel,再kill掉主库,查看主库切换

这里博主再挖一坑,redis哨兵模式切换主库的时刻,若何通知运维职员呢?

总结

本文挖坑:

  • redis哨兵模式切换主库的时刻,若何通知运维职员呢?
,

欧博亚洲手机版下载

欢迎进入欧博亚洲手机版下载(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。

Sunbet声明:该文看法仅代表作者自己,与本平台无关。转载请注明:Redis哨兵

标签列表

    文章归档

      站点信息

      • 文章总数:465
      • 页面总数:0
      • 分类总数:8
      • 标签总数:804
      • 评论总数:0
      • 浏览总数:13467