spring实战4 spring整合redis哨兵

太过爱你忘了你带给我的痛 2022-05-18 00:55 259阅读 0赞

前言

  1. 对spring整合redis单例感兴趣的朋友,请移步此处 spring实战3 spring整合单例redis
  2. 对springboot整合单例redis感兴趣的朋友,请移步此处 SpringBoot实战之13 整合redis

开始

建项目

新建spring-redis-sentinel web项目

导包

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-test</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.data</groupId>
  7. <artifactId>spring-data-redis</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>redis.clients</groupId>
  11. <artifactId>jedis</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>com.fasterxml.jackson.core</groupId>
  15. <artifactId>jackson-databind</artifactId>
  16. </dependency>
  17. <!--自己封装的增删改查包-->
  18. <dependency>
  19. <groupId>com.hsy.java</groupId>
  20. <artifactId>java-util</artifactId>
  21. </dependency>

配置文件

新建redis.properties

  1. #访问地址 redis中心
  2. redis.host=172.16.191.102
  3. # redis.host=192.168.1.106
  4. #访问端口
  5. redis.port=6379
  6. #授权密码,有没有这一项取决于要连接的redis服务是否设置了此项
  7. redis.auth=123456
  8. redis.dbIndex=0
  9. redis.timeout=100000
  10. # redis哨兵信息
  11. redis.sentinel.node1.host=172.16.191.102
  12. redis.sentinel.node1.port=26379
  13. redis.sentinel.node2.host=172.16.191.102
  14. redis.sentinel.node2.port=26380
  15. redis.sentinel.node3.host=172.16.191.102
  16. redis.sentinel.node3.port=26381
  17. redis.pool.maxTotal=200
  18. #连接池的最大数据库连接数。设为0表示无限制
  19. redis.pool.maxIdle=1024
  20. redis.pool.minIdle=8
  21. #在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
  22. redis.pool.testOnCreate=true
  23. redis.pool.testOnBorrow=true
  24. redis.pool.testOnReturn=true
  25. #Idle时进行连接扫描
  26. redis.pool.testWhileIdle=true
  27. redis.pool.maxWaitMillis=100000
  28. #表示idle object evitor两次扫描之间要sleep的毫秒数
  29. redis.pool.timeBetweenEvictionRunsMillis=30000
  30. #表示idle object evitor每次扫描的最多的对象数
  31. redis.pool.numTestsPerEvictionRun=10
  32. #表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;
  33. # 这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
  34. redis.pool.minEvictableIdleTimeMillis=60000

