Redis的实战Demo
Springboot+Redis的一个小Demo,边实战边学习
前言
实践是检验真理的唯一标准,比起背八股学理论知识,不如先在网上找个小Demo看看怎么个事(前提是你了解过SpringBoot和Mysql,对这类后端+数据库有一定理解)。
前面我们也了解到,Redis与Mysql最大的不同就是它的键值对存储方式,这也将在下面的代码中得以显现。本文将围绕Demo中的代码,尽可能去解释代码都干了什么,并基于Demo提炼其中的知识点,提供照葫芦画瓢的“葫芦”。
项目结构
1 | springboot-redis-demo |
详细代码
RedisConfig
1 | package com.redis_demo.config; |
RedisConfig是 Redis 的核心配置类,用于自定义 RedisTemplate(Spring Data Redis 的核心操作工具),解决 Java 对象与 Redis 存储格式的转换问题。
说白了就是不同于Mysql的关系型数据库,一个select和多个join下来才能出一个类对象,Redis是键值对的存储形式,也就是说value不能是一个类对象,而可以是json,RedisConfig的作用就是进行二者之间的格式转换。
application.properties
1 | spring.redis.host=localhost |
UserController UserService User类
和正常的SpringBoot项目流程一样,没有区别:
UserController
1 | package com.redis_demo.controller; |
UserService
1 | package com.redis_demo.service; |
User
1 | package com.redis_demo.entity; |
UserServiceImpl
到了这里就要真正去了解Redis的交互操作了。
在使用Mysql作为数据库的项目中,impl层的书写无非就是写写SQL语句,做一做变量的映射、类的处理。
然而在Redis中,正如前面说的它是基于键值对的数据库,存储的信息其实是高度集成(且冗余?)的,更多的操作是简单的基于key的增删改查以及设置过期时间等,并且事实上Redis也就用于处理这些,作为项目中主数据库的缓存去做简单而又大量的查找和删除工作。
我们的这个Demo是以Redis为主数据库的,只是单纯方便学习,如果不做持久化配置,数据可能丢失。并且也几乎不会有以Redis为项目主数据库的应用场景。Redis更多作为项目某一模块的数据库使用。
1 | package com.redis_demo.service.impl; |
其实和正常的数据库操作逻辑是相通的
下面一部分来列举redisTemplate的操作
redisTemplate
RedisTemplate 是 Spring Data Redis 提供的一个核心类,它封装了 Redis 的各种操作,提供了更高级的抽象来与 Redis 交互。
下面列举常用的几个方法(具体的查手册吧,说不完,记不完,学不完):
String
设置值
1 | redisTemplate.opsForValue().set("key", "value"); |
获取值
1 | Object value = redisTemplate.opsForValue().get("key"); //键值对的值可以是很多数据类型 |
数值操作
1 | redisTemplate.opsForValue().increment("counter", 1); // 增加1 |
删除值
1 | redisTemplate.delete(key); |
Hash
设置值
1 | redisTemplate.opsForHash().put("user:1", "name", "张三"); |
获取值
1 | Object name = redisTemplate.opsForHash().get("user:1", "name"); |
删除字段
1 | redisTemplate.opsForHash().delete("user:1", "age"); |
数值操作
1 | redisTemplate.opsForHash().increment("user:1", "age", 1); // 年龄+1 |
List
添加元素
1 | // 从左端添加 |
弹出元素
1 | Object leftPop = redisTemplate.opsForList().leftPop("list1"); // 左端弹出 |
获取元素
1 | Object first = redisTemplate.opsForList().index("list1", 0); // 获取索引0的元素 |
在指定元素前后插入
1 | redisTemplate.opsForList().leftPush("list1", "pivot", "newValue"); // 在pivot前插入 |
Set
添加元素
1 | redisTemplate.opsForSet().add("set1", "a", "b", "c", "d"); |
获取所有元素
1 | Set<Object> members = redisTemplate.opsForSet().members("set1"); |
移除元素
1 | redisTemplate.opsForSet().remove("set1", "a", "b"); |
集合运算
1 | Set<Object> union = redisTemplate.opsForSet().union("set1", "set2"); // 并集 |
ZSet
添加元素
1 | redisTemplate.opsForZSet().add("zset1", "member1", 100.0); |
批量添加
1 | Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>(); |
获取单个元素的分数
1 | Double score = redisTemplate.opsForZSet().score("zset1", "member1"); |
获取元素
1 | // 按分数范围获取 |
获取排名
1 | Long rank = redisTemplate.opsForZSet().rank("zset1", "member1"); // 正序排名(从0开始) |
移除元素
1 | redisTemplate.opsForZSet().remove("zset1", "member1"); |