目录
- 前言
- Windows系统打开redis
- Springboot整合redis
- 依赖
- 实体类
- yml配置文件
- config配置
- 各个数据存储类型分别说明记录
- string
- 数据写入redis,并查询
- 通过命令行查询
- list
- 插入数据到redis中
- 从redis中读取
- 命令读取数据
- hash
- 向redis中逐个添加map键值对
- 获取key对应的map中所有的键
- 获取key对应的所有map键值对
- 获取key对应的map中,key为username的map的对应的值
- 获取key对应的map中所有的值
- 判断key对应的map中是否有指定的键
- 如果key对应的map不存在,则新增到map中,存在则不新增也不覆盖
- 将一个完成的键值对直接放入redis
- 命令读取数据
- set
- 向key中批量添加值
- 获取key中的所有值
- 获取key对应集合的长度
- 随机获取key对应的集合中的元素
- 随机获取key对应集合中指定个数的元素
- 随机获取key对应集合中指定个数的元素,并且去重
- zset
- 注意
前言
在springboot框架中,通过RedisTemplate中封装好的方法去操作redis中的各种数据类型,完成增删改查操作。
本项目将数据序列化为json格式,分别以set、zset、hash的结构存入数据库中,完成查询所有数据、通过id查询单个数据,新增数据的操作。
redis有五种常用的数据结构:string hash list set zset
key-string:一个key对应一个值。
key-hash:一个key对应一个Map。
key-list:一个key对应一个列表。
key-set:一个key对应一个集合。
key-zset:一个key对应一个有序的集合。
Windows系统打开redis
我从网上下载来的redis包,里面有这些内容。
但是启动redis的服务端时,不会去直接双击“redis-server.exe”文件,因为这样启动不会去读取配置文件,需要通过命令行启动。如果需要远程访问redis,则需要在配置文件中配置ip等信息。
bind 0.0.0.0
监听地址,默认是127.0.0.1,会导致只能在本地访问,修改为0.0.0.0则可以在任意IP访问,生产环境不要设置为0.0.0.0
protected-mode no
将保护模式改为no
使用cmd命令行启动服务端
redis-server redis.conf
双击启动客户端
redis的存储查询数据命令,会在演示springboot使用redis中说明。
Springboot整合redis
依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
</dependencies>
实体类
public class User {
private Integer id = 0;
private String username = "";
private String remark = "";
}
yml配置文件
用于配置redis的ip、端口、数据库、连接池等
spring:
redis:
port: 6379
host: 127.0.0.1
database: 1
password: 123456
jedis:
pool:
max-active: 8
max-idle: 8
max-wait: 1ms
timeout: 5000ms
config配置
将实体类数据序列化为json格式
import java.text.SimpleDateFormat;
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;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//ObjectMapper 指定在转成json的时候的一些转换规则
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// 把自定义的objectMapper设置到jackson2JsonRedisSerializer
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// RedisTemplate默认的序列化方式使用的是jdk的序列化
// 设置了key的序列化方式
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(jackson2JsonRedisSerializer); // 配置hash格式
// 设置了value序列化方式
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer); // 配置hash格式
return template;
}
}
在启动类中需要使用@ComponentScan()注解扫描配置文件
各个数据存储类型分别说明记录
专门编写一个测试类
import com.alibaba.fastjson.JSON;
import com.redis.StartApplication;
import com.redis.pojo.User;
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.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest(classes = StartApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class TestRedis {
@Autowired
private RedisTemplate redisTemplate;
}
string
初始化数据
private String initUserJson() {
return JSON.toJSON(new User(1,"hzx1","This is a test user")).toString();
}
数据写入redis,并查询
@Test
public void saveDataInRedisString() {
redisTemplate.opsForValue().set("user", initUserJson());
// 输出存入redis的数据
System.out.println(redisTemplate.opsForValue().get("user"));
}
通过命令行查询
#1. 添加值
set key value
#2. 取值
get key
list
初始化数据
private List initUserList(int num) {
List<User> resUserList = new ArrayList<>();
for (int i = 1; i <= num; i++) {
resUserList.add(new User(i, "hzx" + i, "This is the " + i + "th user"));
}
return resUserList;
}
插入数据到redis中
list通过链表实现,插入数据时需要区分左插入和右插入。可以逐条数据插入也可以批量数据插入
@Test
public void saveDataInRedisList() {
List list = initUserList(10);
// 逐条插入
for (Object user : list) {
redisTemplate.opsForList().leftPush("userListLeft", user);
redisTemplate.opsForList().rightPush("userListRight",user);
}
// 批量插入
redisTemplate.opsForList().leftPushAll("userListLeft",list);
redisTemplate.opsForList().rightPushAll("userListRight",list);
}
从redis中读取
@Test
public void queryDataFromRedisList(){
List userList;
System.out.println("左插入List");
userList = redisTemplate.opsForList().range("userListLeft", 0, 10);
for (Object o : userList) {
System.out.println(o.toString());
}
System.out.println("右插入List");
userList = redisTemplate.opsForList().range("userListRight", 0, 10);
for (Object o : userList) {
System.out.println(o.toString());
}
}
两种插入方式,最终顺序也不同
命令读取数据
#1. 存储数据(从左侧插入数据,从右侧插入数据)
lpush key value [value ...]
rpush key value [value ...]
#2. 存储数据(如果key不存在,什么事都不做,如果key存在,但是不是list结构,什么都不做)
lpushx key value
rpushx key value
#3. 修改数据(在存储数据时,指定好你的索引位置,覆盖之前索引位置的数据,index超出整个列表的长度,也会失败)
lset key index value
#4. 弹栈方式获取数据(左侧弹出数据,从右侧弹出数据)
lpop key
rpop key
#5. 获取指定索引范围的数据(start从0开始,stop输入-1,代表最后一个,-2代表倒数第二个)
lrange key start stop
#6. 获取指定索引位置的数据
lindex key index
#7. 获取整个列表的长度
llen key
#8. 删除列表中的数据(他是删除当前列表中的count个value值,count > 0从左侧向右侧删除,count < 0从右侧向左侧删除,count == 0删除列表中全部的value)
lrem key count value
#9. 保留列表中的数据(保留你指定索引范围内的数据,超过整个索引范围被移除掉)
ltrim key start stop
#10. 将一个列表中最后的一个数据,插入到另外一个列表的头部位置
rpoplpush list1 list2
hash
向redis中逐个添加map键值对
redisTemplate.opsForHash().put("map1","id",1);
redisTemplate.opsForHash().put("map1","username","hzx1");
redisTemplate.opsForHash().put("map1","remark","This is the No.1 user");
获取key对应的map中所有的键
redisTemplate.opsForHash().keys("map1")
获取key对应的所有map键值对
redisTemplate.opsForHash().entries("map1")
获取key对应的map中,key为username的map的对应的值
redisTemplate.opsForHash().get("map1", "username")
获取key对应的map中所有的值
redisTemplate.opsForHash().values("map1")
判断key对应的map中是否有指定的键
redisTemplate.opsForHash().hasKey("map1","username")
如果key对应的map不存在,则新增到map中,存在则不新增也不覆盖
redisTemplate.opsForHash().putIfAbsent("map2","username","hzx2");
redisTemplate.opsForHash().putIfAbsent("map2","username","hzx02abcd");
将一个完成的键值对直接放入redis
Map<Object,Object> map3 = new HashMap<>();
map3.put("id",3);
map3.put("username","hzx03");
redisTemplate.opsForHash().putAll("map3",map3);
命令读取数据
#1. 存储数据
hset key field value
#2. 获取数据
hget key field
#3. 批量操作
hmset key field value [field value ...]
hmget key field [field ...]
#4. 自增(指定自增的值)
hincrby key field increment
#5. 设置值(如果key-field不存在,那么就正常添加,如果存在,什么事都不做)
hsetnx key field value
#6. 检查field是否存在
hexists key field
#7. 删除key对应的field,可以删除多个
hdel key field [field ...]
#8. 获取当前hash结构中的全部field和value
hgetall key
#9. 获取当前hash结构中的全部field
hkeys key
#10. 获取当前hash结构中的全部value
hvals key
#11. 获取当前hash结构中field的数量
hlen key
set
向key中批量添加值
redisTemplate.opsForSet().add("set1","hzx1","hzx2");
redisTemplate.opsForSet().add("set1","hzx3");
获取key中的所有值
redisTemplate.opsForSet().members("set1")
获取key对应集合的长度
redisTemplate.opsForSet().size("set1")
随机获取key对应的集合中的元素
redisTemplate.opsForSet().randomMember("set1")
随机获取key对应集合中指定个数的元素
set本身是不会有重复的值
随机获取可能获取到一样的,所以返回的list集合中可能会有重复的值
redisTemplate.opsForSet().randomMembers("set1",2)
随机获取key对应集合中指定个数的元素,并且去重
redisTemplate.opsForSet().distinctRandomMembers("set1",2)
zset
注意
执行添加操作时要注意,当sqlserver数据库添加成功而redis添加失败的情况。
在hash、set、zset中,zset既要排序又要查重,对内存的消耗是最大的,所以一般不使用。