spring实战4 spring整合redis哨兵

前言

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

开始

建项目

新建spring-redis-sentinel web项目

导包

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
<!--自己封装的增删改查包-->
<dependency>
    <groupId>com.hsy.java</groupId>
    <artifactId>java-util</artifactId>
</dependency>

配置文件

新建redis.properties

#访问地址 redis中心
redis.host=172.16.191.102
# redis.host=192.168.1.106
#访问端口
redis.port=6379
#授权密码,有没有这一项取决于要连接的redis服务是否设置了此项
redis.auth=123456
redis.dbIndex=0
redis.timeout=100000

# redis哨兵信息
redis.sentinel.node1.host=172.16.191.102
redis.sentinel.node1.port=26379
redis.sentinel.node2.host=172.16.191.102
redis.sentinel.node2.port=26380
redis.sentinel.node3.host=172.16.191.102
redis.sentinel.node3.port=26381

redis.pool.maxTotal=200
#连接池的最大数据库连接数。设为0表示无限制
redis.pool.maxIdle=1024
redis.pool.minIdle=8
#在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
redis.pool.testOnCreate=true
redis.pool.testOnBorrow=true
redis.pool.testOnReturn=true
#Idle时进行连接扫描
redis.pool.testWhileIdle=true

redis.pool.maxWaitMillis=100000
#表示idle object evitor两次扫描之间要sleep的毫秒数
redis.pool.timeBetweenEvictionRunsMillis=30000
#表示idle object evitor每次扫描的最多的对象数
redis.pool.numTestsPerEvictionRun=10
#表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;
# 这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
redis.pool.minEvictableIdleTimeMillis=60000

新建spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<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
">
    <context:property-placeholder location="classpath:config/redis.properties" ignore-resource-not-found="true"/>
    <!--<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:properties/redis.properties</value>
            </list>
        </property>
    </bean>-->

    <!-- redis config start -->
    <!-- 配置JedisPoolConfig实例 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${redis.pool.maxTotal}"/>
        <property name="maxIdle" value="${redis.pool.maxIdle}"/>
        <property name="minIdle" value="${redis.pool.minIdle}"/>
        <property name="testOnCreate" value="${redis.pool.testOnCreate}"/>
        <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
        <property name="testOnReturn" value="${redis.pool.testOnReturn}"/>
        <property name="testWhileIdle" value="${redis.pool.testWhileIdle}"/>
        <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"/>
        <property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}"/>
        <property name="numTestsPerEvictionRun" value="${redis.pool.numTestsPerEvictionRun}"/>
        <property name="minEvictableIdleTimeMillis" value="${redis.pool.minEvictableIdleTimeMillis}"/>
    </bean>

    <!-- 配置JedisConnectionFactory -->
    <bean id="jedisConnectionFactory"
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}"/>
        <property name="port" value="${redis.port}"/>
        <property name="password" value="${redis.auth}"/>
        <property name="database" value="${redis.dbIndex}"/>
        <property name="timeout" value="${redis.timeout}"/>
        <property name="poolConfig" ref="poolConfig"/>
    </bean>

    <bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
        <property name="sentinels">
            <set>
                <bean name="sentinelNode1" class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="${redis.sentinel.node1.host}"/>
                    <constructor-arg name="port" value="${redis.sentinel.node1.port}"/>
                </bean>
                <bean name="sentinelNode2" class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="${redis.sentinel.node2.host}"/>
                    <constructor-arg name="port" value="${redis.sentinel.node2.port}"/>
                </bean>
                <bean name="sentinelNode3" class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="${redis.sentinel.node3.host}"/>
                    <constructor-arg name="port" value="${redis.sentinel.node3.port}"/>
                </bean>
            </set>
        </property>
        <property name="master">
            <bean name="masterNode" class="org.springframework.data.redis.connection.RedisNode">
                <!--必须指定主节点名称-->
                <property name="name" value="mymaster"/>
                <!--
                <constructor-arg name="host" value="${redis.host}"/>
                <constructor-arg name="port" value="6379"/>
                -->
            </bean>
        </property>
    </bean>

    <!--哨兵配置方式二-->
    <!--
    <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>
    -->


    <!--
     使用JDK提供的序列化功能。 优点是反序列化时不需要提供类型信息(class),但缺点是序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。
    -->
    <bean id="stringKeySerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    <!--
        JdkSerializationRedisSerializer,这个序列化方法是Idk提供的,
        要求要被序列化的类继承自Serializeable接口,然后通过Jdk对象序列化的方法保存,
        这个序列化保存的对象,即使是个String类型的,在redis控制台,也是看不出来的,
        因为它保存了一些对象的类型什么的额外信息。
    -->
    <bean id="jdkSerializationRedisSerializer"
          class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    <bean id="genericJackson2JsonRedisSerializer"
          class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
    <!--
    使用Jackson库将对象序列化为JSON字符串。优点是速度快,序列化后的字符串短小精悍。
    但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。
    通过查看源代码,发现其只在反序列化过程中用到了类型信息。
    -->
    <!--<bean id="jackson2JsonRedisSerializer" class="org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer">
        <constructor-arg type="java.lang.Object" ></constructor-arg>
    </bean>-->
    <!-- 配置RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory"/>
        <!-- 如果不配置Serializer,那么存储的时候只能使用String,如果用对象类型存储,那么会提示错误 can't cast to String!!!-->
        <property name="keySerializer" ref="stringKeySerializer"/>
        <property name="hashKeySerializer" ref="stringKeySerializer"/>
        <property name="valueSerializer" ref="genericJackson2JsonRedisSerializer"/>
        <property name="hashValueSerializer" ref="genericJackson2JsonRedisSerializer"/>
    </bean>
    <!-- 配置StringRedisTemplate 下面的各种key都是stringKeySerializer序列化方式-->
    <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory"/>
    </bean>
    <!-- redis config end -->
