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系统监视整个主从集群。

redis搭建哨兵集群模式+整合springboot_第1张图片

2、Sentinel故障转移

当Sentinel系统察觉到Server1主服务器下线时,就会终止server2/3/4的复制。
redis搭建哨兵集群模式+整合springboot_第2张图片

同时Sentinel将server2升级为主服务器,server3/4从新的主服务器进行复制。同时等待server1的再次上线。
redis搭建哨兵集群模式+整合springboot_第3张图片

Sentinel系统也可以主动降级主服务为从服务器,将从服务器升级为主服务器。
redis搭建哨兵集群模式+整合springboot_第4张图片

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 利用文件传输工具将其传出到服务器

redis搭建哨兵集群模式+整合springboot_第5张图片

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

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

启动命令如下:

redis-sentinel sentinel01.conf

redis-sentinel sentinel02.conf

redis-sentinel sentinel03.conf

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

redis搭建哨兵集群模式+整合springboot_第6张图片

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

redis搭建哨兵集群模式+整合springboot_第7张图片

填写主机IP等信息
redis搭建哨兵集群模式+整合springboot_第8张图片

其他两个同理

最后连接效果

redis搭建哨兵集群模式+整合springboot_第9张图片

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

redis搭建哨兵集群模式+整合springboot_第10张图片

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

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

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

4.1 pom依赖


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redisartifactId>
dependency>


