美文网首页
Spring-data-redis -- 集成

Spring-data-redis -- 集成

作者: saoraozhe3hao | 来源:发表于2018-09-12 15:16 被阅读0次

官网:https://projects.spring.io/spring-data-redis/

应用场景

1、数据库缓存
2、缓存微信的access_token,因为同一时间只有最后一次获取的access_token有效,因此把access_token放在一个地方最为合理
3、会话共享

IDEA配置
1、Maven新增依赖

<dependency>
    <groupId>redis.clients</groupId>  <!-- Redis客户端 -->
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-redis</artifactId>  <!-- Spring 集成 Redis -->
  <version>2.0.10.RELEASE</version>
</dependency>

基本使用

Jedis jedis = new Jedis ("localhost", 6379 );
// jedis.auth("password");  // 如果需密码
try {
    jedis.set("test", "1") ;
    System.out.println(jedis.get("test"));
} finally {
    jedis.close();
}

连接池使用

JedisPoolConfig poolCfg =new JedisPoolConfig() ;
poolCfg.setMaxIdle(50);  // 最大空闲数
poolCfg.setMaxTotal(100) ;  // 最大连接数
poolCfg.setMaxWaitMillis(20000);  // 最大等待毫秒数
JedisPool pool = new JedisPool(poolCfg, "localhost");
Jedis jedis = pool.getResource() ;
// jedis.auth("password");  // 如果需密码
try {
     jedis.set("test", "1") ;
    System.out.println(jedis.get("test"));
} finally {
     jedis.close();
}

Spring使用

1、Spring 配置文件中加入

<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxTotal" value="2048" />
    <property name="maxIdle" value="200" />
    <property name="numTestsPerEvictionRun" value="1024" />
    <property name="timeBetweenEvictionRunsMillis" value="30000" />
    <property name="minEvictableIdleTimeMillis" value="-1" />
    <property name="softMinEvictableIdleTimeMillis" value="10000" />
    <property name="maxWaitMillis" value="1500" />
    <property name="testOnBorrow" value="true" />
    <property name="testWhileIdle" value="true" />
    <property name="testOnReturn" value="false" />
    <property name="jmxEnabled" value="true" />
    <property name="blockWhenExhausted" value="false" />
</bean>

<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
          p:use-pool="true" p:host-name="localhost" p:port="6379">  <!-- 连接工厂 -->
    <constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
          p:connection-factory-ref="jedisConnFactory"/>  <!-- Redis操作类 -->

2、注入与使用

@Autowired   // 自动注入
private RedisTemplate<String, Object> redisTemplate;   // 定型,指明要往redis存的对象类型

City city = new City();                     // City 必须可序列化
city.setCityName("广州");
redisTemplate.opsForValue().set("city_1", city);  // 存入
// RedisTemplate的泛型被定型为City后,这里就不用强制类型转换了
City city1 = redisTemplate.opsForValue().get("city_1");   // 上下两次操作可能用的不是同一个连接

redisTemplate.opsForHash() // Hash数据操作
redisTemplate.opsForList()  // List数据操作
redisTemplate.opsForSet()  // Set数据操作
redisTernplate.opsForZSet() // ZSet数据操作

SessionCallback callBack = new SessionCallback<City>(){  // 定型为execut要返回的类型
    public City execute(RedisOperations ops) throws DataAccessException {
         ops.multi();    // 开启事务来执行
         ops.boundValueOps("role_l").set(city);
         return (City) ops.boundValueOps("role_l").get() ;
    }
};
city1 = (City) redisTemplate.execute(callBack);  // 用同一个连接 执行
city1 = (City) redisTemplate.executePipelined(callBack) ; // 批量执行

订阅与发布

1、定义消息处理器

public class MessageListener{
    public void handleMessage(String message){    };
    public void handleMessage(Map message){    };
    public void handleMessage(byte[] message){    };
    public void handleMessage(Serializable message){    };
    public void handleMessage(Serializable message, String channel){    };
}

2、xml中配置消息处理器

<bean id="listener" class="com.hogen.redis.MessageListener"/>
<redis:listener-container>    <!-- 默认依赖的连接工厂的ID为 redisConnectionFactory -->
    <redis:listener ref="listener" method="handleMessage" topic="topic1" />
</redis:listener-container>

3、发布消息

 redisTemplate.convertAndSend("topic1", "消息1");

哨兵模式

1、配置Bean

<!-- 哨兵配置 -->
<bean id="sentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
    <property name="master">
        <bean class="org.springframework.data.redis.connection.RedisNode">
            <property name="name" value="mymaster"></property>   <!-- master名称,与Redis的sentinel.conf中的配置一致 -->
        </bean>
     </property>
     <property name="sentinels">
        <set>
            <bean class="org.springframework.data.redis.connection.RedisNode">  <!-- 可以配置多个哨兵 -->
                <constructor-arg name="host" value="47.105.112.41"></constructor-arg>
                <constructor-arg name="port" value="26379"></constructor-arg>  <!-- 哨兵的端口,Spring通过哨兵间接访问Redis -->
            </bean>
        </set>
    </property>
    <property name="database" value="0"></property> <!-- 使用redis的第0个db -->
