redis搭建哨兵集群模式+整合springboot

1. 基本介绍

Sentinel 哨兵模式

  • Sentinel 哨兵模式是为了弥补主从复制集群中主机宕机后,主备切换的复杂性而演变出来的。哨兵顾名思义,就是用来监控的,主要作用就是监控主从集群,自动切换主备,完成集群故障转移。

Sentinel 哨兵Sentinel 哨兵介绍
​ Sentinel 哨兵本质上是一个运行在特殊模式下的Redis实例,只是初始化的过程和工作与普通的 Redis不同,本质上也是一个单独的进程。
​ Sentinel 哨兵 是Redis的高可用解决方案:一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在主服务器下线时可以自动切换从服务器升级为主服务器。

1、Sentinel系统

下图是一个简单的Sentinel系统架构图,一个Sentinel系统监视一个主从集群,其中server1是Redis主服务器,server2/3/4是Redis 从服务器。主从之间利用上面的主从复制来达到主从一致。而Sentinel系统监视整个主从集群。

在这里插入图片描述

2、Sentinel故障转移

当Sentinel系统察觉到Server1主服务器下线时,就会终止server2/3/4的复制。
在这里插入图片描述

同时Sentinel将server2升级为主服务器,server3/4从新的主服务器进行复制。同时等待server1的再次上线。
在这里插入图片描述

Sentinel系统也可以主动降级主服务为从服务器,将从服务器升级为主服务器。
在这里插入图片描述

Sentinel 哨兵监控过程

Sentinel 哨兵监控集群过程:

  • 命令 Sentinel哨兵通过发送命令,让redis服务器返回运行状态。发布订阅 当主服务器状态发生变化时,Sentinel哨兵通过
  • 发布订阅模式通知其他从服务器。
Sentinel 哨兵故障转移

Sentinel 故障转移:

  • 1、Sentinel系统中的Sentinel实例每隔1s就像集群发送PING命令
  • 2、如果集群中有实例的回复Sentinel实例时间超过了 down-after-milliseconds,那么这个实例就会发送PING命令的Sentinel实例被主观下线
  • 3、那么什么时候会客观下线呢?需要Sentinel系统中其他实例也确认集群中该实例主管下线。
  • 如果master主服务器被标记为主观下线,则Sentinel系统中监视master的Sentinel进程需要以每秒一次的频率确认Master是否进入主管下线状态
  • 4、当有足够的Sentinel实例(取决于配置)确认Master进入了主管下线,则Master会被标记为客观下线。
Sentinel 哨兵优缺点

优点:

1、哨兵模式基于主从复制,因此主从复制的优点哨兵都具备

2、哨兵具备了主从切换和故障转移,因此集群有了更高的可用性

缺点:

1、Redis较难支持在线扩容,在线扩容比较复杂。

总结:
sentinel 哨兵主要用来监控redis主从集群,提高了redis 主从集群的可用性。

2. 引导

建议先参考主从模式搭建教程:

Sentinel模式是基于主从模式的嘛,因此要实现Sentinel集群模式的简单搭建需要提前做好主从集群模式的搭建。

想尝试主从怎么搭建的参考上一篇博客:

http://t.csdnimg.cn/emWe0

注意点:注意点:注意点:

**【必须】**参考主从只需参考centos下的redis.conf配置文件那里即可,让三个redis服务跑起来就ok了,其他的无需参考,主从归主从,哨兵归哨兵嘛。

通俗点:从标题1看到标题5即可

3. 基本使用(基于Linux的centos系统) (window下的操作也差不多)

3.1在你的windows下准备三个sentinel的配置文件

sentinel01.conf sentinel02.conf sentinel03.conf

sentinel01.conf

bind 0.0.0.0
port 1001
sentinel announce-ip "192.168.6.128"
# 后面的2  表示有2个哨兵认为主库挂了就是客观下线
# 就会开始选举
# 5000 表示每5秒钟检测一次主库是否挂掉
sentinel monitor mymaster 192.168.6.128 6380 2
sentinel failover-timeout mymaster 5000

# linux中 解除redis保护 允许外部连接
protected-mode no
# 后台访问
daemonize yes

sentinel02.conf

bind 0.0.0.0
port 1002
sentinel announce-ip "192.168.6.128"
# 后面的2  表示有2个哨兵认为主库挂了就是客观下线
# 就会开始选举
# 5000 表示每5秒钟检测一次主库是否挂掉
sentinel monitor mymaster 192.168.6.128 6380 2
sentinel failover-timeout mymaster 5000

