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

这篇具有很好参考价值的文章主要介绍了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,SpringBoot,Redis,redis,spring boot

2、Sentinel故障转移

当Sentinel系统察觉到Server1主服务器下线时,就会终止server2/3/4的复制。
redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot

同时Sentinel将server2升级为主服务器,server3/4从新的主服务器进行复制。同时等待server1的再次上线。
redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot

Sentinel系统也可以主动降级主服务为从服务器,将从服务器升级为主服务器。
redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot

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集群模式的简单搭建需要提前做好主从集群模式的搭建。

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

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

**【必须】**参考主从只需参考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,SpringBoot,Redis,redis,spring boot

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,SpringBoot,Redis,redis,spring boot

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

redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot

填写主机IP等信息
redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot

其他两个同理

最后连接效果

redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot

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

redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot

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

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 , 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,SpringBoot,Redis,redis,spring boot

像redis添加了一个keyTest键的valueTest值,查看主库从库效果:
redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot
redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot
redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot

5. 正式测试哨兵模式

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

redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot
redis搭建哨兵集群模式+整合springboot,SpringBoot,Redis,redis,spring boot

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

OK !!! 收尾!!!

若有误区或不能解决,私信我,远程协助你!!!文章来源地址https://www.toymoban.com/news/detail-804851.html

到了这里,关于redis搭建哨兵集群模式+整合springboot的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis哨兵集群搭建及RedisTemplate的哨兵模式配置详解

    本文详细介绍了Redis哨兵集群的原理、架构和工作流程,包括哨兵的功能作用、故障恢复机制、选举新的master等内容。同时,提供了哨兵集群架构示意图和实例准备、配置、启动、测试的步骤。此外,还介绍了如何在Spring的RedisTemplate中配置哨兵模式,实现Redis主从集群的自动切换和节点感知。

    2024年02月14日
    浏览(44)
  • SpringBoot Redis入门(四)——Redis单机、哨兵、集群模式

    单机模式:单台缓存服务器,开发、测试环境下使用; 哨兵模式:主-从模式,提高缓存服务器的 高可用 和 安全性 。所有缓存的数据在每个节点上都一致。每个节点添加监听器,不断监听节点可用状态,一旦主节点不能再提供服务。各监听器会立即在“从节点“中投票选择

    2024年01月20日
    浏览(39)
  • Linux Redis主从复制 | 哨兵监控模式 | 集群搭建 | 超详细

    4.1 环境部署 4.2 安装Redis(主从服务器) 4.3 修改Master节点Redis配置文件 (192.168.163.100) 4.4 修改Slave节点Redis配置文件 (192.168.163.110 192.168.163.120) 4.5 验证结果 5.1 哨兵模式的原理 5.2 哨兵模式的作用 5.3哨兵模式的结构 哨兵结构由两部分组成, 哨兵节点 和 数据节点 : 哨兵节点:

    2023年04月14日
    浏览(43)
  • SpringBoot Redis 多数据源集成支持哨兵模式和Cluster集群模式

    大家都知道Redis在6.0版本之前是单线程工作的,这导致在一个项目中有大量读写操作的情况下,Redis单实例的性能被其他业务长时间占据,导致部分业务出现延迟现象,为了解决这个问题,部分公司项目选择使用多个Redis实例分别存储不同的业务数据和使用场景,比如IoT网关写

    2024年02月15日
    浏览(40)
  • Redis 主从配置、哨兵、集群模式

    目录 Redis 主从复制  主从复制的作用: 主从复制流程: 搭建Redis 主从复制 安装 Redis 环境准备 修改内核参数 安装redis 创建redis工作目录 环境变量 定义systemd服务管理脚本 修改 Redis 配置文件(Master节点操作) 修改 Redis 配置文件(Slave节点操作) 验证主从效果 Redis 哨兵模式

    2024年02月12日
    浏览(56)
  • Redis三种模式——主从复制,哨兵模式,集群

    目录 一、主从复制  1.1主从复制的概念   1.2Redis主从复制作用  1.2.1数据冗余  1.2.2故障恢复   1.2.3负载均衡  1.2.4高可用基石  1.3Redis主从复制流程    1.4部署Redis 主从复制 1.4.1.环境部署  1.4.2.所有服务器都先关闭防火墙  1.4.3.所有服务器都安装Redis  1.4.4修改Master主节点

    2024年02月14日
    浏览(37)
  • Redis单机,主从,哨兵,集群四大模式

    Redis 单机模式是指 Redis 数据库在单个服务器上以独立的、单一的进程运行的模式。在这种模式下,Redis 不涉及数据分片或集群配置,所有的数据和操作都在一个实例中进行。以下是关于 Redis 单机模式的详细介绍: 单一实例: 在 Redis 单机模式中,只有一个 Redis 实例在一个服

    2024年02月13日
    浏览(41)
  • 搭建Redis主从集群和哨兵

    说明:单机的Redis存在许多的问题,如数据丢失问题、高并发问题、故障恢复问题、海量数据的存储能力问题,针对这四个问题,对应解决方式有:数据持久化(参考:http://t.csdn.cn/SSyBi)、搭建主从集群、Redis哨兵和搭建分片集群; 本文介绍搭建Redis主从集群和哨兵,用以解

    2024年02月16日
    浏览(36)
  • Redis 主从复制 + 哨兵模式 + Cluster 集群

    redis群集有三种模式: 分别是主从同步/复制、哨兵模式、Cluster,下面会讲解一下三种模式的工作方式,以及如何搭建cluster群集 主从复制是高可用Redis的基础,哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡

    2024年02月09日
    浏览(38)
  • redis复制和分区:主从复制、哨兵模式和集群模式

    在 Redis 中,复制和分区是用于数据冗余和性能扩展的关键特性。以下是主从复制、哨兵模式和集群模式的工作原理的简要概述: 主从复制 (Replication) 基本概念 :Redis 的主从复制功能允许多个 Redis 服务器具有相同的数据副本。这在读取操作的负载均衡、数据备份、灾难恢复等

    2024年01月20日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包