新建spring配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">
  3. <context:property-placeholder location="classpath:config/redis.properties" ignore-resource-not-found="true"/>
  4. <!--<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:properties/redis.properties</value> </list> </property> </bean>-->
  5. <!-- redis config start -->
  6. <!-- 配置JedisPoolConfig实例 -->
  7. <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
  8. <property name="maxTotal" value="${redis.pool.maxTotal}"/>
  9. <property name="maxIdle" value="${redis.pool.maxIdle}"/>
  10. <property name="minIdle" value="${redis.pool.minIdle}"/>
  11. <property name="testOnCreate" value="${redis.pool.testOnCreate}"/>
  12. <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
  13. <property name="testOnReturn" value="${redis.pool.testOnReturn}"/>
  14. <property name="testWhileIdle" value="${redis.pool.testWhileIdle}"/>
  15. <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"/>
  16. <property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}"/>
  17. <property name="numTestsPerEvictionRun" value="${redis.pool.numTestsPerEvictionRun}"/>
  18. <property name="minEvictableIdleTimeMillis" value="${redis.pool.minEvictableIdleTimeMillis}"/>
  19. </bean>
  20. <!-- 配置JedisConnectionFactory -->
  21. <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
  22. <property name="hostName" value="${redis.host}"/>
  23. <property name="port" value="${redis.port}"/>
  24. <property name="password" value="${redis.auth}"/>
  25. <property name="database" value="${redis.dbIndex}"/>
  26. <property name="timeout" value="${redis.timeout}"/>
  27. <property name="poolConfig" ref="poolConfig"/>
  28. </bean>
  29. <bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
  30. <property name="sentinels">
  31. <set>
  32. <bean name="sentinelNode1" class="org.springframework.data.redis.connection.RedisNode">
  33. <constructor-arg name="host" value="${redis.sentinel.node1.host}"/>
  34. <constructor-arg name="port" value="${redis.sentinel.node1.port}"/>
  35. </bean>
  36. <bean name="sentinelNode2" class="org.springframework.data.redis.connection.RedisNode">
  37. <constructor-arg name="host" value="${redis.sentinel.node2.host}"/>
  38. <constructor-arg name="port" value="${redis.sentinel.node2.port}"/>
  39. </bean>
  40. <bean name="sentinelNode3" class="org.springframework.data.redis.connection.RedisNode">
  41. <constructor-arg name="host" value="${redis.sentinel.node3.host}"/>
  42. <constructor-arg name="port" value="${redis.sentinel.node3.port}"/>
  43. </bean>
  44. </set>
  45. </property>
  46. <property name="master">
  47. <bean name="masterNode" class="org.springframework.data.redis.connection.RedisNode">
  48. <!--必须指定主节点名称-->
  49. <property name="name" value="mymaster"/>
  50. <!-- <constructor-arg name="host" value="${redis.host}"/> <constructor-arg name="port" value="6379"/> -->
  51. </bean>
  52. </property>
  53. </bean>
  54. <!--哨兵配置方式二-->
  55. <!-- <bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration"> <constructor-arg name="propertySource" ref="propertySource"/> </bean> <bean name="propertySource" class="org.springframework.core.io.support.ResourcePropertySource"> <constructor-arg name="location" value="classpath:spring-redis-sentinel.properties" /> </bean> -->
  56. <!-- 使用JDK提供的序列化功能。 优点是反序列化时不需要提供类型信息(class),但缺点是序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。 -->
  57. <bean id="stringKeySerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
  58. <!-- JdkSerializationRedisSerializer,这个序列化方法是Idk提供的, 要求要被序列化的类继承自Serializeable接口,然后通过Jdk对象序列化的方法保存, 这个序列化保存的对象,即使是个String类型的,在redis控制台,也是看不出来的, 因为它保存了一些对象的类型什么的额外信息。 -->
  59. <bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
  60. <bean id="genericJackson2JsonRedisSerializer" class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
  61. <!-- 使用Jackson库将对象序列化为JSON字符串。优点是速度快,序列化后的字符串短小精悍。 但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。 通过查看源代码,发现其只在反序列化过程中用到了类型信息。 -->
  62. <!--<bean id="jackson2JsonRedisSerializer" class="org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer"> <constructor-arg type="java.lang.Object" ></constructor-arg> </bean>-->
  63. <!-- 配置RedisTemplate -->
  64. <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
  65. <property name="connectionFactory" ref="jedisConnectionFactory"/>
  66. <!-- 如果不配置Serializer,那么存储的时候只能使用String,如果用对象类型存储,那么会提示错误 can't cast to String!!!-->
  67. <property name="keySerializer" ref="stringKeySerializer"/>
  68. <property name="hashKeySerializer" ref="stringKeySerializer"/>
  69. <property name="valueSerializer" ref="genericJackson2JsonRedisSerializer"/>
  70. <property name="hashValueSerializer" ref="genericJackson2JsonRedisSerializer"/>
  71. </bean>
  72. <!-- 配置StringRedisTemplate 下面的各种key都是stringKeySerializer序列化方式-->
  73. <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
  74. <property name="connectionFactory" ref="jedisConnectionFactory"/>
  75. </bean>
  76. <!-- redis config end -->
  77. </beans>

crud

新建dao层crud方法,此处引用的是个人封装好的增删改查方法,在不粘贴。

  1. @Repository(value = "redisRepository")
  2. public class RedisRepository extends AbstractSpringRedisCacheEnhance {
  3. @Autowired
  4. RedisTemplate<String, Object> redisTemplate;
  5. @Override
  6. public StringRedisTemplate getStringRedisTemplate() {
  7. return null;
  8. }
  9. @Override
  10. public RedisTemplate<String, Object> getRedisTemplate() {
  11. return redisTemplate;
  12. }
  13. }

