一.Redis通用命令:
1.redis-cli:在使用redis命令前,需要启动redis客户端,在redis安装目录下执行,会连接本地的 redis 服务:
注意:Redis 服务器本身不提供直接的交互式命令行,因此如果你想要执行 Redis 命令,就需要使用 redis-cli 或其他支持 Redis 协议的客户端来与服务器进行通信。redis-cli 提供了一个方便的方式来执行 Redis 命令,而不需要编写额外的代码或使用其他工具。redis-cli 是 Redis 提供的一个官方命令行工具,它可以让你直接在终端输入 Redis 命令,并将其发送到 Redis 服务器进行执行。
2.SET key名称 key值:创建redis,名称为name,值为343如下:
3.TTL key名称:查看某个key的缓存有效时间,以秒为单位。
-1:表示没有设置过期时间,永久有效
-2:没有这个key的缓存
445333:表示445333秒后该缓存key过期
4.EXISTS key名称:判断key是否存在。
1:存在
0:不存在
5.EXPIRE key名称 过期时间秒:给一个key设置有效期,有效期到期时该key会被自动删除,成功返回1。
6.DEL key名称:删除一个指定的key,成功返回1。
7.help 命令名称:查看命令的作用(用法)
二.redis数据结构:
redis是一个key-value的数据库,key一般是String类型,value的类型多种多样如下:
1.String类型:
String类型,也就是字符串类型,是Redis中最简单的存储类型是value是字符串,不过根据字符串的格式不同,又可以分为3类:
string :普通字符串
int :整数类型,可以做自增、自减操作
float: 浮点类型,可以做自增、自减操作
不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过512m
String类型的常见命令
SET :添加或者修改已经存在的一个String类型的键值对(set k1 Rose
添加一个key为k1,值为Rose的数据)
GET :根据key获取String类型的value(get k1
获取key为k1的值)
MSET :批量添加多个String类型的键值对(MSET k1 v1 k2 v2
新增key为k1,值为v1的数据和key为k2,值为V2的数据)
MGET :根据多个key获取多个String类型的value(MGET k1 k2
获取key为k1,k2的值)
INCR :让一个整型的key自增1(INCR age
让key为age的值自增1)
INCRBY :让一个整型的key自增并指定步长,例如:incrby num 2
让num值自增2
(INCRBY age 2
把key为age的值自增2, INCRBY age -1
把key为age的值自减1)
INCRBYFLOAT :让一个浮点类型的数字自增并指定步长(INCRBYFLOAT score 0.5
把key为score的值自增0.5)
SETNX :添加一个String类型的键值对,前提是这个key不存在,否则不执行(SETNX name2 lisi
新增key为name2,值为lisi的数据,只有本来没有name2这个key才会新增成功)
SETEX :添加一个String类型的键值对,并且指定有效期(setex name 10 jack
新增一个key为name,值为jack的数据,有效期为10秒)
注意:key的命名不仅仅是当个单词,也可以加冒号隔开等
- Redis的key的格式可以分项目分业务分类保存:项目名]:[业务名]:[类型]:[id]
- (set heima:user:2 '{"id" :2,"name": "Rose" ,"age": 18}' 新增key为heima:user:2,值为一个'{"id" :2,"name": "Rose" ,"age": 18}'的json数据的信息。
2. Hash类型:
Hash类型,也叫散列,其value是一个无序字典,类似于Java中的HashMap结构
String结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段时很不方便:
Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD:
Hash类型常用命令:
HSET key field value : 添加或者修改hash类型key的field的值(HSET heima:user:3 name Lucy
创建一个key为heima:user:3,Hash的field为name ,值为Lucy的数据)
HGET key field :获取一个hash类型key的field的值(HGET heima:user:3 age
获取key为heima:user:3 ,Hash的field为age的值)
**HMSET:**批量添加多个hash类型key的field的值(HMSET heima:user:4 name LiLei age 20
创建key为 heima:user:4 Hash的field为name ,值我为LiLei的数据和 Hash的field为age,值为20的数据)
HMGET :批量获取多个hash类型key的field的值(HMGET heima:user:4 name age sex
获取key为 heima:user:4 Hash的field为name ,age, sex的三个值)
HGETALL :获取一个hash类型的key中的所有的field和value(HGETALL heima:user:4
获取key为heima:user:4的所有的field和value)
HKEYS :获取一个hash类型的key中的所有的field(HKEYS heima:user:4
获取key为heima:user:4的所有的field)
HVALS :获取一个hash类型的key中的所有的value( HVALS heima:user:4
获取key为heima:user:4的所有的value)
HINCRBY :让一个hash类型key的字段值自增并指定步长(HINCRBY heima:user:4 age 2
把key为heima:user:4的field为age的值自增2。-2 是自减2)
HSETNX :添加一个hash类型的key的field值,前提是这个field不存在,否则不执行(HSETNX heima:user:4 sex woman
新增key为heima:user:4,field为sex,值为woman的数据,只有在这个可以中本来没有field为sex的时候才会新增成功)
以上数据的创建与获取如下:
3. List类型:
Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。
特征也与LinkedList类似:
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一般
List类型常用命令:
LPUSH key element... :向列表左侧插入一个或多个元素(LPUSH users 1 2 3
新增key为users,值顺序为3 2 1的数据)
LPOP key : 移除并返回列表左侧的第一个元素,没有则返回nil(LPOP users 1
删除key为users的从左边开始的第一个数据,并返回这个删除的数据的值)
RPUSH key element... :向列表右侧插入一个或多个元素(RPUSH users 1 2 3
新增key为users,值顺序为1 2 3的数据)
RPOP key :移除并返回列表右侧的第一个元素(RPOP users 1
删除key为users的从右边开始的第一个数据,并返回这个删除的数据的值)
LRANGE key star end :返回一段角标范围内的所有元素(LRANGE users 1 2
获取key为users的左边开始第一到第二个数据,都包含)
BLPOP和BRPOP :与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil(BLPOP users2 100
删除key为users2的数据,没有找到就等待100秒)
创建以上List类型的redis数据方式如下:
4. Set类型:
Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。因为也是一个hash表,因此具备与HashSet类似的特征:
- 无序
- 元素不可重复
- 查找快
- 支持交集、并集、差集等功能
Set类型的常用命令:
SADD key member ... :向set中添加一个或多个元素(sadd s1 a b c
新增key为s1的set 添加 a b c值)
SREM key member... :移除set中的指定元素(SREM s1 a
删除key为s1的a值)
SCARD key : 返回set中元素的个数(SREM s1
返回key为s1的元素个数)
SISMEMBER key member :判断一个元素是否存在于set中(SISMEMBER S1 b
判断b元素是否存在key为s1的set中)
SMEMBERS :获取set中的所有元素(SMEMBERS S1
获取key为s1的所有元素)
SINTER key1 key2...:求key1与key2的交集
SDIFF key] key2...:求key1与key2的差集
SUNION key1 key2...:求key1和key2的并集
5. SortedSet类型
Redis的SortedSet是一个可排序的set集合,与]ava中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。
SortedSet具备下列特性:
- 可排序
- 元素不重复
- 查询速度快
因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。
SortedSet类型常用命令:
ZADD key score member: 添加一个或多个元素到sorted set,如果已经存在则更新其score值(ZADD stus 85 Jack 89 Lucy
添加一个key为stus,姓名为Jack分数为85 和 姓名为Lucy分数为89 的数据)
ZREM key member :删除sorted set中的一个指定元素(ZREM stus Tom
删除key为stus,姓名为Tom的数据)
ZSCORE key member :获取sorted set中的指定元素的score值(ZSCORE stus Rose
获取key为stus,姓名为Rose的元素的分数)
ZRANK key member: 获取sorted set 中的指定元素的排名(ZRANK stus Rose
获取key为stus,姓名为Rose的元素的排名)
ZCARD key :获取sorted set中的元素个数(ZCARD stus
获取key为stus的元素个数)
ZCOUNT key min max :统计score值在给定范围内的所有元素的个数(ZCOUNT stus 0 80
获取key为stus的分数为0到80分的元素个数)
ZINCRBY key increment member: 让sorted set中的指定元素自增,步长为指定的increment值(ZINCRBY stus 2 Amy
把key为stus,姓名为Amy的分数自增2)
ZRANGE key min max :按照score排序后,获取指定排名范围内的元素(ZRANGE stus 0 2
获取key为stus分数为后三名的姓名。 ZREVRANGE stus 0 2
获取key为stus分数为前三名的姓名。)
ZRANGEBYSCORE key min max: 按照score排序后,获取指定score范围内的元素(ZRANGEBYSCORE stus 0 80
获取key为stus分数为0 到80的姓名)
ZDIFF、ZINTER、ZUNION: 求差集、交集、并集
注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可
创建以上缓存数据的命令如下:
三. 数据持久化
1. 什么是数据持久化:
在计算机领域,数据持久化通常指的是将内存中的数据写入到硬盘或其他持久性存储介质中,以便在系统重启或断电后能够重新加载和使用这些数据。
2. redis的数据持久化:
在 Redis 中,数据持久化是指将内存中的数据以某种格式写入到硬盘上的文件中,以便在 Redis 服务器重启时能够重新加载数据,保证数据的持久性和可靠性。Redis 支持两种数据持久化方式:
- RDB(Redis Database Backup) :RDB 是一种周期性地将内存中的数据以快照的形式写入到硬盘上的文件中的方式。它会在指定的时间间隔内生成一个快照文件,记录了某一时刻的 Redis 数据库状态。RDB 文件是一个二进制文件,通常以 .rdb 扩展名结尾。
- AOF(Append-Only File) :AOF 是一种将 Redis 服务器接收到的每一条写命令追加到文件末尾的方式。它以日志的形式记录了服务器接收到的所有写操作,包括对数据的增、删、改操作。AOF 文件是一个文本文件,内容是 Redis 命令的序列,可以通过文本编辑器进行查看和修改。
3. 数据持久化:
4. 什么是RDB: RDB是Redis内存到硬盘的快照,用于持久化。
RDB三种触发机制:
save(同步):生成RDB文件,如存在旧的RDB文件,新替换旧文件。在执行这个命令后,再执行redis其他命令会阻塞,等RDB文件生成完成后,其他命令才能进行。
bgsave(异步):生成RDB文件,如存在旧的RDB文件,新替换旧文件。在执行这个命令后,再执行redis其他命令不会阻塞,其他命令与这个命令异步进行。会fork新进程,需要消耗内存空间。
save与bgsave命令区别:
自动:在redis.conf文件配置下面内容,会根据配置生成RDB文件。满足任一就会被执行。
5. 什么是AOF:
AOF 是一种持久化方式,它以追加的方式记录所有写操作命令,将它们追加到文件的末尾,以确保持久化数据的安全性。
AOF三种策略:
always:每条命令执行就复制命令硬盘。
everysec :每秒复杂命令到硬盘。
no :由操作系统控制。
三者区别:
AOF重写: AOF(Append Only File)重写是 Redis 中的一种机制,用于优化 AOF 持久化文件的大小和性能。AOF 重写的目的是通过重新写入一份与当前数据集完全相同的 AOF 文件来解决这个问题,但新文件的体积要比原来的文件小得多。AOF 重写并不是简单地将现有的 AOF 文件拷贝到另一个文件中,而是通过读取内存中的数据,生成一系列的命令,然后将这些命令按照一定的格式写入新的 AOF 文件中。在这个过程中,会去除一些可以简化的命令。
作用
- 减少硬盘占用量
- 加速恢复速度
两种方式:
- bgrewriteaof命令
- AOF重写配置:在redis.conf文件配置下面内容,会根据配置生成RDB文件。两个都满足才会被执行。
6. RDB与AOC的区别:
7. fork 操作:
-
在 Redis 中,fork 是指创建子进程来执行持久化操作。比如生成 RDB 快照或者执行 AOF 文件重写,Redis 使用 fork 来创建子进程,然后在子进程中执行持久化操作,而父进程则继续处理客户端请求。这种方式可以避免持久化操作对 Redis 服务器的性能造成影响,因为持久化操作通常会消耗大量的 CPU 和内存资源。
-
然而,fork 操作并不总是高效的,特别是在数据集较大时。因为在 fork 过程中,操作系统会将父进程的内存页复制一份给子进程,这会消耗大量的时间和内存。当数据集很大时,这种复制操作会变得非常昂贵,可能会导致 Redis 在 fork 过程中出现阻塞,影响 Redis 的响应能力和性能。
优化 fork 操作:
- 使用延迟化持久化:延迟持久化可以将持久化操作推迟到更合适的时机执行,比如在闲时或者低峰期。
- 增加物理内存:增加服务器的物理内存可以减少 fork 过程中的内存页复制操作,提高 fork 的效率。
- 使用专用持久化服务器:将持久化操作分离到专用的持久化服务器上,可以避免持久化操作对主服务器性能的影响。
- 使用 Copy-On-Write(写时复制)技术:Copy-On-Write 是一种技术,它可以延迟内存页的复制操作,直到有进程试图修改这些页。在 Redis 中,可以通过操作系统的 Copy-On-Write 功能来减少 fork 过程中的内存复制开销。
四. redis复制
1.主从复制:
Redis 主从复制是一种数据复制和同步机制,用于在不同的 Redis 服务器之间保持数据的一致性和高可用性。在主从复制中,有一个主服务器(master)和一个或多个从服务器(slave)。主服务器负责接收写操作并将数据同步到从服务器,而从服务器则复制主服务器的数据,并可以处理读请求,以提供更好的性能和可扩展性。
2. 主从复制的主要特点:
- 数据同步 :主服务器将写操作记录在自己的 AOF 文件中,同时将写操作发送给所有从服务器。从服务器接收到写操作后,执行相同的写操作,以保持数据的一致性。
- 读写分离 :从服务器可以处理读请求,减轻主服务器的负载。客户端可以向任意一个从服务器发送读请求,从服务器会返回最新的数据。这样可以提高系统的读取性能和扩展性。
- 故障转移 :如果主服务器发生故障,可以通过将一个从服务器升级为主服务器来实现故障转移。这样可以保持系统的可用性,并确保数据不丢失。
- 扩展性 :通过添加更多的从服务器,可以扩展系统的读取性能和容量。从服务器可以分担主服务器的读取负载,从而提高系统的整体性能。
- 复制链 :从服务器可以成为其他从服务器的主服务器,从而形成复制链。这样可以实现级联复制,使数据在不同的层次之间进行复制和同步。
三. redis慢查询
生命周期:
慢查询:发生在第3阶段
- 客户端超时不一定慢查询,但慢查询是客户端超时的一个可能因素
四. Redis的java客户端Jedis:
1.Jedis:
Jedis官网地址:https://github.com/redis/jedis
2.Jedis 和 Redis 之间的关系:
- Jedis 是 Redis 的客户端库:Jedis 不是 Redis 本身,而是一个由 Java 编写的客户端库,用于连接和与 Redis 服务器进行通信。它提供了一组 API 来执行 Redis 命令,从而让 Java 程序能够与 Redis 交互。
- Jedis 是 Redis 的官方支持的 Java 客户端之一:虽然 Redis 本身是用 C 语言编写的,但是 Redis 社区提供了许多官方和第三方的客户端库,用于各种编程语言。Jedis 是其中一个由 Redis 开发团队维护的官方 Java 客户端库之一。
- Jedis 提供了丰富的功能和易用的 API:Jedis 不仅仅是一个简单的 Redis 协议的封装,它还提供了一些高级功能,比如连接池管理、数据类型的序列化和反序列化、Pipeline 等。这些功能使得在 Java 中使用 Redis 变得更加方便和高效。
3.Jedis案例:
(1)创建maven工程,引入依赖pom.xml:
bash
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cyj.study</groupId>
<artifactId>JedisDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.0</version>
</dependency>
<!-- 单元测试 -->
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
(2)建立连接,测试与释放资源 JedisTest.java
bash
package com.cyj.study;
import com.cyj.study.util.JedisConnectionFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
import java.util.Map;
public class JedisTest {
private Jedis jedis;
@BeforeEach
void setup() {
//1.建立连接
// jedis = new Jedis("127.0.0.1", 6379); //没有工具类时(Jedis的直连方式)
jedis = JedisConnectionFactory.getJedis(); //自己有创建JedisConnectionFactory工具类时(Jedis连接池)
//2.密码(redis没有密码时不用写)
//jedis.auth("111111");
//3.选择库
jedis.select(0);
}
@Test
void testString() {
//存入数据
String result = jedis.set("name", "LiLi");
System.out.println("result = " + result);
//获取数据
String name = jedis.get("name");
System.out.println("name = " + name);
}
@Test
void testHash() {
// 插入hash数据
jedis.hset("user:1","name","Jack");
jedis.hset("user:1", "age","21");
// 获取
Map<String, String> map = jedis.hgetAll("user:1");
System.out.println(map);
}
@AfterEach
void tearDown() {
if (jedis != null) {
jedis.close();
}
}
}
结果;
使用Jedis连接池方式时,需要创建一个Jedis连接池工具类 JedisConnectionFactory.java:
bash
package com.cyj.study.util;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* @author AUAS
*/
public class JedisConnectionFactory {
//Jedis连接池
private static final JedisPool jedisPool;
static {
//配置连接池
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大连接
jedisPoolConfig.setMaxTotal(8);
// 最大空闲连接
jedisPoolConfig.setMaxIdle(8);
// 最小空闲连接
jedisPoolConfig.setMinIdle(0);
// 设置最长等待时间, 毫秒
jedisPoolConfig.setMaxWaitMillis(1000);
//创建连接池对象
jedisPool = new JedisPool(jedisPoolConfig,
"127.0.0.1", 6379, 1000);
}
/**
* 获取Jedis对象
*/
public static Jedis getJedis() {
return jedisPool.getResource();
}
}
注意:Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式。
四.Redis的java客户端SpringData
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis
官网地址: https://spring.io/projects/spring-data-redis
- 1.提供了对不同Redis客户端的整合 (Lettuce和Jedis)
- 2.提供了RedisTemplate统一API来操作Redis
- 3.支持Redis的发布订阅模型
- 4.支持Redis哨兵和Redis集群
- 5.支持基于Lettuce的响应式编程支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列
- 6.支持基于Redis的IDKCollection实现
SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:
SpringBoot已经提供了对SpringDataRedis的支持,使用非常简单。
1.SpringDataRedis案例:
(1)引入依赖pom.xml:
bash
<!--Redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--连接池依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
(2)配置文件
(3) 注入RedisTemplate
(4)测试