Redis
简介
- 概念:Remote dictionary server,是一个开源的基于内存的数据存储系统
- 功能:可以用作数据库缓存和消息队列等各种场景,是最热门的noSQL数据库之一
- 优点:随着互联网的发展,应用系统的访问量越来越大,数据库的性能瓶颈越来越明显,主要是由于磁盘IO导致的,磁盘IO的读写速度与内存相比是非常慢的,将数据存储在内存中会大大的提高性能
- 支持的数据类型:
- 五种基本数据类型:
- String:字符串,大小上限512M
- List:列表
- Set:集合
- SortedSet:有序集合
- Hash:哈希
- 五种高级数据类型
- 消息队列:Stream
- 地理空间:Geospatial
- HyperLogLog
- 位图:Bitmap
- 位域:Bitfield
- 五种基本数据类型:
- CLI(Command Line Interface)通过Redis-CLI工具使用Redis
- 应用程序接口 API
- 图形用户界面 GUI
- 优势:
- 性能极高
- 数据类型丰富,单键值对最大支持512M大小的数据
- 简单易用,支持所有主流编程语言
- 支持数据持久化、主从复制、哨兵模式等高可用特性
String
在Redis中数据是以键值对的形式存储的,键和值之间使用空格来分隔,可以使用SET命令设置键值对
> SET NAME YIYE "OK"
使用GET命令获取键值对的值
> GET NAME "YIYE"
注意
- Redis中的键是区分大小写的
使用DEL命令删除键值对的值
> DEL NAME (integer) 1//返回值为整数类型
使用EXISTS命令查找键值对是否存在
> EXISTS NAME (integer) 0//返回值为0表示不存在
使用KEYS命令查看有哪些键
KEYS *//表示查找所有的键 KEYS *me//表示查找所有以me结尾的键
FLUSHALL(
删库跑路、清除所有的键值对)使用TTL命令查看键值对的过期时间
TTL NAME >-1 //表示没有设置过期时间
使用EXPIRE 命令来设置过期时间
EXPIRE NAME 10//十秒后过期 //再次执行TTL命令会发现时间持续减少,当最后返回值为-2时,说明已经过期了,执行GET、KEYS方法也找不到这个键
也可以使用SETEX命令来设置一个带有过期时间的键值对
SETEX NAME 5 依夜帅的一比
SETNX命令,当键不存在时设置键的值,如果键已经不存在将不会有任何动作
SETNX NAME Y
Redis默认是不支持中文的,通过
redis-cli --raw
启动,即可获取到中文字符
List列表
一般用来操作和存储一些有顺序的数据,和数组的概念比较类似
命令
使用LPUSH命令添加到列表的头部
LPUSH letter a //LPUSH也可以添加多个元素,如: LPUSH letter b c d e
使用LRANGE来获取列表中的元素
LRANGE letter 0 -1 //表示获取起始位置为0,到最后一个位置的元素(-1为最后一个位置) 1)"a"
使用RPUSH命令添加到列表的尾部
RPUSH letter f
同样的,可以使用LPOP和RPOP来从头部和尾部删除元素
LPOP/RPOP letter [COUNT] //会返回一个被删除的元素 //注:COUNT为被删除的数量,在老版本中是不被支持的
使用LLEN命令来查看列表的长度
LLEN letter >3
使用LTRIM命令删除列表指定以外的元素
LTRIM letter startIndex
Set集合
Set中的元素是不能重复的,并没有顺序
命令
SADD命令添加集合
> SADD course Redis (integer) 1
SMEMBERS命令查询集合内容
SMEMBERS course 1)Redis
SISMEMBER命令查询元素是否存在
> SISMEMBER course Redis (integer) 1
SREM命令删除集合中的元素
> SREM course Redis (integer) 1
集合的运算
SINTER命令进行交集运算
> SADD course Redis (integer) 1 > SADD course JAVAS (integer) 1 > SADD course1 Redis (integer) 1 > SINTER course course1 1) "Redis"
SUNION命令进行并集运算
> SUNION course course1 1) "Redis" 2) "JAVAS" 3) "C#"
SDIFF命令进行差集运算
> SDIFF course1 course 1) "C#" > SDIFF course course1 1) "JAVAS"
SortedSet有序合集(ZSet)
有序集合与集合的区别是有序集合的每个元素都会关联一个浮点类型的分数,然后按照这个分数来对这个集合中的元素来进行从小到大的排序,有序集合的成员是唯一的,但是分数是可以重复的
命令
ZADD命令向有序集合中添加一个元素
> ZADD result 680 清华 660 北大 650 复旦 640 浙大 (integer) 4
ZRANGE命令查看元素
> ZRANGE result 0 -1 [WITHSCORES 添加后同时输出分数] 1) "浙大" 2) "复旦" 3) "北大" 4) "清华"
ZSCORE命令查询分数
> ZSCORE result 清华 "680"
ZRANK命令查看某个成员的排名
> ZRANK result 清华 (integer) 3//索引为3
ZREVRANK命令查看某个成员的反转排名
> ZREVRANK result 清华 (integer) 0
ZREM命令删除某个成员
> ZREM result 复旦 (integer) 1
哈希Hash
哈希是一个字符类型的字段和值的映射表,简单来说就是一个键值对的集合,特别适合用来储存对象
命令
HSET命令向哈希中添加一个键值对
> HSET person name yiye (integer) 1 > HSET person age 18 (integer) 1
HGET命令获取哈希中键值对的值
> HGET person name "yiye" > HGET person age "18"
HGETALL获取整个哈希中的所有键值对
> HGETALL person 1) "name" 2) "yiye" 3) "age" 4) "18"
HDEL删除键值对
> HDEL person age (integer) 1 > HGETALL person 1) "name" 2) "yiye"
HEXISTS命令来判断某个键值对是否存在
> HEXISTS person name (integer) 1 > HEXISTS person age (integer) 0
HKEYS命令获取哈希中的所有键
> HKEYS person 1) "name"
HLENS命令获取哈希中所有键值对的数量
> HLEN person (integer) 1
发布订阅模式
Redis提供了发布订阅模式的功能,通过PUBLISH命令来将消息发送到指定的频道,然后通过SUBSCRIBE命令来订阅这个频道,这样就可以接收到这个频道的消息了
使用:
打开一个终端,使用SUBSCRIBE命令订阅一个频道
在另外一个终端使用PUBLISH命令发送消息
订阅频道的终端可以有多个,但有局限性,例如消息无法持久化,无法记录历史信息等等
消息队列Stream
Stream是Redis5.0版本引入的一个新的数据结构,它是一个轻量级的的消息队列,可以用来解决发布订阅功能的一些局限性
命令
XADD,向Stream中添加消息
> XADD yiye * course redis "1694965560109-0" //*表示自动生成一个消息的ID
XLEB,查看Stream中消息的数量
> XLEN yiye (integer) 3
XRANGE查看Stream中的详细内容
> XRANGE yiye - + 1) 1) "1694965560109-0" 2) 1) "course" 2) "redis" 2) 1) "1694965632269-0" 2) 1) "course" 2) "git" 3) 1) "1694965641518-0" 2) 1) "course" 2) "Ngix"
可以使用XDEL命令来删除消息、
> XDEL yiye 1694965641518-0 (integer) 1 > XRANGE yiye - + 1) 1) "1694965560109-0" 2) 1) "course" 2) "redis" 2) 1) "1694965632269-0" 2) 1) "course" 2) "git"
XTRIM命令来删除
> XTRIM yiye MAXLEN 0//MAXLEN指所有的消息 (integer) 2 > XRANGE yiye - + (empty list or set)
自己设置ID
> XADD yiye 1-0 course git "1-0" > XADD yiye 2-0 course docker "2-0" > XADD yiye 3-0 course redis "3-0" //ID的格式是一个整数加上短横线再加上一个整数,第一个整数表示一个时间戳,第二个整数表示一个序列号
XREAD命令来读取消息(消费者需要从消息队列中读取消息,以消费消息(处理消息))
> XREAD COUNT 2 BLOCK 1000 STREAMS yiye 0 1) 1) "yiye" 2) 1) 1) "1-0" 2) 1) "course" 2) "git" 2) 1) "2-0" 2) 1) "course" 2) "docker" //COUNT 2表示读取两个消息 //BLOCK 1000 表示如果没有就阻塞1000毫秒/1秒 //STREAMS yiye 0 从STREAM的第一条消息开始读取 //可以重复读取 //将0改为$则接收最新的消息
XGROUP CREATE 建立消费者组
> XGROUP CREATE yiye group1 0 "OK" //yiye指Stream //group1为消费者组的名称 //0为消费者组的ID
XINFO GROUPS来查看消费者组的信息
> XINFO GROUPS yiye 1) 1) "name" 2) "group1" 3) "consumers" 4) "0" 5) "pending" 6) "0" 7) "last-delivered-id" 8) "0-0"
XGROUP CREATECONSUMER 添加消费者
XGROUP CREATECONSUMER yiye group1 consumer1 XGROUP CREATECONSUMER yiye group1 consumer2 XGROUP CREATECONSUMER yiye group1 consumer3
XREADGROUP GROUP读取消费者组的消息
XREADGROUP GROUP group1 consumer1 COUNT 2 BLOCK 1000 STREAMS yiye >//读取最新消息
SpringBoot使用Redis作为缓存
安装依赖
修改配置文件
server.port=8080 spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.database=0
实体类序列化
@Data public class User implements Serializable { private Integer id; private String username; private String password; }
在Application类上添加启用缓存注解
@SpringBootApplication @EnableCaching//启用缓存 public class RedisDemoApplication { public static void main(String[] args) { SpringApplication.run(RedisDemoApplication.class, args); } }
业务逻辑层
@Service public class UserServiceImpl implements UserService { @Override @Cacheable(value = "user",key = "#id",unless = "#result=null") public User getUserById(Integer id) { System.out.println("访问数据库得到数据对象"); User user = new User(); user.setId(id); return user; } @Override @CacheEvict(value = "user",key = "#id") public int deleteById(Integer id) { return 0; } }
测试
@SpringBootTest class RedisDemoApplicationTests { @Autowired private UserService userService; @Test void testGetById() { User user = userService.getUserById(20); System.out.println(user); } @Test void testDel(){ int i = userService.deleteById(20); System.out.println(i); } }
注解
- @Cacheable:用于标记一个方法的返回值是可以缓存的,当一个支持缓存的方法在执行后,它的结果会被存储在缓存中,以便后续的调用可以直接从缓存中获取结果,而不是在再执行该方法
- value:缓存的名称,用于识别不同的缓存区域
- key:用于从缓存中查找值的键,键是一个SpEL表达式,用于动态计算储存键
- unless:也是一个SpEL表达式,用于指定在什么情况下不应该缓存方法的返回值
- @Cacheable:用于标记一个方法的返回值是可以缓存的,当一个支持缓存的方法在执行后,它的结果会被存储在缓存中,以便后续的调用可以直接从缓存中获取结果,而不是在再执行该方法
SpringBoot中RedisTemplate
概述
RedisTemplate是一个非常强大的工具,用于与Redis数据库进行交互,它提供了一系列的方法来进行Redis的常见操作,如:设置(set)、获取(get)、删除(delete)等
使用
添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
配置
server.port=8080 spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.database=0
测试
@SpringBootTest class RedisDemoApplicationTests { @Autowired private UserService userService; @Autowired private RedisTemplate<String,Object> redisTemplate; @Test void testGetById() { User user = userService.getUserById(20); System.out.println(user); } @Test void testDel(){ int i = userService.deleteById(20); System.out.println(i); } @Test void RedisTemplate(){ redisTemplate.opsForValue().set("myName666","tom"); } }
自定义RedisTemplate
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(){
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
RedisTemplate<String,Object> template = new RedisTemplate<>();
jedisConnectionFactory.setHostName("127.0.0.1");
jedisConnectionFactory.setPort(6379);
jedisConnectionFactory.afterPropertiesSet();
template.setConnectionFactory(jedisConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
return template;
}
}