测试

新建测试类

  1. package com.hsy.spring.redis.dao;
  2. import com.hsy.spring.redis.sentinel.dao.RedisRepository;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.test.context.ContextConfiguration;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.util.ArrayList;
  11. import java.util.HashMap;
  12. import java.util.List;
  13. import java.util.Map;
  14. import java.util.concurrent.TimeUnit;
  15. /** * @author heshiyuan * @description <p></p> * @path spring/com.hsy.spring.redis.dao * @date 2018/7/23 18:42 * @github http://github.com/shiyuan2he * @email shiyuan4work@sina.com * Copyright (c) 2018 shiyuan4work@sina.com All rights reserved. * @price ¥5 微信:hewei1109 */
  16. @SuppressWarnings("Duplicates")
  17. @RunWith(SpringRunner.class)
  18. @ContextConfiguration({
  19. "classpath*:/spring/applicationContext.xml"})
  20. public class RedisRepositoryTest {
  21. private Logger logger = LoggerFactory.getLogger(getClass());
  22. @Autowired private RedisRepository redisRepository;
  23. public Map<String, Object> generateMap(){
  24. Map<String, Object> returnMap = new HashMap<>();
  25. returnMap.put("aa", "aa");
  26. Map<String, Object> innerMap = new HashMap<>();
  27. innerMap.put("ss", 3);
  28. innerMap.put("rr",false);
  29. innerMap.put("tt","中文");
  30. returnMap.put("bb", innerMap);
  31. returnMap.put("cc", 1.000);
  32. returnMap.put("dd", true);
  33. returnMap.put("ee", 1);
  34. return returnMap;
  35. }
  36. public List<Map<String, Object>> generateList(){
  37. List<Map<String, Object>> list = new ArrayList<>();
  38. for (int i = 0; i < 10; i++) {
  39. list.add(generateMap());
  40. }
  41. return list;
  42. }
  43. @Test
  44. public void clear(){
  45. redisRepository.clear();
  46. }
  47. @Test
  48. public void testSet(){
  49. redisRepository.valueSet("name", "robot");
  50. redisRepository.valueSet("name2", "robot", 1600, TimeUnit.SECONDS);
  51. redisRepository.valueSet("set:map", generateMap());
  52. redisRepository.valueSet("set:map", generateMap(), 1600, TimeUnit.SECONDS);
  53. redisRepository.valueSet("set:list", generateList());
  54. redisRepository.valueSet("set:list", generateList(), 1600, TimeUnit.SECONDS);
  55. }
  56. @Test
  57. public void testDelete(){
  58. //redisRepository.delete("name2", true);
  59. redisRepository.delete("name", false);
  60. }
  61. @Test
  62. public void testGet(){
  63. logger.info("{}", redisRepository.valueGet("name", false));
  64. logger.info("{}", redisRepository.valueGet("name2", true));
  65. logger.info("{}", redisRepository.valueGet("set:map", false));
  66. logger.info("{}", redisRepository.valueGet("set:map", true));
  67. logger.info("{}", redisRepository.valueGet("set:list", false));
  68. logger.info("{}", redisRepository.valueGet("set:list", true));
  69. //logger.info("{}", redisRepository.getAndSet("name", "new value",false));
  70. //logger.info("{}", redisRepository.getAndSet("name", "new value",true));
  71. }
  72. @Test
  73. public void testIncrement(){
  74. for (int i = 0; i < 10; i++) {
  75. logger.info("{}", redisRepository.valueIncrement("mobile:15911111111", 1l, 60, TimeUnit.MINUTES));
  76. logger.info("{}", redisRepository.valueIncrement("tel:15911111111", 1.0, 70, TimeUnit.MINUTES));
  77. }
  78. }
  79. @Test
  80. public void testSetArray(){
  81. for (int i = 0; i < 10; i++) {
  82. logger.info("{}", redisRepository.setAdd("set:array1",i));
  83. }
  84. for (int i = 5; i < 20; i++) {
  85. logger.info("{}", redisRepository.setAdd("set:array1",i));
  86. logger.info("{}", redisRepository.setAdd("set:array2",i));
  87. }
  88. //logger.info("{}", redisRepository.setPop("set:array"));
  89. logger.info("{}", redisRepository.setDifference("set:array1","set:array2"));
  90. logger.info("{}", redisRepository.setDifferenceAndStore("set:array1","set:array2", "set:array3"));
  91. logger.info("{}", redisRepository.setAdd("set:add:map",generateMap()));
  92. logger.info("{}", redisRepository.setAdd("set:add:list",generateList()));
  93. logger.info("{}", redisRepository.setPop("set:add:map"));
  94. logger.info("{}", redisRepository.setPop("set:add:list"));
  95. }
  96. @Test
  97. public void testList(){
  98. for (int i = 0; i < 10; i++) {
  99. logger.info("{}", redisRepository.listLeftPush("list:lilo:list", generateList()));
  100. logger.info("{}", redisRepository.listLeftPush("list:liro:list", generateList()));
  101. logger.info("{}", redisRepository.listRightPush("list:rilo:list", generateList()));
  102. logger.info("{}", redisRepository.listRightPush("list:riro:list", generateList()));
  103. }
  104. for (int i = 0; i < 5; i++) {
  105. logger.info("{}", redisRepository.listLeftPop("list:lilo:list"));
  106. logger.info("{}", redisRepository.listRightPop("list:liro:list"));
  107. logger.info("{}", redisRepository.listLeftPop("list:rilo:list"));
  108. logger.info("{}", redisRepository.listRightPop("list:riro:list"));
  109. }
  110. for (int i = 0; i < 10; i++) {
  111. logger.info("{}", redisRepository.listLeftPush("list:lilo:map", generateMap()));
  112. logger.info("{}", redisRepository.listLeftPush("list:liro:map", generateMap()));
  113. logger.info("{}", redisRepository.listRightPush("list:rilo:map", generateMap()));
  114. logger.info("{}", redisRepository.listRightPush("list:riro:map", generateMap()));
  115. }
  116. for (int i = 0; i < 5; i++) {
  117. logger.info("{}", redisRepository.listLeftPop("list:lilo:map"));
  118. logger.info("{}", redisRepository.listRightPop("list:liro:map"));
  119. logger.info("{}", redisRepository.listLeftPop("list:rilo:map"));
  120. logger.info("{}", redisRepository.listRightPop("list:riro:map"));
  121. }
  122. }
  123. @Test
  124. public void testZSet(){
  125. for (int i = 0; i < 10; i++) {
  126. logger.info("{}", redisRepository.zSetAdd("zset:map", generateMap(), i));
  127. }
  128. redisRepository.zSetIncrementScore("zset:Map", "4", 30);
  129. }
  130. @Test
  131. public void testHash(){
  132. for (int i = 0; i < 10; i++) {
  133. redisRepository.hashPut("hash:map", String.valueOf(i), generateMap());
  134. logger.info("{}", redisRepository.hashGet("hash:map", String.valueOf(i)));
  135. }
  136. for (int i = 0; i < 10; i++) {
  137. redisRepository.hashPut("hash:list", String.valueOf(i), generateList());
  138. logger.info("{}", redisRepository.hashGet("hash:list", String.valueOf(i)));
  139. }
  140. }
  141. }

总结

按照以上操作即可完成spring集成redis哨兵模式,简单而简洁。哨兵模式对于服务器防灾上有很好的可用性,保证服务

健壮可用,方式因服务器故障导致网站缓存穿透而致网站运行不畅。是单例redis基础之上的一个升级方案。

源码

spring-redis-sentinel

发表评论

表情:
评论列表 (有 0 条评论,259人围观)

还没有评论,来说两句吧...

相关阅读