Redis数据库基础
Redis数据库概述
Redis是一个基于内存的key-value结构数据库,即非关系型数据库
(NoSql)数据库并不是要取代关系型数据库,而是关系型数据库的一种补充。
Redis是互联网技术领域使用最为广泛的存储中间件,他是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供的数据可以达到100000+的QPS(每秒内查询次数)
主要特点
- 基于内存存储,读写性能高
- 适合存储热点数据
- 企业应用广泛
Redis下载与开启服务
下载
Redis的Windows是绿色软件,在官网下载之后,之间解压即可使用
注意其中的一些目录结构
redis.windows.conf Redis配置文件
redis-cli.exe Redis客户端
redis-server.exe Redis服务器
开启服务
Window版Redis启动命令
cmd命令窗口启动命令
redis-server.exe redis.windows.conf
也可以使用脚本命令
start cmd /k "redis-server.exe redis.windows.conf"
建立bat后缀文件放入文件位置,即可开启服务
Redis文件配置
在redis.windows.conf文件为redis的核心配置文件,可根据项目情况设置不同的参数
- 设置Redis服务密码,添加内容为 requirepass 123456
- 设置密码为123456.
客户端图形工具
我们通常使用Redis客户端图形工具,因为默认提供的客户端连接工具界面不太友好,同时操作也比较麻烦
我在项目中使用的是Another Redis Desktop Manager
Redis数据类型和命令
Redis数据类型
- 字符串(String),普通字符串,Redis中最简单的数据类型
- 哈希(hash),也叫散列,类似于Java中的HashMap结构
- 列表(list),按照插入顺序排序,可以重复元素,类似Java中的HashSet
- 集合(set),无序集合,没有重复元素,类似JavaHashSet
- 有序集合,集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素
Redis在Java中操作
我们在Java中操作Redis
Spring对Redis客户端进行了整合,提供了Spring Data Redis ,在SpringBoot项目中还提供了对应的Starter,即spring-boot-starter-data-redis
Spring Data Redis
Spring Data Redis是Spring中的一部分,提供了在Spring应用中,通过简单的配置就可以访问Redis服务,对Redis底层开发包进行了高度封装。
可以使用Spring Data Redis来简化Redis操作
Spring Boot中提供了对应的Starter,maven坐标:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
在Spring Data Redis中提供了一个高度封装的类,RedisTemplate,对相应的ap进行了封装,将同一类型的操作封装成operation接口,具体分类如下:
- ValueOperations: string数据操作
- SetOperations: set类型数据操作
- ZSetOperations: zet 类型数据操作
- HashOperations: hash类型的数据操作
- ListOperations: list类型的数据操作
在application.yml文件中,配置redis连接
spring:
redis:
host: localhost
port: 6379
password: 123456
在以上环境搭建之后,springboot框架会自动装配RedisTemplate,我们就可以在任意的位置使用这个对象
测试
下面我们来简单的新建一个测试类,并集成springboot,并且调用RedisTemplate
package com.itheima.test;
import com.itheima.CacheDemoApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest(classes = CacheDemoApplication.class)
@RunWith(SpringRunner.class)
public class RedisTest {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Test
public void test(){
System.out.println(redisTemplate);
}
}
在上面测试案例中,我们直接注入了RedisTemplate,并且指定了泛型为String
- 如果不指定泛型也可以进行操作,但是存储对象的时候需要进行序列化
- 一般项目中存储对象都会转化为json字符串,在进行存储,所以一般会选择使用泛型为String ,避免大量的序列化操作
操作字符串数据类型
/**
* 操作字符串类型的数据
*/
@Test
public void testString(){
// set get setex setnx
redisTemplate.opsForValue().set("name","小明");
String name = redisTemplate.opsForValue().get("name");
System.out.println(name);
redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES);
redisTemplate.opsForValue().setIfAbsent("lock","1");
redisTemplate.opsForValue().setIfAbsent("lock","2");
}
操作哈希数据类型
/**
* 操作哈希类型的数据
*/
@Test
public void testHash(){
//hset hget hdel hkeys hvals
redisTemplate.opsForHash().put("heima","name","tom");
redisTemplate.opsForHash().put("heima","age","20");
String name = (String) redisTemplate.opsForHash().get("heima", "name");
System.out.println(name);
Set keys = redisTemplate.opsForHash().keys("heima");
System.out.println(keys);
List values = redisTemplate.opsForHash().values("heima");
System.out.println(values);
redisTemplate.opsForHash().delete("heima","age");
}
操作列表数据类型
/**
* 操作列表类型的数据
*/
@Test
public void testList(){
//lpush lrange rpop llen
redisTemplate.opsForList().leftPushAll("mylist","a","b","c");
redisTemplate.opsForList().leftPush("mylist","d");
List mylist = redisTemplate.opsForList().range("mylist", 0, -1);
System.out.println(mylist);
redisTemplate.opsForList().rightPop("mylist");
Long size = redisTemplate.opsForList().size("mylist");
System.out.println(size);
}
操作集合类型数据
/**
* 操作集合类型的数据
*/
@Test
public void testSet(){
//sadd smembers scard sinter sunion srem
redisTemplate.opsForSet().add("set1","a","b","c","d");
redisTemplate.opsForSet().add("set2","a","b","x","y");
Set members = redisTemplate.opsForSet().members("set1");
System.out.println(members);
Long size = redisTemplate.opsForSet().size("set1");
System.out.println(size);
Set intersect = redisTemplate.opsForSet().intersect("set1", "set2");
System.out.println(intersect);
Set union = redisTemplate.opsForSet().union("set1", "set2");
System.out.println(union);
redisTemplate.opsForSet().remove("set1","a","b");
}
操作有序集合类型数据
/**
* 操作有序集合类型的数据
*/
@Test
public void testZset(){
//zadd zrange zincrby zrem
redisTemplate.opsForZSet().add("zset1","a",10);
redisTemplate.opsForZSet().add("zset1","b",12);
redisTemplate.opsForZSet().add("zset1","c",9);
Set zset1 = redisTemplate.opsForZSet().range("zset1", 0, -1);
System.out.println(zset1);
redisTemplate.opsForZSet().incrementScore("zset1","c",10);
redisTemplate.opsForZSet().remove("zset1","a","b");
}
缓存框架--Spring Cache
在项目中,我们一般统一管理缓存的框架来实现缓存优化,主要原因是耦合度更低,切换缓存的成本较低
Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单的加一个注解,就能实现缓存功能
导入Redis和SpringCache依赖
<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>
添加配置支持
application.yml文件中添加redis的支持
spring:
redis:
host: 127.0.0.1
port: 6379
password: 123456
在SpringCache中提供了很多缓存操作的注解
注解 | 说明 |
---|---|
@EnableCaching | 开启缓存注解功能吗,通常加在启动类上 |
@Cacheable | 在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据,如果没有缓存数据,调用方法并将方法返回值放到缓存中 |
@CachePut | 将方法的返回值放到缓存中 |
@CacheEvict | 将一条或多条数据从缓存中删除 |
@Caching | 缓存的结合体,可以组合以上注解在一个方法中使用,比如有新增有删除 |
在方法执行前,spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中,查询的时候使用
@Cacheable(cacheNames = "userCache",key="#id")
public User getById(Long id){
User user = userMapper.getById(id);
if(user == null){
throw new RuntimeException("用户不存在");
}
return user;
}
多条件查询使用Cacheable,比如查询的方法参数有多个,我们可以使用hashcode作为缓存的key,
@Cacheable(value = "userCache",key="#userDto.hashCode()",unless = "#result.size() == 0")
public List<User> getList(UserDto userDto){
List<User> list = userMapper.getList("%" + userDto.getName() + "%", userDto.getAge());
return list;
}
需要提供一个hashCode方法
@Data
public class UserDto {
private String name;
private int age;
@Override
public int hashCode() {
int result = Objects.hash(getName(),getAge());
return result;
}
}
hashcode的特点是,只要参数相同,则生成后的hashcode值肯定相同
如果返回结果为空,则不缓存unless="#result == null"或unless="#result.size()==0"
@CachePut
作用: 将方法返回值,放入缓存,一般保存的时候使用该注解
@CachePut(value = "userCache", key = "#user.id")//key的生成:userCache::1
public User insert(User user){
userMapper.insert(user);
return user;
}
- #user.id : #user指的是方法形参的名称, id指的是user的id属性 , 也就是使用user的id属性作为key
@CacheEvict
作用: 清理指定缓存
@CacheEvict(cacheNames = "userCache",key = "#id")//删除某个key对应的缓存数据
public void deleteById(Long id){
userMapper.deleteById(id);
}
@CacheEvict(cacheNames = "userCache",allEntries = true)//删除userCache下所有的缓存数据
public void deleteAll(){
userMapper.deleteAll();
}
@Caching
作用: 组装其他缓存注解
- cacheable 组装一个或多个@Cacheable注解
- put 组装一个或多个@CachePut注解
- evict 组装一个或多个@CacheEvict注解
@Caching(
cacheable = {
@Cacheable(value = "userCache",key = "#id")
},
put = {
@CachePut(value = "userCache",key = "#result.name"),
@CachePut(value = "userCache",key = "#result.age")
}
)
public User insert(User user){
userMapper.insert(user);
return user;
}
```****
标签:缓存,Redis,redis,user,优化,public,redisTemplate
From: https://www.cnblogs.com/yifan0820/p/17988077