Redis笔记01

Posted by RyoCY on 2025-08-01
Estimated Reading Time 12 Minutes
Words 2.9k In Total
Viewed Times

黑马程序员Redis课程笔记

基础篇

NoSQL

分类

  • 键值类型(Redis)

  • 文档类型(MongoDB)

  • 列类型(HBase)

  • Graph类型(Neo4j)

与SQL区别

---------- SQL NoSQL
数据结构 结构化 非结构化
数据关联 关联的 无关联
查询方式 SQL查询 非SQL
事务特性 ACID BASE
存储方式 磁盘 内存
拓展性 垂直 水平
使用场景 数据结构固定,对数据安全性要求高 数据结构结构不固定,安全性要求不高,对性能有要求

Redis

Redis诞生于2009年全称是Remote Dictionary Server,远程词典服务器,是一个基于内存的键值型NoSQL数据库。

特征

  • 键值(key-value)型,value支持多种不同数据结构,功能丰富

  • 单线程,每个命令具备原子性

  • 低延迟,速度快(基于内存、O多路复用、良好的编码)

  • 支持数据持久化支持主从集群、分片集群

  • 支持多语言客户端

数据结构

Redis是典型的key-value数据库,key一般是字符串,而value包含很多不同的数据类型。

数据类型 示例
String hello world
Hash {“name”:“Jack”,“age”:21}
List [A->B->C->C]
Set {A,B,C}
SortedSet {A:1,B:2,C:3]
GEO {A:(120.3,30.5)]
BitMap 0110110101110101011
HyperLog 0110110101110101011

命令

进入redis官网查看常用命令

键管理

命令 语法示例 说明
DEL DEL key1 key2 删除一个或多个键。
EXISTS EXISTS key 检查键是否存在(返回 1 或 0)。
EXPIRE EXPIRE key 60 设置键的过期时间(秒)。
TTL TTL key 查看键的剩余生存时间(秒,-1 表示永久,-2 表示已过期)。
KEYS KEYS pattern* 查找匹配模式的键(生产环境慎用,可能阻塞)。

字符串

value是字符串,根据字符串的格式不同分为3类:

  • string:普通字符串,例如 hello world

  • int:整数类型,可以做自增、自减操作,例如 10

  • float:浮点类型,可以做自增、自减操作,例如 92.5

底层都以字节数组形式存储,最大空间不超过512m。

命令 语法示例 说明
SET SET key value 设置键值对,可覆盖之前的值
GET GET key 获取键的值。
INCR INCR key 将键的值递增 1(原子操作)。
MSET MSET k1 v1 k2 v2 批量设置多个键值对。
MGET MGET k1 k2 根据多个key获取多个String类型的value
SETNX SETNX newkey value 添加一个String类型的键值对,前提是这个key不存在,否则不执行
SETEX SETEX key seconds value 添加一个String类型的键值对,并指定有效期

Key的层级形式

Redis的key允许有多个单词形成层级结构,多个单词之间用:隔开,格式如下:

  • 项目名:业务名:类型:id

格式也可以根据需求修改。例如如果项目名叫program,有user和product两种不同类型的数据,我们可以这样定义key:

  • user相关的key:program:user:1

  • product相关的key:program:product:1

如果value是一个Java对象,例如一个User对象,则可以将对象序列化为JSON字符串后存储

KEY VALUE
program:user:1 {“id”:1, “name”: “Ryo”, “age”: 21}
program:product:1 {“id”:1, “name”: “咖啡”, “price”: 19}

Hash类型

  • Hash类型,也叫散列,其中value是一个无序字典,类似于Java中的HashMap结构

  • String结构是将对象序列化为JSON字符串后存储,不方便修改对象的某个属性值

  • Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD

KEY field value
program:user:1 name Ryo
age 21
program:user:2 name Tsugu
age 18

Hash的常见命令:

命令 语法示例 说明
HSET HSET key field value 添加或者修改hash类型key的field的值
HGET HGET key field 获取一个hash类型key的field的值
HMSET HMSET key field1 value1 field2 value2 批量添加多个hash类型key的field的值
HMGET HMGET key field1 field2 批量获取多个hash类型key的field的值
HGETALL HGETALL key 获取一个hash类型的key中的所有的field和value
HKEYS HKEYS key 获取一个hash类型的key中的所有的field
HVALS HVALS key 获取一个hash类型的key中的所有的value
HINCRBY HINCRBY key field increment 让一个hash类型key的字段值自增并指定步长
HSETNX HSETNX key field value 添加一个hash类型的key的field值,前提是这个field不存在,否则不执行

List类型

Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。特征也与LinkedList类似:

  • 有序

  • 元素可以重复

  • 插入和删除快

  • 查询速度一般

常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。

命令 语法示例 说明
LPUSH LPUSH key element1 element2 向列表左侧插入一个或多个元素
LPOP LPOP key 移除并返回列表左侧的第一个元素,没有则返回 nil
RPUSH RPUSH key element1 element2 向列表右侧插入一个或多个元素
RPOP RPOP key 移除并返回列表右侧的第一个元素
LRANGE LRANGE key start end 返回列表中指定下标范围内的所有元素(支持负数下标,如 -1 表示末尾)
BLPOP BLPOP key1 key2 timeout 阻塞式移除并返回列表左侧第一个元素,无元素时等待指定时间(秒)
BRPOP BRPOP key1 key2 timeout 阻塞式移除并返回列表右侧第一个元素,无元素时等待指定时间(秒)

Set类型

Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。因为也是一个hash表,因此具备与HashSet类似的特征:

  • 无序

  • 元素不可重复

  • 查找快

  • 支持交集、并集、差集等功能

