Redis
String类型
Redis字符串类型常用命令:
- SET key value 设置指定key的值
- GET key 获取指定key的值
- SETEX key seconds value 设置指定key的值,并将key的过期时间设置为seconds秒
- SETNX key value 只有在key不存在时设置key的值
哈希类型
Redis哈希类型常用命令:
- HSET key field value 将哈希表key中的字段field设为value
- HGET key field 获取存储在哈希表中的指定字段的值
- HDEL key field 删除存储在哈希表中的指定字段
- HKEYS key 获取哈希表中所有字段
- HVALS key 获取哈希表中所有的值
存储模型:
列表类型
Redis列表类型常用命令:
Redis 列表是简单的字符串列表,按照插入顺序排序 (很像数据结构的队列 {先进先出})
- LPUSH key value1 [value2] 将一个或多个值插入到列表头部
- LRANGE key start stop 获取列表指定范围内的元素
- RPOP key 移除并获取列表最后一个元素
- LLEN key 获取列表长度
存储模型:
集合类型
Redis集合类型常用命令:
Redis set是String类型的无序集合。集合成员是唯一的,集合中不能出现重复的数据。
- SADD key member1 [member2] 向集合添加一个或多个成员
- SMEMBERS key 返回集合中的所有成员
- SCARD key 获取集合的成员数
- SINTER key1 [key2] 返回给定所有集合的交集
- SUNION key1 [key2] 返回所有给定集合的并集
- SREM key member1 [member2] 删除集合中一个或多个成员
存储模型:
有序集合类型
Redis有序集合类型常用命令:
Redis 有序集合是String类型的无序集合,且不允许有重复成员。每个元素都关联一个double类型的分数。
- ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员
- ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合中指定区间内的成员
- ZINCRBY key increment member 有序集合中对指定成员的分数加上增量increment
- ZREM key member [member] 移除有序集合中的一个或多个成员
存储模型:
通用命令
Redis的通用命令是不分数据类型的,都可以使用的命令
- KEYS pattern 查找所有符合给定模式(pattern)的key
- EXISTS key 检查给定key是否存在
- TYPE key 返回key所存储的值的类型
- DEL key 该命令用于key存在是删除key
Spring Data Redis
1, 导入maven坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2,配置Redis数据源(写yml)
spring:
redis:
host: ${sky.redis.host}
port: ${sky.redis.port}
password: ${sky.redis.password}
database: ${sky.redis.database}
SpringCache (建议用这个)
为什么使用Spring Cache
缓存有诸多的好处,于是大家就摩拳擦掌准备给自己的应用加上缓存的功能。但是网上一搜却发现缓存的框架太多了,各有各的优势,比如Redis、Memcached、Guava、Caffeine等等。
如果我们的程序想要使用缓存,就要与这些框架耦合。聪明的架构师已经在利用接口来降低耦合了,利用面向对象的抽象和多态的特性,做到业务代码与具体的框架分离。
但我们仍然需要显式地在代码中去调用与缓存有关的接口和方法,在合适的时候插入数据到缓存里,在合适的时候从缓存中读取数据。
想一想AOP的适用场景,这不就是天生就应该AOP去做的吗?
是的,Spring Cache就是一个这个框架。它利用了AOP,实现了基于注解的缓存功能,并且进行了合理的抽象,业务代码不用关心底层是使用了什么缓存框架,只需要简单地加一个注解,就能实现缓存功能了。而且Spring Cache也提供了很多默认的配置,用户可以3秒钟就使用上一个很不错的缓存功能。
1,导入maven坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--json依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
2,添加配置
spring:
cache:
type: redis #指定使用redis作为缓存
redis:
time-to-live: 1800000 # 配置 ttl 缓存过期时间,单位毫秒,这里设置了3600秒,即1个钟失效
cache-null-values: true # 是否缓存 Null 值,默认为 true,默认解决“缓存穿透”问题。
use-key-prefix: true # 是否使用key前缀,默认为 true
3,开启缓存
在启动类上面加上 @EnableCaching
@Slf4j
@SpringBootApplication
@EnableCaching
public class WaiMaiApplication {
public static void main(String[] args) {
SpringApplication.run(WaiMaiApplication.class,args);
log.info("项目启动成功!123");
}
}
4,写配置
package com.sky.config;
import lombok.extern.slf4j.Slf4j;
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.StringRedisSerializer;
/**
* 功能:
* 作者: 沙琪马
* 日期: 2024/5/13 14:07
*/
@Configuration
@Slf4j
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
log.info("开始创建redis模版对象...");
RedisTemplate redisTemplate = new RedisTemplate();
// 设置redis的连接工厂对象
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 设置redis key的序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}
5,注解使用
spring boot cache 提供了一些注解方便做cache应用。
(1)@CacheConfig:主要用于配置该类中会用到的一些共用的缓存配置
(2)@Cacheable:主要方法返回值加入缓存。同时在查询时,会先从缓存中取,若不存在才再发起对数据库的访问。
(3)@CachePut:配置于函数上,能够根据参数定义条件进行缓存,与@Cacheable不同的是,每次回真实调用函数,所以主要用于数据新增和修改操作上。
(4)@CacheEvict:配置于函数上,通常用在删除方法上,用来从缓存中移除对应数据
(5)@Caching:配置于函数上,组合多个Cache注解使用。
常用的一般是:
@Cacheable 将函数的返回值加入缓存
@CacheEvict 删除数据库的缓存
(1) @Cacheable
cacheNames 是指一个缓存分区,(如果没有会自动创建)
key 指定的是缓存的名称
像我这样设置结果就是:
elf::#name_#type_#generation
@GetMapping("/all")
@Cacheable(cacheNames = "elf", key = "#name+'_'+#type+'_'+#generation")
public Result listAll(@RequestParam(required = false) String name,
@RequestParam(required = false) String type,
@RequestParam(defaultValue = "0") Integer generation){
Criteria criteria = new Criteria();
List<Criteria> criteriaList = new ArrayList<>();
// 对 name 进行模糊查询
if (StrUtil.isNotBlank(name)) {
Pattern namePattern = Pattern.compile("^.*" + name + ".*$", Pattern.CASE_INSENSITIVE);
criteriaList.add(Criteria.where("name").regex(namePattern));
}
// 对 type 进行精准查询,并包括type或type2为输入type的情况
if (StrUtil.isNotBlank(type)) {
Criteria typeCriteria = new Criteria().orOperator(
Criteria.where("type1").is(type),
Criteria.where("type2").is(type)
);
criteriaList.add(typeCriteria);
}
if (!criteriaList.isEmpty()) {
criteria = new Criteria().andOperator(criteriaList.toArray(new Criteria[0]));
}
Query query = new Query(criteria); // 使用构建好的条件集合创建查询
// 添加世代查询
if ( generation != 0) {
query.addCriteria(Criteria.where("generation").is(generation));
}
query.with(Sort.by(Sort.Direction.ASC, "id_str"));
List<Elf> elfAll = mongoTemplate.find(query, Elf.class);
return Result.success(elfAll);
}
(2) @CacheEvict
删除指定数据
/1、指定删除“category"缓存分区里,某个缓存key的数据。
@CacheEvict(value = "category",key = "'getLevel1Categorys'")
//2、指定删除“category"缓存分区里,某个缓存 key1、key2...keyN 的数据 (批量删)。
@Caching(evict = {
@CacheEvict(value = "category", key = "'getLevel1Categorys'"),
@CacheEvict(value = "category", key = "'getCatelogJson'"),
// @CacheEvict(....) 可以删除多个
}
)
这样是清空,elf下的全部数据
@PostMapping("/save")
@CacheEvict(value = "elf", allEntries = true)
public Result save(@RequestBody Elf elf){
log.info("修改{}属性",elf.getName());
// 1.构建更新查询条件
Query query = new Query(Criteria.where("_id").in(elf.getId()));
// 2.构建更新语句
Update update = new Update().set("name", elf.getName()).set("type1",elf.getType1()).set("type2",elf.getType2())
.set("ability1",elf.getAbility1()).set("ability2",elf.getAbility2()).set("abilityHide",elf.getAbilityHide())
.set("desc",elf.getDesc()).set("stat",elf.getStat());
// 3.执行更新
UpdateResult updateResult = mongoTemplate.updateFirst(query, update, Elf.class);
log.info("更新数量:{}",updateResult.getModifiedCount());
return Result.success();
}