</bean>

<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
    <constructor-arg name="sentinelConfig" ref="sentinelConfiguration"></constructor-arg>
</bean>

<bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="redisConnectionFactory">
        <property name="keySerializer" ref="stringRedisSerializer"/>  <!-- 指定序列化器,否则key会有乱码  -->
        <property name="valueSerializer" ref="jdkSerializationRedisSerializer"/>
    </bean>

集群模式

<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">  
    <property name="maxRedirects" value="${redis.maxRedirects}"></property>  
    <property name="clusterNodes">  
        <set>  
            <bean class="org.springframework.data.redis.connection.RedisNode">  
                <constructor-arg name="host" value="${redis.host1}"></constructor-arg>  
                <constructor-arg name="port" value="${redis.port1}"></constructor-arg>  
            </bean>  
                        <!-- 后面还有5个 -->
        </set>  
    </property>  
</bean>
<!-- 连接工厂 -->
<bean id="jeidsConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">        
    <constructor-arg name="clusterConfig" ref="redisClusterConfiguration"/>
    <constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
</bean>

Redis 用于缓存 mysql 数据

java读操作
1、尝试从redis读数据
2、redis中没有该数据,则从mysql中读取,读出后写入redis,并设置超时时间

java写操作
1、写入mysql
2、写入Redis,并设置超时时间

java删操作
1、从mysql删除
2、从Redis删除

Spring 缓存机制

1、装载RedisCacheManager,在能被<context:component-scan>扫描到的类中加入

// 可以定义一个初始化的类,专门用于装载框架的Bean
@Bean(name="redisCacheManager")
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
    return RedisCacheManager.create(connectionFactory);
}

2、启用缓存注解驱动

<!-- 启用注解驱动,即将缓存机制应用于@Cacheable注解的方法 -->
<cache:annotation-driven cache-manager="redisCacheManager"/>

3、注解Service方法

// @Cacheable实现 读操作的缓存机制。redis中没有对应的数据 才执行该方法,并将该方法的返回值存入redis;redis中的key为 cacheNames::key
// 用Spring表达式语言(SpringEL)获取方法的参数;不指定key 则为所有参数的toStirng;如果有空格、符号,会导致key有双引号,可以用base64对值编码来避免
// 在搜索场景中,要扣除无限值的字段,否则可能导致 key 爆炸
@Cacheable(cacheNames="city",key="'city_' + #id", condition="#query.search==null")  
public City getCity(long id){
    return cityMapper.getCity(id);
}
// @CachePut实现 写操作的缓存机制。执行该方法,并将该方法的返回值存入redis
@CachePut(cacheNames="city",key="'city_' + #city.id")
public City setCity(City city){
    return cityMapper.setCity(city);
}
// @CacheEvict实现 删操作的缓存机制。执行该方法,从redis删除数据
@CacheEvict(cacheNames="city",key="'city_' + #id")
public City setCity(long id){
    return cityMapper.rmCity(id);
}

SpringBoot 整合 redis

0、mybatis-config.xml

  <setting name="lazyLoadingEnabled" value="false"/> <!--如果为true,会出错-->

1、pom.xml

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

2、application.yml

  redis:
    host: r-2zerb3ixj026hfuvhp.redis.rds.aliyuncs.com
    port: 6379
    password: ****
    database: 0
    timeout: 1000ms
    lettuce:    # 也可以是 jedis,jedis 和 lettuce 都是 redis client
      pool:
        max-active: 200
        max-wait: -1ms
        max-idle: 10
        min-idle: 0

3、主类中注解 @EnableCaching
4、RedisTemplate 与 StringRedisTemplate

@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig {

    @Bean
    // 使用 JdkSerializationRedisSerializer 进行序列化,将数据序列化成字节数组
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
        template.setValueSerializer(fastJsonRedisSerializer);
        template.setHashValueSerializer(fastJsonRedisSerializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    // 使用 StringRedisSerializer 进行序列化,将数据序列化成字符串
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        // 设置 数据库 缓存 的默认有效时间
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().ntryTtl(Duration.ofHours(24)).
                // 设置 key 的前缀,可以用于区分不同profile;会使 @Cacheable的cacheNames 失效
                disableCachingNullValues().prefixKeysWith("dev::").
                // 计算生成key的前缀
                .computePrefixWith(cacheName -> profiles.concat("::").concat(cacheName).concat(":"));
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).
                cacheDefaults(config).transactionAware().build();
        return redisCacheManager;
    }
}

5、@Cacheable、@CachePut、@CacheEvict的使用与上文相同
6、使用redisTemplate、stringRedisTemplate、redisCacheManager

stringRedisTemplate.opsForValue().set("access_token", accessToken);
stringRedisTemplate.expire("access_token", duration, TimeUnit.SECONDS);  // 设置过期时间
String accessToken = stringRedisTemplate.opsForValue().get("access_token");
Long millis = stringRedisTemplate.getExpire("access_token", TimeUnit.MILLISECONDS);  // 获取过期时间

相关文章

网友评论

      本文标题:Spring-data-redis -- 集成

      本文链接:https://www.haomeiwen.com/subject/xpgvgftx.html