Redis入门

Redis

一、Redis入门
1.NoSQL

不仅仅指sql,泛指非关系型数据库。

2.NoSQL的四大分类
2.1键值(key-value)存储数据库

1.说明:

- 这一类数据库主要会使用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。

2.特点

- Key/value模型对于IT系统来说的优势在于简单、易部署。

- 但是如果DBA只对部分值进行查询或更新的时候,Key/value就显得效率低下了。

3.相关产品

- Tokyo Cabinet/Tyrant,

- Redis

- SSDB

- Voldemort

- Oracle BDB

2.1列存储数据库

# 1.说明

- 这部分数据库通常是用来应对分布式存储的海量数据。

# 2.特点

- 键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。

# 3.相关产品

- Cassandra、HBase、Riak.

2.3文档型数据库

# 1.说明

- 文档型数据库的灵感是来自于Lotus Notes办公软件的,而且它同第一种键值存储相类似该类型的数据模型是版本化

的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可 以看作是键值数据库的升级版,允许之间嵌

套键值。而且文档型数据库比键值数据库的查询效率更高

# 2.特点

- 以文档形式存储

# 3.相关产品

- MongoDB、CouchDB、 MongoDb(4.x). 国内也有文档型数据库SequoiaDB,已经开源。

2.4图形(Graph)数据库

# 1.说明

- 图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务

器上。

- NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数

据接口或者查询API。

# 2.特点

# 3.相关产品

- Neo4J、InfoGrid、 Infinite Graph、

3.NoSQL常用技术
  • Redis
  • MongoDB
4.什么是Redis

Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库数据是保存在内存里面的

4.1支持的数据类型
  • 字符串类型 String(常用)
  • 散列类型 hash 相当于map
  • 列表类型 list 相当于list
  • 集合类型 set 相当于set
  • 有序集合类型 sortedset 相当于treeSet