</beans>

crud

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

@Repository(value = "redisRepository")
public class RedisRepository extends AbstractSpringRedisCacheEnhance {

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Override
    public StringRedisTemplate getStringRedisTemplate() {
        return null;
    }

    @Override
    public RedisTemplate<String, Object> getRedisTemplate() {
        return redisTemplate;
    }
}

测试

新建测试类

package com.hsy.spring.redis.dao;

import com.hsy.spring.redis.sentinel.dao.RedisRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @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
 */
@SuppressWarnings("Duplicates")
@RunWith(SpringRunner.class)
@ContextConfiguration({"classpath*:/spring/applicationContext.xml"})
public class RedisRepositoryTest {

    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired private RedisRepository redisRepository;

    public Map<String, Object> generateMap(){
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("aa", "aa");
        Map<String, Object> innerMap = new HashMap<>();
        innerMap.put("ss", 3);
        innerMap.put("rr",false);
        innerMap.put("tt","中文");
        returnMap.put("bb", innerMap);
        returnMap.put("cc", 1.000);
        returnMap.put("dd", true);
        returnMap.put("ee", 1);
        return returnMap;
    }
    public List<Map<String, Object>> generateList(){
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(generateMap());
        }
        return list;
    }
    @Test
    public void clear(){
        redisRepository.clear();
    }
    @Test
    public void testSet(){
        redisRepository.valueSet("name", "robot");
        redisRepository.valueSet("name2", "robot", 1600, TimeUnit.SECONDS);
        redisRepository.valueSet("set:map", generateMap());
        redisRepository.valueSet("set:map", generateMap(), 1600, TimeUnit.SECONDS);
        redisRepository.valueSet("set:list", generateList());
        redisRepository.valueSet("set:list", generateList(), 1600, TimeUnit.SECONDS);
    }

    @Test
    public void testDelete(){
        //redisRepository.delete("name2", true);
        redisRepository.delete("name", false);
    }

    @Test
    public void testGet(){
        logger.info("{}", redisRepository.valueGet("name", false));
        logger.info("{}", redisRepository.valueGet("name2", true));
        logger.info("{}", redisRepository.valueGet("set:map", false));
        logger.info("{}", redisRepository.valueGet("set:map", true));
        logger.info("{}", redisRepository.valueGet("set:list", false));
        logger.info("{}", redisRepository.valueGet("set:list", true));
        //logger.info("{}", redisRepository.getAndSet("name", "new value",false));
        //logger.info("{}", redisRepository.getAndSet("name", "new value",true));
    }

    @Test
    public void testIncrement(){
        for (int i = 0; i < 10; i++) {
            logger.info("{}", redisRepository.valueIncrement("mobile:15911111111", 1l, 60, TimeUnit.MINUTES));
            logger.info("{}", redisRepository.valueIncrement("tel:15911111111", 1.0, 70, TimeUnit.MINUTES));
        }
    }
    @Test
    public void testSetArray(){
        for (int i = 0; i < 10; i++) {
            logger.info("{}", redisRepository.setAdd("set:array1",i));
        }
        for (int i = 5; i < 20; i++) {
            logger.info("{}", redisRepository.setAdd("set:array1",i));
            logger.info("{}", redisRepository.setAdd("set:array2",i));
        }
        //logger.info("{}", redisRepository.setPop("set:array"));
        logger.info("{}", redisRepository.setDifference("set:array1","set:array2"));
        logger.info("{}", redisRepository.setDifferenceAndStore("set:array1","set:array2", "set:array3"));

        logger.info("{}", redisRepository.setAdd("set:add:map",generateMap()));
        logger.info("{}", redisRepository.setAdd("set:add:list",generateList()));
        logger.info("{}", redisRepository.setPop("set:add:map"));
        logger.info("{}", redisRepository.setPop("set:add:list"));
    }
    @Test
    public void testList(){
        for (int i = 0; i < 10; i++) {
            logger.info("{}", redisRepository.listLeftPush("list:lilo:list", generateList()));
            logger.info("{}", redisRepository.listLeftPush("list:liro:list", generateList()));
            logger.info("{}", redisRepository.listRightPush("list:rilo:list", generateList()));
            logger.info("{}", redisRepository.listRightPush("list:riro:list", generateList()));
        }

        for (int i = 0; i < 5; i++) {
            logger.info("{}", redisRepository.listLeftPop("list:lilo:list"));
            logger.info("{}", redisRepository.listRightPop("list:liro:list"));
            logger.info("{}", redisRepository.listLeftPop("list:rilo:list"));
            logger.info("{}", redisRepository.listRightPop("list:riro:list"));
        }
        for (int i = 0; i < 10; i++) {
            logger.info("{}", redisRepository.listLeftPush("list:lilo:map", generateMap()));
            logger.info("{}", redisRepository.listLeftPush("list:liro:map", generateMap()));
            logger.info("{}", redisRepository.listRightPush("list:rilo:map", generateMap()));
            logger.info("{}", redisRepository.listRightPush("list:riro:map", generateMap()));
        }

        for (int i = 0; i < 5; i++) {
            logger.info("{}", redisRepository.listLeftPop("list:lilo:map"));
            logger.info("{}", redisRepository.listRightPop("list:liro:map"));
            logger.info("{}", redisRepository.listLeftPop("list:rilo:map"));
            logger.info("{}", redisRepository.listRightPop("list:riro:map"));
        }
    }
    @Test
    public void testZSet(){
        for (int i = 0; i < 10; i++) {
            logger.info("{}", redisRepository.zSetAdd("zset:map", generateMap(), i));
        }
        redisRepository.zSetIncrementScore("zset:Map", "4", 30);
    }
    @Test
    public void testHash(){
        for (int i = 0; i < 10; i++) {
            redisRepository.hashPut("hash:map", String.valueOf(i), generateMap());
            logger.info("{}", redisRepository.hashGet("hash:map", String.valueOf(i)));
        }
        for (int i = 0; i < 10; i++) {
            redisRepository.hashPut("hash:list", String.valueOf(i), generateList());
            logger.info("{}", redisRepository.hashGet("hash:list", String.valueOf(i)));
        }
    }
}

总结

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

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

源码

spring-redis-sentinel

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值