# linux中 解除redis保护 允许外部连接
protected-mode no
# 后台访问
daemonize yes

sentinel03.conf

bind 0.0.0.0
port 1003
sentinel announce-ip "192.168.6.128"
# 后面的2  表示有2个哨兵认为主库挂了就是客观下线
# 就会开始选举
# 5000 表示每5秒钟检测一次主库是否挂掉
sentinel monitor mymaster 192.168.6.128 6380 2
sentinel failover-timeout mymaster 5000

# linux中 解除redis保护 允许外部连接
protected-mode no
# 后台访问
daemonize yes

3.2 利用文件传输工具将其传出到服务器

在这里插入图片描述

3.3. 上传完之后启动这三个哨兵配置

前提:redis主从配置的三个服务必须开启

启动命令如下:

redis-sentinel sentinel01.conf

redis-sentinel sentinel02.conf

redis-sentinel sentinel03.conf

# 查看redis进程
ps -ef|grep redis|grep -v grep

在这里插入图片描述

3.4 redis连接工具进行连接 【工具安装就略过了蛤】

在这里插入图片描述

填写主机IP等信息
在这里插入图片描述

其他两个同理

最后连接效果

在这里插入图片描述

这时切换到主库往下滑找到role这一行,

在这里插入图片描述

此效果证明主从配置搭建没问题

4. redis哨兵模式整合springboot简单的单元测试

gitee代码测试地址:https://gitee.com/crqyue/springboot-redis-sentinel.git

4.1 pom依赖

<!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.10.0</version>
</dependency>

4.2 yaml配置redis连接

spring:
  datasource: # oracle数据库连接 - 可以切换为自己的数据库
    driver-class-name: oracle.jdbc.driver.OracleDriver
    url: jdbc:oracle:thin:@localhost:1521:orcl
    username: oa
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
  redis: # redis哨兵配置
    sentinel:
      master: mymaster
      nodes: 192.168.6.128:1001,192.168.6.128:1002,192.168.6.128:1003
mybatis-plus:
  type-aliases-package: com.cy.entity

4.3 config包下的RedisConfig类

@Configuration
public class RedisConfig {
   
   

	@Bean
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
   
   
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

		redisTemplate.setConnectionFactory(connectionFactory); // 启动时注入连接对象

		StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // 设置序列化器
		GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

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

		redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
		redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);

		return redisTemplate;  // 返回模板对象
	}

}

4.4 util包下的RedisUtil类

@Component
public class RedisUtil {
   
   

	@Resource
	private RedisTemplate<String, Object> redisTemplate;

	/**
	 * 指定缓存失效时间
	 *
	 * @param key  键
	 * @param time 时间(秒)
	 * @return
	 */
	public boolean expire(String key , long time) {
   
   
		try {
   
   
			if (time > 0) {
   
   
				redisTemplate.expire(key , time , TimeUnit.SECONDS);
			}
			return true;
		} catch ( Exception e ) {
   
   
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 根据key 获取过期时间
	 *
	 * @param key 键 不能为null
	 * @return 时间(秒) 返回0代表为永久有效
	 */
	public long getExpire(String key) {
   
   
		return redisTemplate.getExpire(key , TimeUnit.SECONDS);
	}

	/**
	 * 判断key是否存在
	 *
	 * @param key 键
	 * @return true 存在 false不存在
	 */
	public boolean hasKey(String key) {
   
   
		try {
   
   
			return redisTemplate.hasKey(key);
		} catch ( Exception e ) {
   
   
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 删除缓存
	 *
	 * @param key 可以传一个值 或多个
	 */
	public void del(String... key) {
   
   
		if (key != null && key.length > 0) {
   
   
			if (key.length == 1) {
   
   
				redisTemplate.delete(key[0]);
			} else {
   
   
				redisTemplate.delete(Arrays.asList(key));
			}
		}
	}


	// ============================= key相关操作 =============================


	/**
	 * 可以实现分布式锁
	 *
	 * @param key
	 * @param value
	 * @return key存在则返回false,不存在则存储key-value并返回true
	 */
	public boolean setnx(String key , String value) {
   
   
		return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key , value));
	}

	/**
	 * 可以实现分布式锁
	 *
	 * @param key
	 * @param value
	 * @param timeout
	 * @param unit
	 * @return key存在则返回false,不存在则存储key-value并返回true
	 */
	public boolean setnx(String key , String value , long timeout
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值