5.redis的应用场景
  • 缓存(数据查询、短连接、新闻内容、商品内容等,(缓存主要是针对增删改不频繁的数据))
  • 任务队列(秒杀、抢购、12306等)
  • 数据过期处理(可以精确到毫秒、短信验证码
  • 分布式集群架构中的session分离 session存在服务器里面的
  • 聊天室的在线好友列表
  • 应用排行榜
  • 网站访问统计
6.Redis安装
1、环境准备

vmware 15.X+

centos 7.x+

2、下载redis源码包

-https://redis/io/

3、下载完整原码包

redis-4.0.14.tar.gz

4、将下载redis资料包上传到Linux中
5、解压文件

tar -zxvf redis-4.0.14.tar.gz

6、安装gcc

yum install -y gcc

gcc:由c语言开发的编译器工具

7.进入解压缩目录执行如下命令进行源文件编译

cd redis-4.0.14

make

8.编译完成后执行如下命令

make install PREFIX=/usr/local/redis

9.进入/usr/local/redis/bin目录启动redis服务

./redis-server

./redis-server & 后台启动

10.Redis服务端口默认是 6379
11.进入bin目录执行客户端连接操作

./redis-cli –p 6379

12.连接成功出现上面界面连接成功

退出客户端命令:exit

7.配置文件设置
1.进入安装好的redis目录,复制配置文件

cd /usr/local/redis/bin

–这句命令的作用是将redis-4.0.14中的redis.conf文件拷贝到bin目录

cp /root/redis-4.0.14/redis.conf /user/local/redis/bin

2.修改配置文件
# 修改配置文件
vi redis.conf
# 修改端口
port xxxx
# Redis后台启动
修改 daemonize 为 yes
# Redis服务器可以跨网络访问
修改 bind 为 0.0.0.0
# 开启aof持久化,这个可以不做
appendonly yes
3.通过配置文件启动redis服务器

./redis-server redis.conf

4.退出redis服务

1.正常关闭本地redis:redis-cli shutdown,默认关闭本地6379的redis

2.如果正常关闭不了,可以通过杀死线程关闭

ps aux |grep redis 查看当前线程

kill - 9 57928 杀死redis线程

ps aux |grep redis 再查看目标线程是否还在

8.redis数据库相关指令
1.数据库操作指令

1.Redis中库说明

- 使用redis的默认配置器动redis服务后,默认会存在16个库,编号从0-15

- 可以使用select 库的编号 来选择一个redis的库

2.Redis中操作库的指令

- 清空当前的库 FLUSHDB

- 清空全部的库 FLUSHALL

3.redis客户端显示中文

- ./redis-cli -p 7000 --raw

2.操作key相关指令

1.DEL指令

- 语法 : DEL key [key …]

- 作用 : 删除给定的一个或多个key 。不存在的key 会被忽略。

- 可用版本: >= 1.0.0

- 返回值: 被删除key 的数量。

2.EXISTS指令

- 语法: EXISTS key

- 作用: 检查给定key 是否存在。

- 可用版本: >= 1.0.0

- 返回值: 若key 存在,返回1 ,否则返回0。

3.EXPIRE

- 语法: EXPIRE key seconds

- 作用: 为给定key 设置生存时间,当key 过期时(生存时间为0 ),它会被自动删除。

- 可用版本: >= 1.0.0

- 时间复杂度: O(1)

- 返回值:设置成功返回1 。

4.KEYS

- 语法 : KEYS pattern

- 作用 : 查找所有符合给定模式pattern 的key 。

- 语法:

KEYS * 匹配数据库中所有key 。

KEYS h?llo 匹配hello ,hallo 和hxllo 等。

KEYS h*llo 匹配hllo 和heeeeello 等。

KEYS h[ae]llo 匹配hello 和hallo ,但不匹配hillo 。特殊符号用 “” 隔开

- 可用版本: >= 1.0.0

- 返回值: 符合给定模式的key 列表。

5.MOVE

- 语法 : MOVE key db

- 作用 : 将当前数据库的key 移动到给定的数据库db 当中。

- 可用版本: >= 1.0.0

- 返回值: 移动成功返回1 ,失败则返回0 。

6.PEXPIRE

- 语法 : PEXPIRE key milliseconds

- 作用 : 这个命令和EXPIRE 命令的作用类似,但是它以毫秒为单位设置key 的生存时间,而不像EXPIRE 命令那样, 以秒为单位。

- 可用版本: >= 2.6.0

- 时间复杂度: O(1)

- 返回值:设置成功,返回1 key 不存在或设置失败,返回0

7.PEXPIREAT

- 语法 : PEXPIREAT key milliseconds-timestamp

- 作用 : 这个命令和EXPIREAT 命令类似,但它以毫秒为单位设置key 的过期unix 时间戳,而不是像EXPIREAT那样, 以秒为单位。

- 可用版本: >= 2.6.0

- 返回值:如果生存时间设置成功,返回1 。当key 不存在或没办法设置生存时间时,返回0 。(查看EXPIRE 命令获取 更多信息)

8.TTL

- 语法 : TTL key

- 作用 : 以秒为单位,返回给定key 的剩余生存时间(TTL, time to live)。

- 可用版本: >= 1.0.0

- 返回值:

当key 不存在时,返回-2 。

当key 存在但没有设置剩余生存时间时,返回-1 。

否则,以秒为单位,返回key 的剩余生存时间。

- Note : 在Redis 2.8 以前,当key 不存在,或者key 没有设置剩余生存时间时,命令都返回-1 。

9.PTTL

- 语法 : PTTL key

- 作用 : 这个命令类似于TTL 命令,但它以毫秒为单位返回key 的剩余生存时间,而不是像TTL 命令那样,以秒为单 位。

- 可用版本: >= 2.6.0

- 返回值: 当key 不存在时,返回-2 。当key 存在但没有设置剩余生存时间时,返回-1 。

- 否则,以毫秒为单位,返回key 的剩余生存时间。

- 注意 : 在Redis 2.8 以前,当key 不存在,或者key 没有设置剩余生存时间时,命令都返回-1 。

10.RANDOMKEY

- 语法 : RANDOMKEY

- 作用 : 从当前数据库中随机返回(不删除) 一个key 。

- 可用版本: >= 1.0.0

- 返回值:当数据库不为空时,返回一个key 。当数据库为空时,返回nil 。

11.RENAME

- 语法 : RENAME key newkey

- 作用 : 将key 改名为newkey 。当key 和newkey 相同,或者key 不存在时,返回一个错误。当newkey 已经存在 时,RENAME 命令将覆盖旧值。

- 可用版本: >= 1.0.0

- 返回值: 改名成功时提示OK ,失败时候返回一个错误。

12.TYPE

- 语法 : TYPE key

- 作用 : 返回key 所储存的值的类型。

- 可用版本: >= 1.0.0

- 返回值:

none (key 不存在)

string (字符串)

list (列表)

set (集合)

zset (有序集)

hash (哈希表)

9.String 类型
1.常用命令操作
命令说明
set设置一个key/value
get根据key获取对应的value
mset一次设置多个key value
mget一次获取多个key的value
getset获取原始key的值,同时设置新值
strlen获取对应key存储value的长度
append为对应key的value追加内容
getrange索引0开始截取value的内容,索引是以字节为单位
setex设置一个key存活的有效期(秒)
psetex设置一个key存活的有效期(毫秒)
setnx存在不做任何操作,不存在添加
msetnx原子操作(只要有一个存在不做任何操作)可以同时设置多个key,只有有一个存在都不保存
decr进行数据类型的-1操作
decrby根据提供的数据进行减法操作
incr进行数值类型的+1操作
incrby根据提供的数据进行加法操作
incrbyfloat根据提供的数据加入浮点数
10.List类型

list列表相当于java中list集合,特点元素有序且可以重复

1.常用操作指令
命令说明
lpush将某个值加入到一个key列表头部
ipushx同lpush,但是必须要保证这个key存在
rpush将某个值加入到一个key列表末尾
rpushx同rpush,单是必须要保证这个key存在
lpop返回和移除列表左边的第一个元素
rpop返回和移除列表右边的第一个元素
lrange获取某一个下标区间内的元素 区间0代表开始 -1代表最后
llen获取列表元素个数
lset设置某一个指定索引的值(索引必须存在)
lindex获取某一个指定位置的元素
lrem删除重复元素
ltrim保留列表中特定区间内的元素
linsert在某一个元素之前,之后插入新元素key BEFORE|AFTER pivot value
11.Set类型

特点:Set类型 Set集合 元素无序 不可以重复

1.常用命令
命令说明
sadd为集合添加元素
smembers显示集合中所有元素 无序
scard返回集合元素中元素的个数
spop随机返回一个元素,并将元素在集合中删除
smove从一个集合中向另一个几个移动元素 必须是同一种类型
srem从集合中删除指定的一个元素
sismember判断一个几个中是否含有这个元素,有返回1 没有返回0
srandmember随机返回元素
sdiff获取元素:去掉第一个集合中其他集合含有的相同元素,批量删除指定元素
sinter求交集:获取多个集合中都包含的数据
sunion求和集:将多个集合的元素一起取出,并且会去重
12.Zset类型

特点:可排序的set集合 排序 不可重复 相当于java中的treeSet

ZSET 官方 可排序SET sortSEt sorteSet

1.常用命令
命令说明
zadd添加一个有序集合元素
zcard返回集合的元素个数
zrange升序arevrange降序返回一个范围内的元素
zrangebyscore安装分数查找一个范围内的元素
zrank返回排名
zrevrank倒序排名
zscore显示某一个元素的分数
zrem移除某一个元素
zincrby给某个特定元素加分
13.hash类型

特点:value 是一个map结构 存在key value key 无序的

1.常用命令
命令说明
hset设置一个key/value队
hget获取一个key对应的value
hgetall获取所有的key/value对
hdel删除某一个key/value对
hexists判断一个key是否存在
hkeys获取所有的key
hvals获取所有的value
hmset设置多个key/value
hmget获取多个key的value
hsetnx设置一个不存在的key的值
hincrby为value进行加hset
hincrbyfloat为value加入浮点值
二、Redis持久化机制

client redis[内存] ----> 内存数据—>数据持久化—>磁盘

Redis官方提供了两种不同的持久化方法来将数据存储到硬盘里面,分别是:

  • 快照(Snapshot)
  • AOF(Append Only File) 只追加日志文件
1.快照
1、特点:

这种方式可以将某一时刻的所有数据都写入硬盘中,当然这也是redis的默认开启持久化方式,保存的文件是以.rdb形式结尾的文件,因此这种方式也称之为RDB方式

2、快照生成方式
  • 客户端方式:BGSAVE和SAVE指令
  • 服务器配置自动触发

1.客户端方式之BGSAVE

- a.客户端可以使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时,redis会调用fork¹来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求。

`名词解释: fork当一个进程创建子进程的时候,底层的操作系统会创建该进程的一个副本,在Linux系统中创建子 进程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后,对被写入的 内存的共享才会结束服务

2.客户端方式之SAVE

- b. 客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令

  • 注意:SAVE命令并不常用,使用SAVE命令在快照创建完毕之前,redis处于阻塞状态,无法对外提供服务

3.服务器配置方式之满足配置自动触发

- 如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令

4.服务器接收客户端shutdown指令

- 当redis通过shutdown指令接收到关闭服务器的请求时,会执行一个save命令,阻塞所有的客户端,不再执行客户端执行发送的任何命令,并且在save命令执行完毕之后关闭服务器

3、配置生成快照名称和位置

1.修改生成快照名称

dbfilename dump.rdb

2.修改生成位置

dir ./

2.AOF只追加日志文件
1、特点

这种方式可以将所有客户端执行的写命令记录到日志文件中,AOF持久化会将被执行的写命令写到AOF的 文件末尾,以此来记录数据发生的变化,因此只要redis从头到尾执行一次AOF文件所包含的所有写命令,就 可以恢复AOF文件的记录的数据集

2、开启AOF持久化

在redis的默认配置中AOF持久化机制是没有开启的,需要在配置中开启

1.开启AOF持久化机制

a.修改appendonly yes 开启持久化机制

b.修改appendfilename “appendonly.aof” 指定生成文件名称

3、日志追加频率

1.always (一直在开启)【谨慎使用】

- 说明: 每个redis写命令都要同步写入硬盘,严重降低redis速度

- 解释: 如果用户使用了always选项,那么每个redis写命令都会被写入硬盘,从而将发生系统崩溃时出现的数据丢失减到最少;遗憾的是,因为这种同步策略需要对硬盘进行大量的写入操作,所以redis处理命令的速度会受到硬盘性能的限制;

- 注意: 转盘式硬盘在这种频率下200左右个命令/s ; 固态硬盘(SSD) 几百万个命令/s;

- 警告: 使用SSD用户请谨慎使用always选项,这种模式不断写入少量数据的做法有可能会引发严重的写入放大问题,导 致将固态硬盘的寿命从原来的几年降低为几个月。

2.everysec (每秒一次)【推荐】

- 说明: 每秒执行一次同步显式的将多个写命令同步到磁盘

- 解释: 为了兼顾数据安全和写入性能,用户可以考虑使用everysec选项,让redis每秒一次的频率对AOF文件进行同步;redis每秒同步一次AOF文件时性能和不使用任何持久化特性时的性能相差无几,而通过每秒同步一次AOF文件,redis 可以保证,即使系统崩溃,用户最多丢失一秒之内产生的数据。

# 3.no 【不推荐】

- 说明: 由操作系统决定何时同步

- 解释:最后使用no选项,将完全由操作系统决定什么时候同步AOF日志文件,这个选项不会对redis性能带来影响但是系统崩溃时,会丢失不定数量的数据,另外如果用户硬盘处理写入操作不够快的话,当缓冲区被等待写入硬盘数据填满 时,redis会处于阻塞状态,并导致redis的处理命令请求的速度变慢。

4、修改同步频率

1.修改日志同步频率

修改appendfsync everysec|always|no 指定

例:appendfsync everysec

3.AOF文件的重写
1、AOF带来的问题

AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态,其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件Redis提供了AOF重写(ReWriter)机制。

2、AOF重写

用来在一定程度上减小AOF文件的体积

3、触发重写方式

1.客户端方式触发重写

- 执行BGREWRITEAOF命令 不会阻塞redis的服务

2.服务器配置方式自动触发

- 配置redis.conf中的auto-aof-rewrite-percentage选项 参加下图↓↓↓

- 如果设置auto-aof-rewrite-percentage值为100和auto-aof-rewrite-min-size 64mb,并且启用的AOF持久化时,那么 当AOF文件体积大于64M,并且AOF文件的体积比上一次重写之后体积大了至少一倍(100%)时,会自动触发,如果重写过于频 繁,用户可以考虑将auto-aof-rewrite-percentage设置为更大

4、重写原理

注意:重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重新写了一个新的aof文件,替换原来的文件,这点跟快照有点类似

重写流程:

- 1. redis调用fork ,现在有父子两个进程,子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令

- 2. 父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保 证如果子进程重写失败的话并不会出问题。

- 3. 当子进程把快照内容以命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。

- 4. 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KXcxFGtU-1687141250884)(C:\Users\WangQi\AppData\Roaming\Typora\typora-user-images\1686941773960.png)]

4.持久化总结

两种持久化方案既可以同时使用,又可以单独使用,在某种情况下也可以都不使用,具体使用那种持久化方案取决于用户的数据和应用决定

无论使用AOF还是快照机制持久化,将数据持久化到硬盘都是有必要的,除了持久化外,用户还应该对持久化的文件进行备份(最好备份在多个不同的地方)

三、Java操作Redis

Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java、C、C#、C++、

php、Node.js、Go等。 在官方网站里列一些Java的客户端,有Jedis、Redisson、Jredis、JDBC

Redis、等其中官方推荐使用Jedis和Redisson。 在企业中用的最多的就是Jedis,Jedis同样也是托管在

github上.

说白了Jedis就是使用Java操作Redis的客户端(工具包)

地址:https://github.com/xetorthio/jedis

1.环境准备
1.1引入依赖
<!--引入jedis连接依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.0</version>
</dependency>
1.2设置Linux的防火墙端口
# 查看防火墙释放运行
[root@localhost bin]# firewall-cmd --state
running
# 查看防火墙当前已经放行的端口
[root@localhost bin]# firewall-cmd --list-ports
# 设置防火墙放行redis的端口号 6379
[root@localhost bin]# firewall-cmd --zone=public --add-port=6379/tcp --permanent
success
[root@localhost bin]# firewall-cmd --list-ports
# 重启防火墙服务
[root@localhost bin]# systemctl restart firewalld.service
# 再次查看防火墙放行的端口,已经有6379端口了
[root@localhost bin]# firewall-cmd --list-ports
6379/tcp
1.3创建jedis对象
public static void main(String[] args) {
//1.创建jedis对象
//1.redis服务必须关闭防火墙 2.redis服务必须开启远程连接
Jedis jedis = new Jedis("192.168.40.4", 6379);
jedis.select(0);//选择操作的库默认0号库
//2.执行相关操作
//....
//3.释放资源
jedis.close();
}
2.操作key相关API
private Jedis jedis;
	@Before
	public void before(){
		this.jedis = new Jedis("192.168.202.205", 7000);
	}
	@After
	public void after(){
		jedis.close();
	}
	//测试key相关
	@Test
	public void testKeys(){
    	//删除一个key
		jedis.del("name");
		//删除多个key
		jedis.del("name","age");
		//判断一个key是否存在exits
		Boolean name = jedis.exists("name");
		System.out.println(name);
		//设置一个key超时时间 expire pexpire
		Long age = jedis.expire("age", 100);
		System.out.println(age);
		//获取一个key超时时间 ttl
		Long age1 = jedis.ttl("newage");
		System.out.println(age1);
		//随机获取一个key
		String s = jedis.randomKey();
		//修改key名称
		jedis.rename("age","newage");
		//查看可以对应值的类型
		String name1 = jedis.type("name");
		System.out.println(name1);
		String maps = jedis.type("maps");
		System.out.println(maps);
}
3.操作String相关API
//测试String相关
@Test
public void testString(){
	//set
	jedis.set("name","小陈");
	//get
	String s = jedis.get("name");
	System.out.println(s);
	//mset
	jedis.mset("content","好人","address","海淀区");
	//mget
	List<String> mget = jedis.mget("name", "content", "address");
	mget.forEach(v-> System.out.println("v = " + v));
	//getset
	String set = jedis.getSet("name", "小明");
	System.out.println(set);
}
4.操作List相关API
//测试List相关
@Test
public void testList(){
	//lpush
    jedis.lpush("names1","张三","王五","赵柳","win7");
	//rpush
	jedis.rpush("names1","xiaomingming");
	//获取所有数据
	List<String> names1 = jedis.lrange("names1", 0, -1);
	names1.forEach(name-> System.out.println("name = " + name));
	//获取并删除数据
	String names11 = jedis.lpop("names1");
	System.out.println(names11);
	//插入数据
	jedis.linsert("names", ListPosition.BEFORE,"123","9999999");
}
5.操作Set的相关API
//测试SET相关
@Test
public void testSet(){
    //sadd
    jedis.sadd("names","zhangsan","lisi");
    //smembers
    jedis.smembers("names");
    //sismember
    jedis.sismember("names","xiaochen");
}
5.操作ZSet相关API
//测试ZSET相关
@Test
public void testZset(){
    //zadd
    jedis.zadd("names",10,"张三");
    //zrange
    jedis.zrange("names",0,-1);
    //zcard
    jedis.zcard("names");
    //zrangeByScore
    jedis.zrangeByScore("names","0","100",0,5);
}
6、操作Hash相关API
//测试HASH相关
@Test
public void testHash(){
    //hset
    jedis.hset("maps","name","zhangsan");
    //hget
    jedis.hget("maps","name");
    //hgetall
    jedis.hgetAll("mps");
    //hkeys
    jedis.hkeys("maps");
    //hvals
    jedis.hvals("maps");
}
四、SpringBoot整合Redis

Spring Boot Data Redis 种提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是RedisTemplate的子类,两个方法基本一致,不同之处在于主要体现在操作数据类型不同,RedisTemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedisTemplate的两个泛型都是String,意味着StringRedisTemplate的key和value都只能是字符串

注意:使用RedisTemplate默认是将对象序列化到Redis中,所以放入的对象必须实现对象序列化接口

springboot2.0后已经将jedis改成了Lettuce

在RedisTemplate中定义了对5种数据结构的操作方法

  • opsForvalue():操作字符串
  • opsForList():操作列表
  • opsForSet():操作集合
  • opsForZSet():操作有序集合
  • opsForHash():操作hash
1.环境准备
1.1引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1.2配置application.yml
#Spring配置
spring:
    #Redis配置
    redis:
        database: 0 #Redis数据库索引(默认为0)
        host: 127.0.0.1 #Redis服务器地址
        port: 6379 #Redis服务器连接端口
        password: #Redis服务器连接密码(默认为空)
2.使用StringRedisTemplate和RedisTemplate
//对字符串支持比较友好,不能存储对象
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate; //存储对象
@Test
public void testRedisTemplate(){
    // 可以手动设置key的序列化规则
    red
    redisTemplate.opsForValue().set("user",new User("21","小黑",23,new Date()));
    User user = (User) redisTemplate.opsForValue().get("user");
    System.out.println(user);
    
    Set keys = redisTemplate.keys("*");
    keys.forEach(key -> System.out.println(key));
    
    Object name = redisTemplate.opsForValue().get("name");
    System.out.println(name);
    
    Object xiaohei = redisTemplate.opsForValue().get("xiaohei");
    System.out.println(xiaohei);
    
    redisTemplate.opsForValue().set("name","xxxx");
    Object name = redisTemplate.opsForValue().get("name");
    
    redisTemplate.opsForList().leftPushAll("lists","xxxx","1111");
    List lists = redisTemplate.opsForList().range("lists", 0, -1);
    lists.forEach(list-> System.out.println(list));
}

//key的绑定操作 如果日后对某一个key的操作及其频繁,可以将这个key绑定到对应redistemplate中,日后基于绑定操作都是操作这个key
//boundValueOps 用来对String值绑定key
//boundListOps 用来对List值绑定key
//boundSetOps 用来对Set值绑定key
//boundZsetOps 用来对Zset值绑定key
//boundHashOps 用来对Hash值绑定key
@Test
public void testBoundKey(){
    BoundValueOperations<String, String> nameValueOperations =
    stringRedisTemplate.boundValueOps("name");
    nameValueOperations.set("1");
    //yuew
    nameValueOperations.set("2");
    String s = nameValueOperations.get();
    System.out.println(s);
}

//hash相关操作 opsForHash
@Test
public void testHash(){
    stringRedisTemplate.opsForHash().put("maps","name","小黑");
    Object o = stringRedisTemplate.opsForHash().get("maps", "name");
    System.out.println(o);
}

//zset相关操作 opsForZSet
@Test
public void testZSet(){
    stringRedisTemplate.opsForZSet().add("zsets","小黑",10);
    Set<String> zsets = stringRedisTemplate.opsForZSet().range("zsets", 0, -1);
    zsets.forEach(value-> System.out.println(value));
}

//set相关操作 opsForSet
@Test
public void testSet(){
    stringRedisTemplate.opsForSet().add("sets","xiaosan","xiaosi","xiaowu");
    Set<String> sets = stringRedisTemplate.opsForSet().members("sets");
    sets.forEach(value-> System.out.println(value));
}

//list相关的操作opsForList
@Test
public void testList(){
    // stringRedisTemplate.opsForList().leftPushAll("lists","张三","李四","王五");
    List<String> lists = stringRedisTemplate.opsForList().range("lists", 0, -1);
    lists.forEach(key -> System.out.println(key));
}

//String相关的操作 opsForValue
@Test
public void testString(){
    //stringRedisTemplate.opsForValue().set("166","好同学");
    String s = stringRedisTemplate.opsForValue().get("166");
    System.out.println(s);
    Long size = stringRedisTemplate.opsForValue().size("166");
    System.out.println(size);
}

//key相关的操作
@Test
public void test(){
    Set<String> keys = stringRedisTemplate.keys("*");//查看所有key
    Boolean name = stringRedisTemplate.hasKey("name");//判断某个key是否存在
    stringRedisTemplate.delete("age");//根据指定key删除
    stringRedisTemplate.rename("","");//修改key的名称
    stringRedisTemplate.expire("key",10, TimeUnit.HOURS);
    //设置key超时时间 参数1:设置key名 参数2:时间 参数3:时间的单位
    stringRedisTemplate.move("",1);//移动key
}
五、综合案例

springboot + mybatis-plus + mysql + redis + aop切面实现缓存

1.导入依赖
<?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 https://maven.apache.org/xsd/maven-
4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.5.2</version>
	</parent>
	<groupId>com.example</groupId>
	<artifactId>day02-springboot-redis</artifactId>
	<version>0.0.1-SNAPSHOT</version>
    
	<properties>
        <java.version>11</java.version>
        <mysql.version>5.1.49</mysql.version>
	</properties>

    <dependencies>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        	<optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
	</dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
2.编辑配置文件
server:
	port: 8888
spring:
    datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/springboot_redis?useSSL=false
        username: root
        password: root
    redis:
   		host: 192.168.3.157
# 设置mybatis plus的日志显示查询语句
mybatis-plus:
	configuration:
		log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.beans
@Data
@TableName("province")
public class Province implements Serializable {
    //使用RedisTemplate要实现Serializable接口
    // 指定当前属性为主键id
    @TableId(type = IdType.AUTO)
    private Integer pid;
    private String pname;
}
4.dao层
@Mapper
public interface ProvinceMapper extends BaseMapper<Province> {
}
5.服务层
public interface ProvinceService extends IService<Province> {
}
@Service
public class ProvinceServiceImpl extends ServiceImpl<ProvinceMapper,Province> implements ProvinceService{
}
6.控制层
@RestController
@RequestMapping("/province")
public class ProvinceController {
    @Autowired
    private ProvinceService provinceService;
    
    @GetMapping("")
    public List<Province> findAll(){
        return provinceService.list();
    }
    
    @GetMapping("/{id}")
    public Province findById(@PathVariable("id") Integer pid){
    	return provinceService.getById(pid);
    }
    
    @GetMapping("/ids")
    public List<Province> findAllWithParam(@RequestParam("id") List<Integer> ids){
    	return provinceService.listByIds(ids);
    }
}
7.redis配置文件
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 绑定连接工厂对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        
        // 设置所有的key都以字符串方式进行序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        
        // 设置所有的value都已jdk默认的方式进行序列化
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
        return redisTemplate;
    }
}
8.AOP切面类
@Configuration
@Aspect
public class MyAspectConfig {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    
    // 这里因为用的是mybatis-plus的框架方法,因此要配置框架类表达式
    @Around("execution(* com.baomidou.mybatisplus.extension.service.IService.list())")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            // 方法执行前
            System.out.println("MyAspectConfig.around---执行前先查询redis缓存");
            BoundValueOperations<String, Object> provinceOperation = redisTemplate.boundValueOps("provinces");
            Object provinces = provinceOperation.get();
            if (provinces != null){
            	return provinces;
            }
            // 如果redis中没有数据,就从数据库查询
            Object proceed = joinPoint.proceed();
            // 方法执行后
            System.out.println("MyAspectConfig.around---执行后将数据保存到redis缓存");
            // 将从数据库查询的数据缓存到redis中
            provinceOperation.set(proceed);
            return proceed;
        } catch (Throwable e) {
            throw e;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Redis入门中,常用的命令有以下几个: 1. SET:用于设置键值对。可以将一个键设置为对应的值。 2. GET:用于获取键的值。可以根据键获取相应的值。 3. DEL:用于删除指定的键。可以删除一个或多个键。 4. EXISTS:用于检查键是否存在。可以判断一个键是否存在。 5. KEYS:用于获取所有键。可以获取当前Redis数据库中的所有键。 6. INCR:用于键的值自增。可以将键对应的值自增1。 7. DECR:用于键的值自减。可以将键对应的值自减1。 8. TTL:用于获取键的过期时间。可以获取键的剩余存活时间。 9. EXPIRE:用于设置键的过期时间。可以设置键的存活时间。 10. PERSIST:用于移除键的过期时间。可以取消键的存活时间。 11. LPUSH:用于将元素添加到列表的头部。可以将一个或多个元素添加到列表的头部。 12. RPUSH:用于将元素添加到列表的尾部。可以将一个或多个元素添加到列表的尾部。 13. LPOP:用于移除并返回列表的第一个元素。可以移除并返回列表的第一个元素。 14. RPOP:用于移除并返回列表的最后一个元素。可以移除并返回列表的最后一个元素。 15. SADD:用于向集合中添加元素。可以将一个或多个元素添加到集合中。 16. SMEMBERS:用于获取集合的所有成员。可以获取集合中的所有成员。 17. SCARD:用于获取集合的成员数量。可以获取集合中的成员数量。 18. ZADD:用于向有序集合中添加元素。可以将一个或多个元素添加到有序集合中。 19. ZRANGE:用于获取有序集合的指定范围内的元素。可以获取有序集合中指定范围内的元素。 20. ZCARD:用于获取有序集合的成员数量。可以获取有序集合中的成员数量。 以上是Redis入门常用的命令,可以帮助你开始使用Redis进行数据存储和操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Redis常用命令大集合(快速入门)](https://blog.csdn.net/yy12345_6_/article/details/124177795)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [尚硅谷Redis入门视频](https://download.csdn.net/download/wang9527007/10390271)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wq²º²²

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值