知识点
1.Redis的应用场景?
1.Token令牌的生成
2.短信验证码的code
3.可以实现缓存查询数据 a. 减轻我们的数据库的访问压力 Redis与mysql数据库不同步的问题
4.Redis帮助实现计数器
5.分布式锁
6.延迟操作 分布式消息中间件
注意:Redis官方是没有windows版本的,只有linux,这时候因为 在nio中epoll只有linux操作系统独有
2.Redis线程模型?
Redis的采用NIO的IO多路复用原则,也就是一个线程维护多个不同的Redis客户端连接,从而提高处理
并发效率和保证线程安全问题.底层采用linux操作系统的epoll技术避免空轮询.
3.Redis数据结构?
String类型、Hsh类型、List类型、Set类型 、Sorted-Sets
String: 存储 set key value ; 获取 get key
Hsh: 存储 hmset key zhang 28 li 27 liu 23; 获取 hget key zhang/li/liu
list: 存储 lpush key xiaomi xiaojun xiaoqiang ;获取 lrange key 0(开始位置) 3(结束)
移出第一个元素并获得: lpop key
set: 存储 sadd key xiao1 xiao2 xiao3 xiao3(不能重复,无序) 存储3个元素
获取 smembers key
sortset: 存储 zadd key 1 zhang zadd key 2 li zadd key 3 zhang
(序号 值 ;有序的,值不能重复,重复存入,序号会覆盖之前序号,取值按照序号排序)
获取 zrange key 0 10 withscores(带上此参数,取值包含序号)
4.SpringBoot整合redis使用注意事项:
1.使用对象必须序列化 implements Serializable
2. private RedisTemplate<String ,Object> redisTemplate;使用@Resource注入,
不能使用@Autowired,因为按照类型找的autoWired找不到这种泛型类
demo地址:链接:https://pan.baidu.com/s/1PKxK4waUF0jfuofqx1Ajxw
提取码:fsh3
Springboot整合redis 使用(实体类必须实现序列化)
1.pom.xml依赖
<!--SpringBoot整合redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--springboot整合 mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.46.sec06</version>
</dependency>
2.application.properties配置文件
server.port=8080
spring.application.name=redis
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.redis.host=127.0.0.1
spring.redis.password=zsq2170
spring.redis.port=6379
spring.redis.database=1
#连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.lettuce.shutdown-timeout=5000ms
3.编写工具类 这里redis存Json字符串工具类
@Component
public class RedisUtils {
@Autowired
private StringRedisTemplate redisTemplate;
//不设置超时时间
public void setString(String key ,String value){
setString(key,value,null);
}
//设置超时时间,单位秒
public void setString(String key ,String value ,Long timeOut){
if(null!=timeOut&&timeOut>0){
redisTemplate.opsForValue().set(key,value);
redisTemplate.expire(key,timeOut, TimeUnit.SECONDS);
}else {
redisTemplate.opsForValue().set(key,value);
}
}
public String getString(String key){
return redisTemplate.opsForValue().get(key);
}
}
4.这里是redis存二进制工具类
@Component
public class RedisObjectUtils {
@Resource //此处不可使用@Autowired注解(会找不到redisTemplate) 实则redisTemplate已经初始化,且使用@Autowired会找不到此泛型类
private RedisTemplate<String ,Object> redisTemplate;
//不设置超时时间
public void setObject(String key ,Object value){
setObject(key,value,null);
}
//设置超时时间,单位秒
public void setObject(String key ,Object value ,Long timeOut){
if(null!=timeOut&&timeOut>0){
redisTemplate.opsForValue().set(key,value);
redisTemplate.expire(key,timeOut, TimeUnit.SECONDS);
}else {
redisTemplate.opsForValue().set(key,value);
}
}
public Object getObject(String key){
return redisTemplate.opsForValue().get(key);
}
}
5.编写测试接口
@RestController
public class RedisController {
@Autowired
private RedisUtils redisUtils; //redis存字符串工具类
@Autowired
private RedisObjectUtils redisObjectUtils; //redis存二进制工具类
//存json字符串
@GetMapping("/addUser")
public String addUser(UserEntity userEntity){
String json = JSON.toJSONString(userEntity);
redisUtils.setString("userEntity",json,300L);
return "存储成功";
}
@GetMapping("/getUser")
public UserEntity getUser(String key){
String s = redisUtils.getString(key);
return JSON.parseObject(s, UserEntity.class);
}
//存二进制
@GetMapping("/addUserBinary")
public String addUserBinary(UserEntity userEntity){
redisObjectUtils.setObject("userEntity",userEntity,300L);
return "存储成功";
}
@GetMapping("/getUserBinary")
public UserEntity getUserBinary(String key){
return (UserEntity)redisObjectUtils.getObject(key);
}
}
6.调用接口测试.注意事项,实体对象一定要实现序列化
SpringBoot 整合Redis 注解形式
1.依赖和配置文件一样 ,添加redis配置类信息
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport{
/**
* 配置自定义redisTemplate
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setValueSerializer(jackson2JsonRedisSerializer());
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setStringSerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
//json序列化
@Bean
public RedisSerializer<Object> jackson2JsonRedisSerializer() {
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
return serializer;
}
/**
* 配置缓存管理器
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 生成一个默认配置,通过config对象即可对缓存进行自定义配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// 设置缓存的默认过期时间,也是使用Duration设置 单位分钟
config = config.entryTtl(Duration.ofMinutes(10))
// 设置 key为string序列化
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
// 设置value为json序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()))
// 不缓存空值
.disableCachingNullValues();
// 使用自定义的缓存配置初始化一个cacheManager
return RedisCacheManager
.builder(redisConnectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
}
/**
* 定制化key生成器
* 设置 全限定类名 + 方法名 + 参数名 共同组成 key
* @return key生成器
* @date 2019/4/12 14:09
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (Object target, Method method, Object... params) -> {
StringBuilder sb = new StringBuilder(16);
sb.append(target.getClass().getName());
sb.append("_");
sb.append(method.getName());
sb.append("_");
for (int i = 0; i < params.length; i++) {
sb.append(params[i]);
if (i < params.length - 1) {
sb.append(",");
}
}
return sb.toString();
};
}
}
2.测试接口
@RestController
public class MemberController {
@Autowired
private MemberMapper memberMapper;
@Cacheable(cacheNames = "members" ,key = "'getListMember'")
@GetMapping("/getListMember")
public List<MemberEntity> getListMember(){
return memberMapper.fandAll();
}
/**
* Cacheable:可用于类或方法上;在目标方法执行前,会根据key先去缓存中查询看是否有数据,有就直接
* 返回缓存中的key对应的value值。不再执行目标方法;无则执行目标方法,并将方法的返回值
* 作为value,并以键值对的形式存入缓存
* condition: 缓存注解检查缓存中是否有对应的key-value 在 运行目标方法之前,
*/
@Cacheable(cacheNames = "members" ,key = "'getMemberById'+#id" , condition = "#id !=null")
@GetMapping("/getMemberById1")
public MemberEntity getMemberById1(Long id){
return memberMapper.getMemberById(id);
}
/**
* CachePut:可用于类或方法上;在执行完目标方法后,并将方法的返回值作为value,并以键值对的形式存入缓存中
*/
@CachePut(cacheNames = "members" ,key = "'getMemberById'+#id")
@GetMapping("/getMemberById2")
public MemberEntity getMemberById2(Long id){
return memberMapper.getMemberById(id);
}
/**
* CacheEvict:可用于类或方法上;在执行完目标方法后,清除缓存中对应key的数据(如果缓存
* 中有对应key的数据缓存的话)
* beforeInvocation:此属性主要出现在@CacheEvict注解中, 默认false 表示先执行方法后结束后删除缓存
* true->表示方法执行前生效,先删除缓解再执行方法,不存在缓存没被删除情况
*/
@CacheEvict(cacheNames = "members" ,key = "'getMemberById'+#id" , beforeInvocation = true)
@GetMapping("/getMemberById3")
public MemberEntity getMemberById3(Long id){
return memberMapper.getMemberById(id);
}
/**
* 不指定key , 使用redisCacheConfig里面的KeyGenerator生成策略 生成key
* unless : 功能是:是否令注解(在方法执行后的功能)不生效;若unless的结果为true,则(方法执行后的功能)不生效;
* 若unless的结果为false,则(方法执行后的)功能生效。
*/
@Cacheable(cacheNames = "KeyGenerator" , unless="#result == null")
@GetMapping("/getMemberById4")
public MemberEntity getMemberById4(Long id){
return memberMapper.getMemberById(id);
}
}