命令 语法示例 说明
SADD SADD key member1 member2 向集合中添加一个或多个元素
SREM SREM key member1 member2 从集合中移除一个或多个指定元素
SCARD SCARD key 返回集合中元素的数量(基数)
SISMEMBER SISMEMBER key member 判断指定元素是否是集合的成员
SMEMBERS SMEMBERS key 获取集合中的所有元素
SINTER SINTER key1 key2 返回多个集合的交集
SDIFF SDIFF key1 key2 返回第一个集合与其他集合的差集
SUNION SUNION key1 key2 返回多个集合的并集

SortedSet类型

Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。

SortedSet具备下列特性:

  • 可排序

  • 元素不重复

  • 查询速度快

因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。

命令 语法示例 说明
ZADD ZADD key score1 member1 [score2 member2] 添加一个或多个元素到有序集合,若已存在则更新其score
ZREM ZREM key member1 [member2] 删除有序集合中的一个或多个指定元素
ZSCORE ZSCORE key member 获取有序集合中指定元素的分数
ZRANK ZRANK key member 获取指定元素的排名(按分数升序,从 0 开始)
ZREVRANK ZREVRANK key member 获取指定元素的排名(按分数降序,从 0 开始)
ZCARD ZCARD key 获取有序集合的元素个数
ZCOUNT ZCOUNT key min max 统计分数在范围内的元素数量
ZINCRBY ZINCRBY key increment member 指定元素自增,步长为指定的increment值
ZRANGE ZRANGE key start stop 按分数升序返回排名在范围之间的元素
ZREVRANGE ZREVRANGE key start stop 按分数降序返回排名在范围之间的元素
ZRANGEBYSCORE ZRANGEBYSCORE key min max 返回分数在范围之间的元素(升序)
ZDIFF ZDIFF numkeys key1 key2 计算多个有序集合的差集
ZINTER ZINTER numkeys key1 key2 计算多个有序集合的交集
ZUNION ZUNION numkeys key1 key2 计算多个有序集合的并集

Redis的Java客户端

目前主流的Redis的Java客户端:

  • Jedis:以Redis命令作为方法名称,学习成本低,简单实用。但是Jedis实例是线程不安全的,多线程环境下需要基于连接池来使用。

  • Lettuce:基于Netty实现的,支持同步、异步和响应式编程方式,并且是线程安全的。支持Redis的哨兵模式、集群模式和管道模式。

  • Redisson:基于Redis实现的分布式、可伸缩的Java数据结构集合。包含诸如Map、Queue、Lock、Semaphore、AtomicLong等强大功能。

Jedis

在maven中引入依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>

创建单元测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private Jedis jedis;

@BeforeEach
void setUp() {
//1. 建立连接
jedis = new Jedis("127.0.0.1", 6379);
//2. 设置密码
jedis.auth("123456");
//3. 选择库
jedis.select(0);
}

@Test
void testString(){
jedis.set("name","Ryo");
String name = jedis.get("name");
System.out.println("name = " + name);
}

@Test
void testHash(){
jedis.hset("Test:user:1","name","Ryo");
jedis.hset("Test:user:2","name","Lily");
jedis.hset("Test:user:1","age","21");
jedis.hset("Test:user:2","age","18");
Map<String, String> map = jedis.hgetAll("Test:user:1");
System.out.println(map);
}

//释放资源
@AfterEach
void tearDown(){
if (jedis != null){
jedis.close();
}
}

Jedis连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,推荐使用Jedis连接池代替直连方式。

首先在main文件夹下创建一个工具类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class JedisConnectionFactory {
private static final JedisPool jedisPool;

static {
// 配置连接池
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(8);
poolConfig.setMaxIdle(8);
poolConfig.setMinIdle(0);
poolConfig.setMaxWaitMillis(1000);
jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379, 1000, "123456");
}

public static Jedis getJedis(){
return jedisPool.getResource();
}
}

随后可以在单元测试中使用:

1
jedis = JedisConnectionFactory.getJedis();

SpringDataRedis

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis。

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)

  • 提供了RedisTemplate统一API来操作Redis

  • 支持Redis的发布订阅模型

  • 支持Redis哨兵和Redis集群

  • 支持基于Lettuce的响应式编程

  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化

  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中。

API 返回值类型 说明
redisTemplate.opsForValue() ValueOperations 操作String类型数据
redisTemplate.opsForHash() HashOperations 操作Hash类型数据
redisTemplate.opsForList() ListOperations 操作List类型数据
redisTemplate.opsForSet() SetOperations 操作Set类型数据
redisTemplate.opsForzSet() ZSetOperations 操作SortedSet类型数据
redisTemplate 通用的命令
  1. 在maven中引入依赖:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--common-pool-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
  1. 配置文件:

1
2
3
4
5
6
7
8
9
10
11
spring:
redis:
host: 127.0.0.1
port: 6379
password: 123456
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 100ms
  1. 编写测试

1
2
3
4
5
6
7
8
9
   @Autowired
private RedisTemplate redisTemplate;

@Test
void testString(){
redisTemplate.opsForValue().set("NAME", "Ryoo");
Object name = redisTemplate.opsForValue().get("NAME");
System.out.println("NAME = " + name);
}

RedisTemplate写入前会把Object序列化为字节形式,默认是采用JDK序列化,例如:

1
2
127.0.0.1:6379> get "\xac\xed\x00\x05t\x00\x04NAME"
"\xac\xed\x00\x05t\x00\x04Ryoo"

可以自定义RedisTemplate的序列化方式