安装Redis
Linux安装
安装c编译器
yum -y install gcc
下载redis
cd /usr/local
wget http://download.redis.io/releases/redis-3.2.5.tar.gz
解压redis
tar -xvf redis-3.2.5.tar.gz
mv redis-3.2.5 redis
编译redis
cd redis
make
配置redis
修改redis.conf
# bind 127.0.0.1 去掉绑定本机IP,让其它机器访问
protected mode no 关闭保护模式
启动redis服务器
切换到src中
./redis-server ../redis.conf
启动redis客户端
./redis-cli
Windows安装
从官网下载redis的windows版本
https://github.com/tporadowski/redis/releases
解压后,双击redis-server.exe,就完成了Redis启动
SpringBoot整合Redis
前置准备
1)导入Redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2)添加配置文件
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0
spring.redis.jedis.pool.max-active=100
spring.redis.jedis.pool.max-wait=100ms
spring.redis.jedis.pool.max-idle=100
spring.redis.jedis.pool.min-idle=10
编程式缓存
1)编写配置类
配置RedisTemplate
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
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;
}
}
2)使用RestTemplate
常用方法:
- ValueOperations opsForValue() 获得string类型的操作对象
- HashOperations opsForHash 获得hash类型的操作对象
- …
ValueOperations操作对象
- set(key,value) 保存key-value
- Object get(key) 读取value
使用缓存的步骤:
- 先查询缓存
- 如果查到直接返回
- 如果查不到,查询数据库
- 数据库查到,保存缓存中
- 数据库查不到返回null
//假设这里有一个Goods类,我们要通过id查找对应的数据
@Autowired
private GoodsMapper goodsMapper;
@Override
public Goods findById(Long id) {
ValueOperations<String, Object> ops = template.opsForValue();
//先查缓存,缓存有,直接返回不执行同步块,提高效率
Goods goods = (Goods ) ops.get("goods-"+id);
if(goods == null) {
//上锁,保证查询缓存,查询数据库,保存缓存同步执行
synchronized (this) {
//先查询缓存
goods = (Goods ) ops.get("goods-" + id);
//如果查到直接返回
if (goods!= null) {
System.out.println("从缓存查到" + goods);
return goods;
} else {
//如果查不到,查询数据库
System.out.println("缓存没有,查询数据库");
goods = goodsMapper.selectById(id);
if (goods!= null) {
//数据库查到,保存缓存中
System.out.println("数据库查到" + goods);
ops.set("goods-" + id, goods);
return goods;
}
}
System.out.println("数据库没有查到");
return null;
}
}
return goods;
}
声明式缓存
编程式缓存自由度高,但是使用复杂,代码侵入性高;
声明式缓存相反,通过注解来实现热点数据缓存,使用简单,侵入性低。
1)在启动类上添加注解
//启动缓存
@EnableCaching
2)Redis的配置类
@Configuration
public class RedisConfig {
@Bean
public RedisCacheConfiguration provideRedisCacheConfiguration(){
//加载默认配置
RedisCacheConfiguration conf = RedisCacheConfiguration.defaultCacheConfig();
//返回Jackson序列化器
return conf.serializeValuesWith(
RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
}
}
3)缓存相关注解
- @CacheConfig 使用在Service类上,可以配置缓存名称,如:
@CacheConfig(cacheNames = “books”) - @Cacheable 使用在查询方法上,让方法优先查询缓存
- @CachePut 使用在更新和添加方法上,数据库更新和插入数据后同时保存到缓存里
- @CacheEvict 使用在删除方法上,数据库删除后同时删除缓存
注意:缓存的实体类必须实现序列化接口
这里假设有一个Brand类,看看增删改查对应的redis注解:
//配置缓存名称为brand
@CacheConfig(cacheNames = "brand")
@Service
public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements IBrandService {
@Autowired
private BrandMapper brandMapper;
//按分类查询品牌时进行缓存,缓存名称是brand-category,键是分类id
@Cacheable(cacheNames = "brand-category",key = "T(String).valueOf(#cid)")
@Override
public List<Brand> findBrandsByCategory(Integer cid) {
return brandMapper.selectBrandsByCategory(cid);
}
//缓存单个品牌
@Cacheable(key = "T(String).valueOf(#id)")
@Override
public Brand findBrandById(Long id) {
return this.getById(id);
}
//修改品牌时更新缓存
@CachePut(key = "T(String).valueOf(#brand.id)")
@Override
public Brand saveBrand(Brand brand) {
this.saveOrUpdate(brand);
return brand;
}
//删除品牌时删除缓存
@CacheEvict(key = "T(String).valueOf(#id)")
@Override
public void deleteBrand(Long id) {
this.removeById(id);
}
//缓存分页
@Cacheable(cacheNames = "brand-page",key = "T(String).valueOf(#page)")
@Override
public IPage<Brand> pageBrands(Long page) {
return this.page(new Page<>(page,10));
}
}