springBoot中如何使用Redis,如何实现session的共享等解决方案

spring boot对常用的数据库支持外,对nosql 数据库也进行了封装自动化。
nosql 产品中Redis使用的简介。

redis简介

    Redis是目前业界使用最广泛的内存数据存储。相比memcached,Redis支持更丰富的数据结构,例如hashes, lists, sets等,同时支持数据持久化。除此之外,Redis还提供一些类数据库的特性,比如事务,HA,主从库。可以说Redis兼具了缓存系统和数据库的一些特性,因此有着丰富的应用场景。
同时介绍Redis使用的两个必须地方的问题:
① redis穿透:
      正常的执行路径是这样的,请求数据,首先会从redis缓存中拿数据,如果缓存没有的话才去查数据库,再写到redis缓存中。那么如果有人请求一条根本不存在的数据时,redis里面肯定没有嘛,它就会去访问数据库,但是数据库没有,所以它也没把数据写回redis缓存。所以它每次请求这个数据的时候它就会直接去访问数据库。如果请求的数量太大的话,都直接穿过redis直接去访问数据库,数据库承受不了这个访问数量。
       解决办法:在redis里面用一个set集来把数据库查询的那个查询主键都读出来存到这个set集里面。如果有请求时,先查redis里面的set有没有这个主键,如果没有就直接返回,不查数据库。如果有的话查redis,如果没有的话才去查数据库并把数据库里的数据写到缓存中。
②redis雪崩:
    每个key(即数据)如果设置了失效时间的话,如果大量key同时过期的时候,这些key又大量地去请求这些key时,因为redis里面没有这些数据,就会大量的请求就会大量涌向数据库,就会导致数据库处理不过来,导致“雪崩”。
    解决办法:在设置失效时间的时候,给它加一个随机的秒数(0~60),来让这些大量的数据进行错开对数据库的访问。这样数据库就能应付过来了。如果这个key的访问频率频繁的时候,我们可以让它每查一次就给它加点有效时间。这样就能解决雪崩问题了。

1、引入 spring-boot-starter-redis

de  ><dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-redis</artifactId>  
</dependency>  
de>

2、添加配置文件

de  ># REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0  
# Redis服务器地址
spring.redis.host=192.168.0.58
# Redis服务器连接端口
spring.redis.port=6379  
# Redis服务器连接密码(默认为空)
spring.redis.password=  
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8  
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1  
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8  
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0  
# 连接超时时间(毫秒)
spring.redis.timeout=0  
de>

3、添加cache的配置类

de  >@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
	
	@Bean
	public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    @SuppressWarnings("rawtypes")
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        //设置缓存过期时间
        //rcm.setDefaultExpiration(60);//秒
        return rcm;
    }
    
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

}

de>

3、Redis工具类已经封装好,可以直接使用。

de   >@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(Application.class)publicclassTestRedis{@AutowiredprivateStringRedisTemplatestringRedisTemplate;@AutowiredprivateRedisTemplateredisTemplate;@Testpublicvoidtest()throwsException{stringRedisTemplate.opsForValue().set("dddddddd","eeeeeeeeeeeeeeeeee");Assert.assertEquals("dddddddd",stringRedisTemplate.opsForValue().get("dddddddd"));
}@TestpublicvoidtestObj()throwsException{Useruser=newUser("[email protected]","aa3","aa333333333123456","aa33333","123333333");ValueOperations<String,User>operations=redisTemplate.opsForValue();operations.set("com.redis",user);operations.set("com.redis.f",user,1,TimeUnit.SECONDS);Thread.sleep(1000);//redisTemplate.delete("com.neo.f");booleanexists=redisTemplate.hasKey("com.redis.f");
if(exists){System.out.println("exists is true");}else{System.out.println("exists is false");}// Assert.assertEquals("aa", operations.get("com.neo.f").getUserName());}}de>

以上都是手动使用的方式,如何在查找数据库的时候自动使用缓存呢,看下面;

4、自动根据方法生成缓存

de  >@RequestMapping("/getUser")
@Cacheable(value="user-key")
public User getUser() {
    User user=userRepository.findByUserName("dddddddd");
System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功"); return user; } de>

其中value的值就是缓存到redis中的key

共享Session

使用spring-session-data-redis

分布式系统中,sessiong共享有很多的解决方案,其中托管到缓存中应该是最常用的方案之一,

Spring Session官方说明

Spring Session provides an API and implementations for managing a user’s session information.

如何使用

1、引入依赖

de  ><dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
de>

2、Session配置:

de  >@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
}
de>

maxInactiveIntervalInSeconds: 设置Session失效时间,使用Redis Session之后,原Boot的server.session.timeout属性不再生效

好了,这样就配置好了,我们来测试一下

3、测试

添加测试方法获取sessionid

de  >@RequestMapping("/uid")
    String uid(HttpSession session) {
        UUID uid = (UUID) session.getAttribute("uid");
        if (uid == null) {
            uid = UUID.randomUUID();
        }
        session.setAttribute("uid", uid);
        return session.getId();
    }
de>

登录redis 输入 de >keys '*sessions*'de>

de  >t<spring:session:sessions:db031986-8ecc-48d6-b471-b137a3ed6bc4
t(spring:session:expirations:1472976480000
de>

其中 1472976480000为失效时间,意思是这个时间后session失效,de >db031986-8ecc-48d6-b471-b137a3ed6bc4de> 为sessionId,登录http://localhost:8080/uid 发现会一致,就说明session 已经在redis里面进行有效的管理了。

如何在两台或者多台中共享session

其实就是按照上面的步骤在另一个项目中再次配置一次,启动后自动就进行了session共享。

 
 
 
 
阅读(0)评论(0) 编辑 |

猜你喜欢

转载自www.cnblogs.com/1314520gjy/p/9634310.html