一、简介
1.了解redis:
redis是一个key-value。它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。为了保证效率,数据都是缓存在内存中。redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
2.redis的优点:
(1)Redis使用现场申请内存的方式来存储数据,并且很少使用free-list等方式来优化内存分配,会在一定程度上存在内存碎片,Redis跟据存储命令参数,会把带过期时间的数据单独存放在一起,并把它们称为临时数据,非临时数据是永远不会被剔除的,即便物理内存不够,适合存储。
(2)Redis提供了事务的功能,可以保证一串 命令的原子性,中间不会被任何操作打断。
(3)Redis除key/value之外,还支持list,set,sorted set,hash等众多数据结构,提供了KEYS进行枚举操作,但不能在线上使用,如果需要枚举线上数据,Redis提供了工具可以直接扫描其dump文件,枚举出所有数据,Redis还同时提供了持久化和复制等功能。
(4)Redis除了作为存储之外还提供了一些其它方面的功能,比如聚合计算、pubsub、scripting等,当然要先理解它的局限。
二、配置
准备工作:
(1)下载redis,链接:https://share.weiyun.com/55a8xxm 密码:a8onvi
(2)启动redis,解压下载的redis,找到下面标记的启动:
成功展示如下:
1.引入redis及缓存池依赖:
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
2.配置yml:
这里连接池用的lettuce,Lettuce的连接是基于Netty的,Netty 是一个多线程、事件驱动的 I/O 框架,连接实例可以在多个线程间共享, 所以,一个多线程的应用可以使用同一个连接实例,而不用担心并发线程的数量,Lettuce 可以帮助我们充分利用异步的优势。
spring:
redis:
#Redis服务器地址
host: 127.0.0.1
#Redis服务器连接端口
port: 6379
#连接超时时间
timeout: 10s
lettuce:
pool:
#连接池最小空闲连接
min-idle: 0
#连接池最大空闲连接
max-idle: 10
#连接池最大连接数(使用负值表示没有限制)
max-active: 10
#连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
3.配置RedisConfig:在引入redis的依赖后,RredisTemplate会自动配置,可以直接注入RedisTemplate使用。
注意:方法名一定要叫redisTemplate 因为@Bean注解是根据方法名配置这个bean的name,覆盖默认配置。
package com.example.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Created by Administrator on 2019/8/13.
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory){
RedisTemplate template = new RedisTemplate <>();
template.setConnectionFactory(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);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
4.Redis工具类:
关于工具类的问题,详见:工具类配置bin
package com.example.Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* The type Redis utils.
*
* @author lxp
* @date 2019 -08-13 14:34:20
*/
@Component
public class RedisUtils {
/**
* 注入redisTemplate bean
*/
private static RedisTemplate redisTemplate;
@Autowired
public void setRedisService(RedisTemplate redisTemplate){
RedisUtils.redisTemplate = redisTemplate;
}
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public static boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public static long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public static boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public static void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public static Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public static boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public static boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
*
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public static long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public static long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public static Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public static Map
5.User类:
package com.example.entity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
/**
* The type User.
*
* @author lxp
* @date 2019 -07-30 16:01:55
*/
@Data
@Table(name = "user")
public class User implements Serializable {
private static final long serialVersionUID = 1222221L;
@Id
@Column(name = "id")
private Integer id;
@Column(name = "user_name")
private String userName;
@Column(name = "pass_word")
private String passWord;
@Column(name = "real_name")
private String realName;
}
6.测试Redis:这里测试用到两个jar包,只加groupId、artifactId两个标签即可,多了下面测试类会报错。
org.springframework.boot
spring-boot-starter-test
junit
junit
package com.example;
import com.example.Util.RedisUtils;
import com.example.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Created by Administrator on 2019/8/12.
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class RedisApplicationTest {
@Test
public void redisTest() {
User user = (User) RedisUtils.get("小A");
log.info("=== Redis打印信息为:==="+user.getUserName());
}
}