<dependency>
    <groupId>redis.clientsgroupId>
    <artifactId>jedisartifactId>
    <version>3.10.0version>
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 , TimeUnit unit) {
		return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key , value , timeout , unit));
	}


	/**
	 * 删除key
	 *
	 * @param key
	 */
	public void delete(String key) {
		redisTemplate.delete(key);
	}

	/**
	 * 批量删除key
	 *
	 * @param keys
	 */
	public void delete(Collection<String> keys) {
		redisTemplate.delete(keys);
	}


	/**
	 * 设置过期时间
	 *
	 * @param key
	 * @param timeout
	 * @param unit
	 * @return
	 */
	public Boolean expire(String key , long timeout , TimeUnit unit) {
		return redisTemplate.expire(key , timeout , unit);
	}

	/**
	 * 设置过期时间
	 *
	 * @param key
	 * @param date
	 * @return
	 */
	public Boolean expireAt(String key , Date date) {
		return redisTemplate.expireAt(key , date);
	}

	/**
	 * 查找匹配的key
	 *
	 * @param pattern
	 * @return
	 */
	public Set<String> keys(String pattern) {
		return redisTemplate.keys(pattern);
	}

	/**
	 * 将当前数据库的 key 移动到给定的数据库 db 当中
	 *
	 * @param key
	 * @param dbIndex
	 * @return
	 */
	public Boolean move(String key , int dbIndex) {
		return redisTemplate.move(key , dbIndex);
	}

	/**
	 * 移除 key 的过期时间,key 将持久保持
	 *
	 * @param key
	 * @return
	 */
	public Boolean persist(String key) {
		return redisTemplate.persist(key);
	}

	/**
	 * 返回 key 的剩余的过期时间
	 *
	 * @param key
	 * @param unit
	 * @return
	 */
	public Long getExpire(String key , TimeUnit unit) {
		return redisTemplate.getExpire(key , unit);
	}

	/**
	 * 从当前数据库中随机返回一个 key
	 *
	 * @return
	 */
	public String randomKey() {
		return redisTemplate.randomKey();
	}

	/**
	 * 修改 key 的名称
	 *
	 * @param oldKey
	 * @param newKey
	 */
	public void rename(String oldKey , String newKey) {
		redisTemplate.rename(oldKey , newKey);
	}

	/**
	 * 仅当 newkey 不存在时,将 oldKey 改名为 newkey
	 *
	 * @param oldKey
	 * @param newKey
	 * @return
	 */
	public Boolean renameIfAbsent(String oldKey , String newKey) {
		return redisTemplate.renameIfAbsent(oldKey , newKey);
	}

	/**
	 * 返回 key 所储存的值的类型
	 *
	 * @param key
	 * @return
	 */
	public DataType type(String key) {
		return redisTemplate.type(key);
	}


	// ============================String=============================

	/**
	 * 普通缓存获取
	 *
	 * @param key 键
	 * @return 值
	 */
	public Object get(String key) {
		return key == null ? null : redisTemplate.opsForValue().get(key);
	}

	/**
	 * 普通缓存放入
	 *
	 * @param key   键
	 * @param value 值
	 * @return true成功 false失败
	 */
	public boolean set(String key , Object value) {
		try {
			redisTemplate.opsForValue().set(key , value);
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * 普通缓存放入并设置时间
	 *
	 * @param key   键
	 * @param value 值
	 * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
	 * @return true成功 false 失败
	 */
	public boolean set(String key , Object value , long time) {
		try {
			if (time > 0) {
				redisTemplate.opsForValue().set(key , value , time , TimeUnit.SECONDS);
			} else {
				set(key , value);
			}
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 递增
	 *
	 * @param key   键
	 * @param delta 要增加几(大于0)
	 * @return
	 */
	public long incr(String key , long delta) {
		if (delta < 0) {
			throw new RuntimeException("递增因子必须大于0");
		}
		return redisTemplate.opsForValue().increment(key , delta);
	}

	/**
	 * 递减
	 *
	 * @param key   键
	 * @param delta 要减少几(小于0)
	 * @return
	 */
	public long decr(String key , long delta) {
		if (delta < 0) {
			throw new RuntimeException("递减因子必须大于0");
		}
		return redisTemplate.opsForValue().increment(key , -delta);
	}

	// ================================Map=================================

	/**
	 * HashGet
	 *
	 * @param key  键 不能为null
	 * @param item 项 不能为null
	 * @return 值
	 */
	public Object hget(String key , String item) {
		return redisTemplate.opsForHash().get(key , item);
	}

	/**
	 * 获取hashKey对应的所有键值
	 *
	 * @param key 键
	 * @return 对应的多个键值
	 */
	public Map<Object, Object> hmget(String key) {
		return redisTemplate.opsForHash().entries(key);
	}

	/**
	 * HashSet
	 *
	 * @param key 键
	 * @param map 对应多个键值
	 * @return true 成功 false 失败
	 */
	public boolean hmset(String key , Map<String, Object> map) {
		try {
			redisTemplate.opsForHash().putAll(key , map);
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * HashSet 并设置时间
	 *
	 * @param key  键
	 * @param map  对应多个键值
	 * @param time 时间(秒)
	 * @return true成功 false失败
	 */
	public boolean hmset(String key , Map<String, Object> map , long time) {
		try {
			redisTemplate.opsForHash().putAll(key , map);
			if (time > 0) {
				expire(key , time);
			}
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 向一张hash表中放入数据,如果不存在将创建
	 *
	 * @param key   键
	 * @param item  项
	 * @param value 值
	 * @return true 成功 false失败
	 */
	public boolean hset(String key , String item , Object value) {
		try {
			redisTemplate.opsForHash().put(key , item , value);
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 向一张hash表中放入数据,如果不存在将创建
	 *
	 * @param key   键
	 * @param item  项
	 * @param value 值
	 * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
	 * @return true 成功 false失败
	 */
	public boolean hset(String key , String item , Object value , long time) {
		try {
			redisTemplate.opsForHash().put(key , item , value);
			if (time > 0) {
				expire(key , time);
			}
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 删除hash表中的值
	 *
	 * @param key  键 不能为null
	 * @param item 项 可以使多个 不能为null
	 */
	public void hdel(String key , Object... item) {
		redisTemplate.opsForHash().delete(key , item);
	}

	/**
	 * 判断hash表中是否有该项的值
	 *
	 * @param key  键 不能为null
	 * @param item 项 不能为null
	 * @return true 存在 false不存在
	 */
	public boolean hHasKey(String key , String item) {
		return redisTemplate.opsForHash().hasKey(key , item);
	}

	/**
	 * hash递增 如果不存在,就会创建一个 并把新增后的值返回
	 *
	 * @param key  键
	 * @param item 项
	 * @param by   要增加几(大于0)
	 * @return
	 */
	public double hincr(String key , String item , double by) {
		return redisTemplate.opsForHash().increment(key , item , by);
	}

	/**
	 * hash递减
	 *
	 * @param key  键
	 * @param item 项
	 * @param by   要减少记(小于0)
	 * @return
	 */
	public double hdecr(String key , String item , double by) {
		return redisTemplate.opsForHash().increment(key , item , -by);
	}

	// ============================set=============================

	/**
	 * 根据key获取Set中的所有值
	 *
	 * @param key 键
	 * @return
	 */
	public Set<Object> sGet(String key) {
		try {
			return redisTemplate.opsForSet().members(key);
		} catch ( Exception e ) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 根据value从一个set中查询,是否存在
	 *
	 * @param key   键
	 * @param value 值
	 * @return true 存在 false不存在
	 */
	public boolean sHasKey(String key , Object value) {
		try {
			return redisTemplate.opsForSet().isMember(key , value);
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 将数据放入set缓存
	 *
	 * @param key    键
	 * @param values 值 可以是多个
	 * @return 成功个数
	 */
	public long sSet(String key , Object... values) {
		try {
			return redisTemplate.opsForSet().add(key , values);
		} catch ( Exception e ) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 将set数据放入缓存
	 *
	 * @param key    键
	 * @param time   时间(秒)
	 * @param values 值 可以是多个
	 * @return 成功个数
	 */
	public long sSetAndTime(String key , long time , Object... values) {
		try {
			Long count = redisTemplate.opsForSet().add(key , values);
			if (time > 0) {
				expire(key , time);
			}
			return count;
		} catch ( Exception e ) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 获取set缓存的长度
	 *
	 * @param key 键
	 * @return
	 */
	public long sGetSetSize(String key) {
		try {
			return redisTemplate.opsForSet().size(key);
		} catch ( Exception e ) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 移除值为value的
	 *
	 * @param key    键
	 * @param values 值 可以是多个
	 * @return 移除的个数
	 */
	public long setRemove(String key , Object... values) {
		try {
			Long count = redisTemplate.opsForSet().remove(key , values);
			return count;
		} catch ( Exception e ) {
			e.printStackTrace();
			return 0;
		}
	}
	// ===============================list=================================

	/**
	 * 获取list缓存的内容
	 *
	 * @param key   键
	 * @param start 开始
	 * @param end   结束 0 到 -1代表所有值
	 * @return
	 */
	public List<Object> lGet(String key , long start , long end) {
		try {
			return redisTemplate.opsForList().range(key , start , end);
		} catch ( Exception e ) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取list缓存的长度
	 *
	 * @param key 键
	 * @return
	 */
	public long lGetListSize(String key) {
		try {
			return redisTemplate.opsForList().size(key);
		} catch ( Exception e ) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 通过索引 获取list中的值
	 *
	 * @param key   键
	 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
	 * @return
	 */
	public Object lGetIndex(String key , long index) {
		try {
			return redisTemplate.opsForList().index(key , index);
		} catch ( Exception e ) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 将list放入缓存
	 *
	 * @param key   键
	 * @param value 值
	 * @return
	 */
	public boolean lSet(String key , Object value) {
		try {
			redisTemplate.opsForList().rightPush(key , value);
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 将list放入缓存
	 *
	 * @param key   键
	 * @param value 值
	 * @param time  时间(秒)
	 * @return
	 */
	public boolean lSet(String key , Object value , long time) {
		try {
			redisTemplate.opsForList().rightPush(key , value);
			if (time > 0) {
				expire(key , time);
			}
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 将list放入缓存
	 *
	 * @param key   键
	 * @param value 值
	 * @return
	 */
	public boolean lSet(String key , List<Object> value) {
		try {
			redisTemplate.opsForList().rightPushAll(key , value);
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 将list放入缓存
	 *
	 * @param key   键
	 * @param value 值
	 * @param time  时间(秒)
	 * @return
	 */
	public boolean lSet(String key , List<Object> value , long time) {
		try {
			redisTemplate.opsForList().rightPushAll(key , value);
			if (time > 0) {
				expire(key , time);
			}
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 根据索引修改list中的某条数据
	 *
	 * @param key   键
	 * @param index 索引
	 * @param value 值
	 * @return
	 */
	public boolean lUpdateIndex(String key , long index , Object value) {
		try {
			redisTemplate.opsForList().set(key , index , value);
			return true;
		} catch ( Exception e ) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 移除N个值为value
	 *
	 * @param key   键
	 * @param count 移除多少个
	 * @param value 值
	 * @return 移除的个数
	 */
	public long lRemove(String key , long count , Object value) {
		try {
			Long remove = redisTemplate.opsForList().remove(key , count , value);
			return remove;
		} catch ( Exception e ) {
			e.printStackTrace();
			return 0;
		}
	}
	// ============================= zSet相关操作 =============================

	/**
	 * 添加元素,有序集合是按照元素的score值由小到大排列
	 *
	 * @param key
	 * @param value
	 * @param score
	 * @return
	 */
	public Boolean zAdd(String key , String value , double score) {
		return redisTemplate.opsForZSet().add(key , value , score);
	}

	/**
	 * 有序set添加元素 不存在就添加
	 *
	 * @param key
	 * @param value
	 * @param score
	 * @return
	 */
	public boolean zAddIf(String key , Object value , double score) {
		return redisTemplate.opsForZSet().addIfAbsent(key , value , score);
	}


	/**
	 * @param key
	 * @param values
	 * @return
	 */
	public Long zRemove(String key , Object... values) {
		return redisTemplate.opsForZSet().remove(key , values);
	}

	/**
	 * 为指定的key加上指定的分数,并返回增加后的值
	 *
	 * @param key
	 * @param value
	 * @param delta
	 * @return
	 */
	public Double zIncrementScore(String key , String value , double delta) {
		return redisTemplate.opsForZSet().incrementScore(key , value , delta);
	}

	/**
	 * 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列
	 *
	 * @param key
	 * @param value
	 * @return 0表示第一位
	 */
	public Long zRank(String key , Object value) {
		return redisTemplate.opsForZSet().rank(key , value);
	}

	/**
	 * 取出指定范围的元素 按下标  降序 按分数从高到低
	 *
	 * @param key
	 * @param value
	 * @return
	 */
	public Long zReverseRank(String key , Object value) {
		return redisTemplate.opsForZSet().reverseRank(key , value);
	}

	/**
	 * 获取集合的元素, 从小到大排序
	 *
	 * @param key
	 * @param start 开始位置
	 * @param end   结束位置, -1查询所有
	 * @return
	 */
	public Set<Object> zRange(String key , long start , long end) {
		return redisTemplate.opsForZSet().range(key , start , end);
	}


	/**
	 * 根据Score值查询集合元素
	 *
	 * @param key
	 * @param min 最小值
	 * @param max 最大值
	 * @return
	 */
	public Set<Object> zRangeByScore(String key , double min , double max) {
		return redisTemplate.opsForZSet().rangeByScore(key , min , max);
	}


	/**
	 * 获取集合的元素, 从大到小排序
	 *
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	public Set<Object> zReverseRange(String key , long start , long end) {
		return redisTemplate.opsForZSet().reverseRange(key , start , end);
	}


	/**
	 * 获取集合大小
	 *
	 * @param key
	 * @return
	 */
	public Long zZCard(String key) {
		return redisTemplate.opsForZSet().zCard(key);
	}

	/**
	 * 查询指定key中某成员的分数
	 *
	 * @param key
	 * @param item
	 * @return
	 */
	public int zScore(String key , Object item) {
		int score = 0;
		try {
			score = redisTemplate.opsForZSet().score(key , item).intValue();
		} catch ( Exception ex ) {
		}
		return score;
	}

	/**
	 * 移除指定索引位置的成员
	 *
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	public Long zRemoveRange(String key , long start , long end) {
		return redisTemplate.opsForZSet().removeRange(key , start , end);
	}

	/**
	 * 根据指定的score值的范围来移除成员
	 *
	 * @param key
	 * @param min
	 * @param max
	 * @return
	 */
	public Long zRemoveRangeByScore(String key , double min , double max) {
		return redisTemplate.opsForZSet().removeRangeByScore(key , min , max);
	}


}

4.5 test测试包下的RedisTest测试类

import com.cy.springbootredissentinel.SpringbootRedisSentinelApplication;
import com.cy.springbootredissentinel.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

/**
 * RedisTest
 *
 * @author wxhn1
 * @since 2024-01-15 12:04
 */
@SpringBootTest(classes = SpringbootRedisSentinelApplication.class)
@Slf4j
public class RedisTest {
	
	@Resource
	RedisUtil redisUtil;
	
	
	@Test
	public void test() {
	
		redisUtil.set("keyTest", "valueTest");
		
		System.out.println("redisUtil = " + redisUtil.get("keyTest"));
	
	}
	
	
}

单元测试效果:

redis搭建哨兵集群模式+整合springboot_第11张图片

像redis添加了一个keyTest键的valueTest值,查看主库从库效果:
redis搭建哨兵集群模式+整合springboot_第12张图片
redis搭建哨兵集群模式+整合springboot_第13张图片
redis搭建哨兵集群模式+整合springboot_第14张图片

5. 正式测试哨兵模式

这时我们先把主库服务给停了,就是redis6380.conf配置启动的这个服务

redis搭建哨兵集群模式+整合springboot_第15张图片
redis搭建哨兵集群模式+整合springboot_第16张图片

使用哨兵模式的一个**注意点:假设启动了三个redis服务,如果主库挂了,那么根据哨兵原则,它会在剩余的两个从库中选一个做为主库,这时从库的配置文件会有所更改**。如若之前挂了的主库重新上线也只就只能充当从库了

OK !!! 收尾!!!

若有误区或不能解决,私信我,远程协助你!!!

你可能感兴趣的:(SpringBoot,Redis,redis,spring,boot)