Redis常见数据结构的实战
Redis是具有高性能的、基于Key-Value结构化的缓存中间件,支持多种丰富的数据类型,包括字符串String, 列表List、集合Set、有序集合SortedSet以及哈希Hash存储
1. 字符串
- 创建一个person对象,将person对象存到Redis
package com.test.springboot.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.springboot.dao.Person;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class StringRedisController {
private static final Logger log = LoggerFactory.getLogger(StringRedisController.class);
@Resource
private RedisTemplate redisTemplate;
@Autowired
private ObjectMapper objectMapper;
@RequestMapping("/person")
public void stringTest() throws Exception {
Person p = new Person(12, "tom","火星");
final String key = "redis:test";
String value = objectMapper.writeValueAsString(p);
//写入缓存
log.info("存入缓存的数据是 {}", value);
redisTemplate.opsForValue().set(key, value);
// 读取数据
Object res = redisTemplate.opsForValue().get(key);
if (res != null) {
Person person = objectMapper.readValue(res.toString(), Person.class);
log.info("从缓存中读取的数据 {}", person.getName());
}
}
}
- Person的实现,要使用二级缓存redis进行缓存,类必须序列化
package com.test.springboot.dao;
import java.io.Serializable;
public class Person implements Serializable {
private Integer age;
private String name;
private String address;
public Person(Integer age, String name, String address) {
this.age = age;
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
序列化的意义:https://www.cnblogs.com/chenmingjun/p/9746310.html
Redis常见数据结构的实战–列表
2. 列表
Redis的列表类型和Java的中的List数据类型比较像,用于存储一系列具有相同类型的数据。其底层对于数据的存储和读取可以理解为一个“数据队列”,往List中添加数据时,即相当于往队列中的某个位置插入数据(比如从队尾插入数据);而从List获取数据时,即相当于从队列中的某个位置中获取数据(比如从队头获取数据)
实战:
按照顺序构造用户数据, 并按照顺序存入, 按照顺序读出
@RequestMapping("/list")
public void listTest() throws Exception{
List<Person> list = new ArrayList<>();
list.add(new Person(1, "one", "第一"));
list.add(new Person(2, "two", "第二"));
list.add(new Person(3, "three", "第三"));
log.info("构造的列表是: {}", list);
final String key = "redis:key";
ListOperations<String, java.io.Serializable> listOperations = redisTemplate.opsForList();
for (Person p: list){
// 从队尾插入数据
listOperations.leftPush(key, p);
// 从缓存中取出数据
log.info("--------从缓存中取出列表数据,从队头开始取------");
Object res = listOperations.rightPop(key);
Person pser;
if (res!=null){
pser = (Person) res;
log.info("取出的数据为 {}", pser.getName());
}
}
}
3. 集合
Redis的集合是和数学中的集合是很相似的, 用于存储相同类型或特性的不重复数据, Redis中的集合存储数据是唯一的, 其底层是通过Hash表实现的。所以增加和删除和查找操作的复杂程度都是O(1)
@RequestMapping("/set")
public void setTest() throws Exception{
List<Person> p = new ArrayList<>();
p.add(new Person("jack"));
p.add(new Person("tom"));
p.add(new Person("alice"));
p.add(new Person("jack"));
log.info("构造的列表是 {}", p.toString());
SetOperations<String, Serializable> setOperations = redisTemplate.opsForSet();
final String key = "key:test2";
redisTemplate.delete(key);
for (Person pp : p){
setOperations.add(key, pp);
}
// 从缓存中取出数据
Object pop = setOperations.pop(key);
if (pop !=null){
log.info("缓存中取出的数据是 {}", pop);
}
}
4.有序集合
Redis的有序集合SortedSet跟集合Set具有某些相同的特性,即存储的数据是不重复、无序、唯一的;而这两者的不同之处在于SortedSet可以通过底层的Score(分数/权重)值对数据进行排序,实现存储的集合数据既不重复又有序,可以说其包含了列表List、集合Set的特性。
5. hash表
Redis的哈希存储跟Java的HashMap数据类型有点类似,其底层数据结构是由Key-Value组成的映射表,而其Value又是由Filed-Value对构成,特别适用于具有映射关系的数据对象的存储。其底层存储结构如图3.23所示
@RequestMapping("/hashtest")
public void hashTest() throws Exception{
List<Student> students = new ArrayList<>();
List<Fruit> fruits = new ArrayList<>();
students.add(new Student("001", "一号", "一号"));
students.add(new Student("002", "二号", "二号"));
students.add(new Student("002", "三号", "三号"));
fruits.add(new Fruit("红","苹果"));
fruits.add(new Fruit("绿","鸭梨"));
fruits.add(new Fruit("黄","香蕉"));
final String key1 = "stu";
final String key2 = "fru";
HashOperations hashOperations = redisTemplate.opsForHash();
for(Student s: students){
hashOperations.put(key1, s.getId(), s);
}
Map<String, Student> smap = hashOperations.entries(key1);
log.info("学生列表是 {}", smap);
//获取指定的学生对象
Student s1 = (Student) hashOperations.get(key1, "001");
log.info("获取的学生对象是{}", s1);
}